diff --git a/.hgtags b/.hgtags index ade129e0e5..40ac516690 100644 --- a/.hgtags +++ b/.hgtags @@ -158,3 +158,5 @@ b53a0576eec80614d7767ed72b40ed67aeff27c9 2.5.2-release 0000000000000000000000000000000000000000 DRTVWR-38_2.5.2-release 0000000000000000000000000000000000000000 2.5.2-release 8f16fc4647d4a97b02042094a213b1fdea5c9462 FSmerge-2.5.2 +43cb7dc1804de1a25c0b2b3f0715584af1f8b470 RLVa-1.2.2 +89532c8dfd5b6c29f1cb032665b44a74a52452e1 RLVa-1.3.0 diff --git a/doc/contributions.txt b/doc/contributions.txt index 51e3028321..ccc09243a9 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -794,6 +794,7 @@ Twisted Laws STORM-844 STORM-643 STORM-954 + STORM-1103 Vadim Bigbear VWR-2681 Vector Hastings diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index cc9edfcdea..2369fd25f2 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -883,6 +883,13 @@ std::string LLNotification::getLabel() const return (mTemplatep ? label : ""); } +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a +bool LLNotification::hasLabel() const +{ + return !mTemplatep->mLabel.empty(); +} +// [/SL:KB] + std::string LLNotification::getURL() const { if (!mTemplatep) diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 34d3537781..e6a6f5d9e7 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -507,6 +507,10 @@ public: return mTimestamp; } +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + bool hasLabel() const; +// [/SL:KB] + std::string getType() const; std::string getMessage() const; std::string getLabel() const; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 678cfc751d..d14c44213f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6426,6 +6426,17 @@ Value 305 + NotificationCanEmbedInIM + + Comment + Controls notification panel embedding in IMs (0 = default, 1 = focused, 2 = never) + Persist + 1 + Type + S32 + Value + 2 + NotificationToastLifeTime Comment @@ -9957,6 +9968,17 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 + NearbyListShowMap + + Comment + Show/hide map above nearby people list + Persist + 1 + Type + Boolean + Value + 1 + NearbyListShowIcons Comment diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 03fa970440..7b175afa08 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -77,8 +77,9 @@ #include "llwindow.h" #include "llworld.h" #include "llworldmap.h" -// [RLVa:KB] - Checked: 2010-03-07 (RLVa-1.2.0c) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvhelper.h" // [/RLVa:KB] #include "kcwlinterface.h" @@ -174,7 +175,10 @@ LLAgent::LLAgent() : mDoubleTapRunMode(DOUBLETAP_NONE), mbAlwaysRun(false), - mbRunning(false), +// mbRunning(false), +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + mbTempRun(false), +// [/RLVa:KB] mbTeleportKeepsLookAt(false), mAgentAccess(gSavedSettings), @@ -2689,7 +2693,36 @@ void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request) sendReliableMessage(); } -void LLAgent::sendWalkRun(bool running) +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i +void LLAgent::setAlwaysRun() +{ + mbAlwaysRun = (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasBehaviour(RLV_BHVR_ALWAYSRUN)); + sendWalkRun(); +} + +void LLAgent::setTempRun() +{ + mbTempRun = (!rlv_handler_t::isEnabled()) || (!gRlvHandler.hasBehaviour(RLV_BHVR_TEMPRUN)); + sendWalkRun(); +} + +void LLAgent::clearAlwaysRun() +{ + mbAlwaysRun = false; + sendWalkRun(); +} + +void LLAgent::clearTempRun() +{ + mbTempRun = false; + sendWalkRun(); +} +// [/RLVa:KB] + +//void LLAgent::sendWalkRun(bool running) +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i +void LLAgent::sendWalkRun() +// [/RLVa:KB] { LLMessageSystem* msgsys = gMessageSystem; if (msgsys) @@ -2698,7 +2731,10 @@ void LLAgent::sendWalkRun(bool running) msgsys->nextBlockFast(_PREHASH_AgentData); msgsys->addUUIDFast(_PREHASH_AgentID, getID()); msgsys->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msgsys->addBOOLFast(_PREHASH_AlwaysRun, BOOL(running) ); +// msgsys->addBOOLFast(_PREHASH_AlwaysRun, BOOL(running) ); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + msgsys->addBOOLFast(_PREHASH_AlwaysRun, BOOL(getRunning()) ); +// [/RLVa:KB] sendReliableMessage(); } } @@ -3485,7 +3521,7 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) : gRlvHandler.hasBehaviour(RLV_BHVR_TPLM) && gRlvHandler.hasBehaviour(RLV_BHVR_TPLOC) ) || ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (isAgentAvatarValid()) && (gAgentAvatarp->isSitting())) )) { - RlvUtil::notifyBlockedTeleport(); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_TELEPORT); return; } // [/RLVa:KB] @@ -3562,7 +3598,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) ( (isAgentAvatarValid()) && (gAgentAvatarp->isSitting()) && (gRlvHandler.hasBehaviourExcept(RLV_BHVR_UNSIT, gRlvHandler.getCurrentObject()))) ) { - RlvUtil::notifyBlockedTeleport(); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_TELEPORT); return; } @@ -3620,7 +3656,7 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) if ( (rlv_handler_t::isEnabled()) && (!RlvUtil::isForceTp()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) || (!gRlvHandler.canStand())) ) { - RlvUtil::notifyBlockedTeleport(); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_TELEPORT); return; } // [/RLVa:KB] diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index b5882df480..8b1422165b 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -330,19 +330,31 @@ public: DOUBLETAP_SLIDERIGHT }; - void setAlwaysRun() { mbAlwaysRun = true; } - void clearAlwaysRun() { mbAlwaysRun = false; } - void setRunning() { mbRunning = true; } - void clearRunning() { mbRunning = false; } - void sendWalkRun(bool running); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + void setAlwaysRun(); + void setTempRun(); + void clearAlwaysRun(); + void clearTempRun(); + void sendWalkRun(); + bool getTempRun() { return mbTempRun; } + bool getRunning() const { return (mbAlwaysRun) || (mbTempRun); } +// [/RLVa:KB] +// void setAlwaysRun() { mbAlwaysRun = true; } +// void clearAlwaysRun() { mbAlwaysRun = false; } +// void setRunning() { mbRunning = true; } +// void clearRunning() { mbRunning = false; } +// void sendWalkRun(bool running); bool getAlwaysRun() const { return mbAlwaysRun; } - bool getRunning() const { return mbRunning; } +// bool getRunning() const { return mbRunning; } public: LLFrameTimer mDoubleTapRunTimer; EDoubleTapRunMode mDoubleTapRunMode; private: bool mbAlwaysRun; // Should the avatar run by default rather than walk? - bool mbRunning; // Is the avatar trying to run right now? +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + bool mbTempRun; +// [/RLVa:KB] +// bool mbRunning; // Is the avatar trying to run right now? bool mbTeleportKeepsLookAt; // Try to keep look-at after teleport is complete //-------------------------------------------------------------------- diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 66f3853e79..f9bdc6c44a 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -37,8 +37,9 @@ #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" -// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "llvoavatarself.h" // [/RLVa:KB] LLAgentListener::LLAgentListener(LLAgent &agent) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 000356f8c6..cb63d961ad 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -49,8 +49,9 @@ #include "llvoavatarself.h" #include "llwearable.h" #include "llwearablelist.h" -// [RLVa:KB] - Checked: RLVa-1.2.0a (2010-03-04) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] #include @@ -945,6 +946,30 @@ const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 return LLUUID(); } +// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0f) | Added: RLVa-1.3.0f +void LLAgentWearables::getWearableItemIDs(uuid_vec_t& idItems) const +{ + for (wearableentry_map_t::const_iterator itWearableType = mWearableDatas.begin(); + itWearableType != mWearableDatas.end(); ++itWearableType) + { + getWearableItemIDs(itWearableType->first, idItems); + } +} + +void LLAgentWearables::getWearableItemIDs(LLWearableType::EType eType, uuid_vec_t& idItems) const +{ + wearableentry_map_t::const_iterator itWearableType = mWearableDatas.find(eType); + if (mWearableDatas.end() != itWearableType) + { + for (wearableentry_vec_t::const_iterator itWearable = itWearableType->second.begin(), endWearable = itWearableType->second.end(); + itWearable != endWearable; ++itWearable) + { + idItems.push_back((*itWearable)->getItemID()); + } + } +} +// [/RLVa:KB] + const LLUUID LLAgentWearables::getWearableAssetID(LLWearableType::EType type, U32 index) const { const LLWearable *wearable = getWearable(type,index); @@ -1983,9 +2008,11 @@ void LLAgentWearables::userRemoveAllAttachments() void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array) { -// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a - // RELEASE-RLVa: [SL-2.0.0] Check our callers and verify that erasing elements from the passed vector won't break random things - if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1b) | Added: RLVa-1.3.1b + static bool sInitialAttachmentsRequested = false; + + // RELEASE-RLVa: [SL-2.5.2] Check our callers and verify that erasing elements from the passed vector won't break random things + if ( (rlv_handler_t::isEnabled()) && (sInitialAttachmentsRequested) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) { // Fall-back code: everything should really already have been pruned before we get this far for (S32 idxItem = obj_item_array.count() - 1; idxItem >= 0; idxItem--) @@ -2037,8 +2064,8 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD); // Wear at the previous or default attachment point -// [RLVa:KB] - Checked: 2010-07-28 (RLVa-1.2.0i) | Added: RLVa-1.2.0i - if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1b) | Added: RLVa-1.3.1b + if ( (rlv_handler_t::isEnabled()) && (sInitialAttachmentsRequested) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) { RlvAttachmentLockWatchdog::instance().onWearAttachment(item, RLV_WEAR_ADD); } @@ -2053,6 +2080,10 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra msg->sendReliable( gAgent.getRegion()->getHost() ); } } + +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1b) | Added: RLVa-1.3.1b + sInitialAttachmentsRequested = true; +// [/RLVa:KB] } void LLAgentWearables::checkWearablesLoaded() const diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index c3134f5bdb..422d462885 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -93,6 +93,10 @@ public: // Accessors //-------------------------------------------------------------------- public: +// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + void getWearableItemIDs(uuid_vec_t& idItems) const; + void getWearableItemIDs(LLWearableType::EType eType, uuid_vec_t& idItems) const; +// [/RLVa:KB] const LLUUID getWearableItemID(LLWearableType::EType type, U32 index /*= 0*/) const; const LLUUID getWearableAssetID(LLWearableType::EType type, U32 index /*= 0*/) const; const LLWearable* getWearableFromItemID(const LLUUID& item_id) const; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e13ff84120..fd657bbeea 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -49,8 +49,10 @@ #include "llvoavatarself.h" #include "llviewerregion.h" #include "llwearablelist.h" -// [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0b) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvhelper.h" +#include "rlvlocks.h" // [/RLVa:KB] // RAII thingy to guarantee that a variable gets reset when the Setter @@ -1738,6 +1740,14 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo lldebugs << "updateAgentWearables()" << llendl; LLInventoryItem::item_array_t items; LLDynamicArray< LLWearable* > wearables; +// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + uuid_vec_t idsCurrent; LLInventoryModel::item_array_t itemsNew; + if (rlv_handler_t::isEnabled()) + { + // Collect the item UUIDs of all currently worn wearables + gAgentWearables.getWearableItemIDs(idsCurrent); + } +// [/RLVa:KB] // For each wearable type, find the wearables of that type. for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) @@ -1773,11 +1783,39 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo // [/RLVa:KB] items.put(item); wearables.put(wearable); +// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + if ( (rlv_handler_t::isEnabled()) && (gAgentWearables.areInitalWearablesLoaded()) ) + { + // Remove the wearable from current item UUIDs if currently worn and requested, otherwise mark it as a new item + uuid_vec_t::iterator itItemID = std::find(idsCurrent.begin(), idsCurrent.end(), item->getUUID()); + if (idsCurrent.end() != itItemID) + idsCurrent.erase(itItemID); + else + itemsNew.push_back(item); + } +// [/RLVa:KB] } } } } +// [RLVa:KB] - Checked: 2011-03-31 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + if ( (rlv_handler_t::isEnabled()) && (gAgentWearables.areInitalWearablesLoaded()) ) + { + // We need to report removals before additions or scripts will get confused + for (uuid_vec_t::const_iterator itItemID = idsCurrent.begin(); itItemID != idsCurrent.end(); ++itItemID) + { + const LLWearable* pWearable = gAgentWearables.getWearableFromItemID(*itItemID); + if (pWearable) + RlvBehaviourNotifyHandler::onTakeOff(pWearable->getType(), true); + } + for (S32 idxItem = 0, cntItem = itemsNew.count(); idxItem < cntItem; idxItem++) + { + RlvBehaviourNotifyHandler::onWear(itemsNew.get(idxItem)->getWearableType(), true); + } + } +// [/RLVa:KB] + if(wearables.count() > 0) { gAgentWearables.setWearableOutfit(items, wearables, !append); @@ -2129,7 +2167,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, } void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append) -//-TT Patch: ReplaceWornItemsOnly +//-TT Patch: ReplaceWornItemsOnly { wearInventoryCategory(category, copy, append, false); } @@ -2146,26 +2184,26 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, &LLAppearanceMgr::instance(), category->getUUID(), copy, append)); -//-TT Patch: ReplaceWornItemsOnly +//-TT Patch: ReplaceWornItemsOnly //category->getUUID(), copy, append, replace)); //-TT } -//-TT Patch: ReplaceWornItemsOnly +//-TT Patch: ReplaceWornItemsOnly void LLAppearanceMgr::replaceCategoryInCurrentOutfit(const LLUUID& cat_id) -{ - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - wearInventoryCategory(cat, false, true); -} +{ + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + wearInventoryCategory(cat, false, true); +} //-TT void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) -//-TT Patch: ReplaceWornItemsOnly +//-TT Patch: ReplaceWornItemsOnly { wearCategoryFinal(cat_id, copy_items, append, false); } void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append, bool replace) -//-TT +//-TT { llinfos << "starting" << llendl; diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index 56490162b1..8a74fd5d87 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -33,8 +33,9 @@ #include "llviewerinventory.h" #include "llviewerregion.h" #include "message.h" -// [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1c) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] LLAttachmentsMgr::LLAttachmentsMgr() diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index e9da51af2c..2ce74b5b25 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -73,6 +73,9 @@ #include "llviewercontrol.h" #include "llfloaterreporter.h" #include "llviewermenu.h" +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h +#include "rlvhandler.h" +// [/RLVa:KB] // static void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) @@ -196,6 +199,19 @@ void LLAvatarActions::startIM(const LLUUID& id) if (id.isNull()) return; +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStartIM(id)) ) + { + LLUUID idSession = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id); + if ( (idSession.notNull()) && (!gIMMgr->hasSession(idSession)) ) + { + make_ui_sound("UISndInvalidOp"); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTIM, LLSD().with("RECIPIENT", LLSLURL("agent", id, "completename").getSLURLString())); + return; + } + } +// [/RLVa:KB] + LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2)); } @@ -232,6 +248,20 @@ void LLAvatarActions::startCall(const LLUUID& id) { return; } + +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStartIM(id)) ) + { + LLUUID idSession = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id); + if ( (idSession.notNull()) && (!gIMMgr->hasSession(idSession)) ) + { + make_ui_sound("UISndInvalidOp"); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTIM, LLSD().with("RECIPIENT", LLSLURL("agent", id, "completename").getSLURLString())); + return; + } + } +// [/RLVa:KB] + LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_call, _1, _2)); } @@ -248,7 +278,17 @@ void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) LLDynamicArray id_array; for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) { - id_array.push_back(*it); +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + const LLUUID& idAgent = *it; + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStartIM(idAgent)) ) + { + make_ui_sound("UISndInvalidOp"); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTCONF, LLSD().with("RECIPIENT", LLSLURL("agent", idAgent, "completename").getSLURLString())); + return; + } + id_array.push_back(idAgent); +// [/RLVa:KB] +// id_array.push_back(*it); } // create the new ad hoc voice session @@ -293,7 +333,17 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids) LLDynamicArray id_array; for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) { - id_array.push_back(*it); +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + const LLUUID& idAgent = *it; + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStartIM(idAgent)) ) + { + make_ui_sound("UISndInvalidOp"); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTCONF, LLSD().with("RECIPIENT", LLSLURL("agent", idAgent, "completename").getSLURLString())); + return; + } + id_array.push_back(idAgent); +// [/RLVa:KB] +// id_array.push_back(*it); } const std::string title = LLTrans::getString("conference-title"); LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 19e5128070..1e83e25048 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -529,7 +529,10 @@ BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask, std::string avatar_name = selection->getColumn(0)->getValue().asString(); if (dest_agent_id.notNull() && dest_agent_id != gAgentID) { - if (drop) +// if (drop) +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + if ( (drop) && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.canStartIM(dest_agent_id)) ) ) +// [/RLVa:KB] { // Start up IM before give the item session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, dest_agent_id); diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index dd25e3a52f..2e5efdbeee 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -40,8 +40,9 @@ #include "llviewercontrol.h" #include "llviewerobject.h" #include "lluictrlfactory.h" -// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.2a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "llagent.h" // [/RLVa:KB] //LLFloaterInspect* LLFloaterInspect::sInstance = NULL; diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 6fff2a2865..8afd70e544 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -42,6 +42,9 @@ #include "llimfloater.h" //-TT - Patch : ShowGroupFloaters #include "llpanelgroup.h" +// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f +#include "rlvhandler.h" +// [/RLVa:KB] // // Globals @@ -128,6 +131,15 @@ void LLGroupActions::startCall(const LLUUID& group_id) return; } +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStartIM(group_id)) && (!gIMMgr->hasSession(group_id)) ) + { + make_ui_sound("UISndInvalidOp"); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTIM, LLSD().with("RECIPIENT", LLSLURL("group", group_id, "about").getSLURLString())); + return; + } +// [/RLVa:KB] + LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, true); if (session_id == LLUUID::null) { @@ -201,8 +213,12 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response) // static void LLGroupActions::leave(const LLUUID& group_id) { - if (group_id.isNull()) +// if (group_id.isNull()) +// return; +// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + if ( (group_id.isNull()) || ((gAgent.getGroupID() == group_id) && (gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP))) ) return; +// [/RLVa:KB] S32 count = gAgent.mGroups.count(); S32 i; @@ -224,6 +240,11 @@ void LLGroupActions::leave(const LLUUID& group_id) // static void LLGroupActions::activate(const LLUUID& group_id) { +// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + if (gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP)) + return; +// [/RLVa:KB] + LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ActivateGroup); msg->nextBlockFast(_PREHASH_AgentData); @@ -371,6 +392,15 @@ void LLGroupActions::startIM(const LLUUID& group_id) if (group_id.isNull()) return; +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStartIM(group_id)) && (!gIMMgr->hasSession(group_id)) ) + { + make_ui_sound("UISndInvalidOp"); + RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTIM, LLSD().with("RECIPIENT", LLSLURL("group", group_id, "about").getSLURLString())); + return; + } +// [/RLVa:KB] + LLGroupData group_data; if (gAgent.getGroupData(group_id, group_data)) { diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index e68d3e0d28..325892ae35 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -43,6 +43,9 @@ #include "llviewercontrol.h" // for gSavedSettings #include "llviewermenu.h" // for gMenuHolder #include "llvoiceclient.h" +// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f +#include "rlvhandler.h" +// [/RLVa:KB] static LLDefaultChildRegistry::Register r("group_list"); S32 LLGroupListItem::sIconWidth = 0; @@ -296,8 +299,14 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected // each group including "none" can be activated +// if (userdata.asString() == "activate") +// return gAgent.getGroupID() != selected_group_id; +// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f if (userdata.asString() == "activate") - return gAgent.getGroupID() != selected_group_id; + return (gAgent.getGroupID() != selected_group_id) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP)); + else if (userdata.asString() == "leave") + return (gAgent.getGroupID() != selected_group_id) || (!gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP)); +// [/RLVa:KB] if (userdata.asString() == "call") return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ac6577de0e..bf9cb4a29d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1,5537 +1,5559 @@ -/** - * @file llinventorybridge.cpp - * @brief Implementation of the Inventory-Folder-View-Bridge classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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 "llinventorybridge.h" - -// external projects -#include "lltransfersourceasset.h" -#include "llavatarnamecache.h" // IDEVO - -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llappearancemgr.h" -#include "llattachmentsmgr.h" -#include "llavataractions.h" -#include "llfloateropenobject.h" -#include "llfloaterreg.h" -#include "llfloaterworldmap.h" -#include "llfriendcard.h" -#include "llgesturemgr.h" -#include "llgiveinventory.h" -#include "llimfloater.h" -#include "llimview.h" -#include "llinventoryclipboard.h" -#include "llinventorydefines.h" -#include "llinventoryfunctions.h" -#include "llinventorymodel.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llinventorypanel.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewtexture.h" -#include "llselectmgr.h" -#include "llsidepanelappearance.h" -#include "llsidetray.h" -#include "lltrans.h" -#include "llviewerassettype.h" -#include "llviewerfoldertype.h" -#include "llviewermenu.h" -#include "llviewermessage.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llvoavatarself.h" -#include "llwearablelist.h" -// [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0b) -#include "rlvhandler.h" -// [/RLVa:KB] - -typedef std::pair two_uuids_t; -typedef std::list two_uuids_list_t; - -struct LLMoveInv -{ - LLUUID mObjectID; - LLUUID mCategoryID; - two_uuids_list_t mMoveList; - void (*mCallback)(S32, void*); - void* mUserData; -}; - -using namespace LLOldEvents; - -// Helpers -// bug in busy count inc/dec right now, logic is complex... do we really need it? -void inc_busy_count() -{ -// gViewerWindow->getWindow()->incBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} -void dec_busy_count() -{ -// gViewerWindow->getWindow()->decBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} - -// Function declarations -void remove_inventory_category_from_avatar(LLInventoryCategory* category); -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); -//-TT Patch: ReplaceWornItemsOnly -void wear_inventory_category_on_avatar(LLInventoryCategory* category); -//-TT -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); -bool confirm_attachment_rez(const LLSD& notification, const LLSD& response); -void teleport_via_landmark(const LLUUID& asset_id); -static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); - -// +=================================================+ -// | LLInvFVBridge | -// +=================================================+ - -LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid) : - mUUID(uuid), - mRoot(root), - mInvType(LLInventoryType::IT_NONE), - mIsLink(FALSE) -{ - mInventoryPanel = inventory->getHandle(); - const LLInventoryObject* obj = getInventoryObject(); - mIsLink = obj && obj->getIsLinkType(); -} - -const std::string& LLInvFVBridge::getName() const -{ - const LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return obj->getName(); - } - return LLStringUtil::null; -} - -const std::string& LLInvFVBridge::getDisplayName() const -{ - return getName(); -} - -// Folders have full perms -PermissionMask LLInvFVBridge::getPermissionMask() const -{ - return PERM_ALL; -} - -// virtual -LLFolderType::EType LLInvFVBridge::getPreferredType() const -{ - return LLFolderType::FT_NONE; -} - - -// Folders don't have creation dates. -time_t LLInvFVBridge::getCreationDate() const -{ - return 0; -} - -// Can be destroyed (or moved to trash) -BOOL LLInvFVBridge::isItemRemovable() const -{ - return get_is_item_removable(getInventoryModel(), mUUID); -} - -// Can be moved to another folder -BOOL LLInvFVBridge::isItemMovable() const -{ - return TRUE; -} - -BOOL LLInvFVBridge::isLink() const -{ - return mIsLink; -} - -/*virtual*/ -/** - * @brief Adds this item into clipboard storage - */ -void LLInvFVBridge::cutToClipboard() -{ - if(isItemMovable()) - { - LLInventoryClipboard::instance().cut(mUUID); - } -} -// *TODO: make sure this does the right thing -void LLInvFVBridge::showProperties() -{ - //show_item_profile(mUUID); - - // Disable old properties floater; this is replaced by the sidepanel. - /**/ - //-TT Experiment. - LLFloaterReg::showInstance("properties", mUUID); -} - -void LLInvFVBridge::removeBatch(LLDynamicArray& batch) -{ - // Deactivate gestures when moving them into Trash - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - S32 count = batch.count(); - S32 i,j; - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if (item) - { - if(LLAssetType::AT_GESTURE == item->getType()) - { - LLGestureMgr::instance().deactivateGesture(item->getUUID()); - } - } - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if (cat) - { - gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); - for (j=0; jgetType()) - { - LLGestureMgr::instance().deactivateGesture(descendent_items[j]->getUUID()); - } - } - } - } - removeBatchNoCheck(batch); -} - -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray& batch) -{ - // this method moves a bunch of items and folders to the trash. As - // per design guidelines for the inventory model, the message is - // built and the accounting is performed first. After all of that, - // we call LLInventoryModel::moveObject() to move everything - // around. - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLMessageSystem* msg = gMessageSystem; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLViewerInventoryItem* item = NULL; - uuid_vec_t move_ids; - LLInventoryModel::update_map_t update; - bool start_new_message = true; - S32 count = batch.count(); - S32 i; - - // first, hide any 'preview' floaters that correspond to the items - // being deleted. - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if(item) - { - LLPreview::hide(item->getUUID()); - } - } - - // do the inventory move to trash - - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if(item) - { - if(item->getParentUUID() == trash_id) continue; - move_ids.push_back(item->getUUID()); - --update[item->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOLFast(_PREHASH_Stamp, TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); - msg->addUUIDFast(_PREHASH_FolderID, trash_id); - msg->addString("NewName", NULL); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if(cat) - { - if(cat->getParentUUID() == trash_id) continue; - move_ids.push_back(cat->getUUID()); - --update[cat->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOL("Stamp", TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); - msg->addUUIDFast(_PREHASH_ParentID, trash_id); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - } - - // move everything. - uuid_vec_t::iterator it = move_ids.begin(); - uuid_vec_t::iterator end = move_ids.end(); - for(; it != end; ++it) - { - gInventory.moveObject((*it), trash_id); - } - - // notify inventory observers. - model->notifyObservers(); -} - -BOOL LLInvFVBridge::isClipboardPasteable() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLUUID &agent_id = gAgent.getID(); - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &item_id = objects.get(i); - - // Can't paste folders <-- why not? -// const LLInventoryCategory *cat = model->getCategory(item_id); -// if (cat) -// { -// return FALSE; -// } - -// const LLInventoryItem *item = model->getItem(item_id); - const LLViewerInventoryItem *item = model->getItem(item_id); - if (item) - { -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - // Can't copy worn objects. DEV-15183 [see P-JIRA: http://jira.secondlife.com/browse/VWR-6110] - // TODO-Catznip: [SL-2.2.0] I don't think preventing copying worn items would prevent the bug that actually occurred? -// if ( (!item->getIsLinkType()) && (get_is_item_worn(item->getUUID())) ) -// { -// return FALSE; -// } -// [/SL:KB] - - if (!item->getPermissions().allowCopyBy(agent_id)) - { -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - // We allow copy/pasting of links as long as their target is available - // (and disallow if the user is trying to paste a folder link pointing to the current folder) - if ( (!item->getIsLinkType()) || (!item->getLinkedItem()) || - ((LLAssetType::AT_LINK_FOLDER == item->getActualType()) && (item->getLinkedUUID() == mUUID)) ) - { - return FALSE; - } -// [/SL:KB] -// return FALSE; - } - } - } - return TRUE; -} - -BOOL LLInvFVBridge::isClipboardPasteableAsLink() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLInventoryItem *item = model->getItem(objects.get(i)); - if (item) - { - if (!LLAssetType::lookupCanLink(item->getActualType())) - { - return FALSE; - } - } - const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); - if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - return FALSE; - } - } - return TRUE; -} - -void hide_context_entries(LLMenuGL& menu, - const menuentry_vec_t &entries_to_show, - const menuentry_vec_t &disabled_entries, - BOOL append) // If append is TRUE, then new enabled entries -{ - const LLView::child_list_t *list = menu.getChildList(); - - // For removing double separators or leading separator. Start at true so that - // if the first element is a separator, it will not be shown. - BOOL is_previous_entry_separator = TRUE; - - for (LLView::child_list_t::const_iterator itor = list->begin(); - itor != list->end(); - ++itor) - { - LLView *menu_item = (*itor); - std::string name = menu_item->getName(); - - // descend into split menus: - LLMenuItemBranchGL* branchp = dynamic_cast(menu_item); - if ((name == "More") && branchp) - { - hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); - } - - - bool found = false; - menuentry_vec_t::const_iterator itor2; - for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) - { - if (*itor2 == name) - { - found = true; - } - } - - // Don't allow multiple separators in a row (e.g. such as if there are no items - // between two separators). - if (found) - { - const BOOL is_entry_separator = (dynamic_cast(menu_item) != NULL); - if (is_entry_separator && is_previous_entry_separator) - found = false; - is_previous_entry_separator = is_entry_separator; - } - - if (!found) - { - if (!menu_item->getLastVisible()) - { - menu_item->setVisible(FALSE); - } - menu_item->setEnabled(FALSE); - } - else - { - menu_item->setVisible(TRUE); - // A bit of a hack so we can remember that some UI element explicitly set this to be visible - // so that some other UI element from multi-select doesn't later set this invisible. - menu_item->pushVisible(TRUE); - if (append) - { - menu_item->setEnabled(TRUE); - } - for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) - { - if (*itor2 == name) - { - menu_item->setEnabled(FALSE); - } - } - } - } -} - -// Helper for commonly-used entries -void LLInvFVBridge::getClipboardEntries(bool show_asset_id, - menuentry_vec_t &items, - menuentry_vec_t &disabled_items, U32 flags) -{ - const LLInventoryObject *obj = getInventoryObject(); - - if (obj) - { - if (obj->getIsLinkType()) - { - items.push_back(std::string("Find Original")); - if (isLinkedObjectMissing()) - { - disabled_items.push_back(std::string("Find Original")); - } - } - else - { - if (LLAssetType::lookupCanLink(obj->getType())) - { - items.push_back(std::string("Find Links")); - } - items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Rename")); - } - - if (show_asset_id) - { - items.push_back(std::string("Copy Asset UUID")); - - bool is_asset_knowable = false; - - LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); - if (inv_item) - { - is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType()); - } - if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 - || (! ( isItemPermissive() || gAgent.isGodlike() ) ) - || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Copy Asset UUID")); - } - } -/* - items.push_back(std::string("Copy Separator")); - - items.push_back(std::string("Copy")); - if (!isItemCopyable()) - { - disabled_items.push_back(std::string("Copy")); - } -*/ - items.push_back(std::string("Cut")); - } - } - -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - items.push_back(std::string("Copy Separator")); - - items.push_back(std::string("Copy")); - if (!isItemCopyable()) - { - disabled_items.push_back(std::string("Copy")); - } -// [/SL:KB] - - - // Don't allow items to be pasted directly into the COF. - if (!isCOFFolder()) - { - items.push_back(std::string("Paste")); - } - if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0)) - { - disabled_items.push_back(std::string("Paste")); - } - - if (gSavedSettings.getBOOL("InventoryLinking")) - { - items.push_back(std::string("Paste As Link")); - if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste As Link")); - } - } - - items.push_back(std::string("Paste Separator")); - - addDeleteContextMenuOptions(items, disabled_items); - - // If multiple items are selected, disable properties (if it exists). - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Properties")); - } -} - -void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - - addOpenRightClickMenuOption(items); - items.push_back(std::string("Properties")); - -// [RLVa:KB] - Checked: 2010-03-01 (RLVa-1.2.0b) | Modified: RLVa-1.1.0a - if (rlv_handler_t::isEnabled()) - { - const LLInventoryObject* pItem = getInventoryObject(); - if ( (pItem) && - ( ((LLAssetType::AT_NOTECARD == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE))) || - ((LLAssetType::AT_LSL_TEXT == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT))) || - ((LLAssetType::AT_TEXTURE == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))) ) ) - { - disabled_items.push_back(std::string("Open")); - } - } -// [/RLVa:KB] - - getClipboardEntries(true, items, disabled_items, flags); - } - hide_context_entries(menu, items, disabled_items); -} - -void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items, - menuentry_vec_t &disabled_items) -{ - const LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - items.push_back(std::string("Find Original")); - if (isLinkedObjectMissing()) - { - disabled_items.push_back(std::string("Find Original")); - } - } - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - items.push_back(std::string("Restore Item")); -} - -void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, - menuentry_vec_t &disabled_items) -{ - - const LLInventoryObject *obj = getInventoryObject(); - - // Don't allow delete as a direct option from COF folder. - if (obj && obj->getIsLinkType() && isCOFFolder() && get_is_item_worn(mUUID)) - { - return; - } - - // "Remove link" and "Delete" are the same operation. - if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) - { - items.push_back(std::string("Remove Link")); - } - else - { - items.push_back(std::string("Delete")); - } - - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } -} - -void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items) -{ - const LLInventoryObject *obj = getInventoryObject(); - const BOOL is_link = (obj && obj->getIsLinkType()); - - if (is_link) - items.push_back(std::string("Open Original")); - else - items.push_back(std::string("Open")); -} - -// *TODO: remove this -BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const -{ - BOOL rv = FALSE; - - const LLInventoryObject* obj = getInventoryObject(); - - if(obj) - { - *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); - if(*type == DAD_NONE) - { - return FALSE; - } - - *id = obj->getUUID(); - //object_ids.put(obj->getUUID()); - - if (*type == DAD_CATEGORY) - { - LLInventoryModelBackgroundFetch::instance().start(obj->getUUID()); - } - - rv = TRUE; - } - - return rv; -} - -LLInventoryObject* LLInvFVBridge::getInventoryObject() const -{ - LLInventoryObject* obj = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - obj = (LLInventoryObject*)model->getObject(mUUID); - } - return obj; -} - -LLInventoryModel* LLInvFVBridge::getInventoryModel() const -{ - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - return panel ? panel->getModel() : NULL; -} - -BOOL LLInvFVBridge::isItemInTrash() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return model->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLInvFVBridge::isLinkedObjectInTrash() const -{ - if (isItemInTrash()) return TRUE; - - const LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); - } - return FALSE; -} - -BOOL LLInvFVBridge::isLinkedObjectMissing() const -{ - const LLInventoryObject *obj = getInventoryObject(); - if (!obj) - { - return TRUE; - } - if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType())) - { - return TRUE; - } - return FALSE; -} - -BOOL LLInvFVBridge::isAgentInventory() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -BOOL LLInvFVBridge::isCOFFolder() const -{ - return LLAppearanceMgr::instance().getIsInCOF(mUUID); -} - -BOOL LLInvFVBridge::isItemPermissive() const -{ - return FALSE; -} - -// static -void LLInvFVBridge::changeItemParent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent_id, - BOOL restamp) -{ - change_item_parent(model, item, new_parent_id, restamp); -} - -// static -void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent_id, - BOOL restamp) -{ - change_category_parent(model, cat, new_parent_id, restamp); -} - -LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - U32 flags) -{ - LLInvFVBridge* new_listener = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLTextureBridge(inventory, root, uuid, inv_type); - break; - - case LLAssetType::AT_SOUND: - if(!(inv_type == LLInventoryType::IT_SOUND)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLSoundBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_LANDMARK: - if(!(inv_type == LLInventoryType::IT_LANDMARK)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLandmarkBridge(inventory, root, uuid, flags); - break; - - case LLAssetType::AT_CALLINGCARD: - if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLCallingCardBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_SCRIPT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLItemBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_OBJECT: - if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLObjectBridge(inventory, root, uuid, inv_type, flags); - break; - - case LLAssetType::AT_NOTECARD: - if(!(inv_type == LLInventoryType::IT_NOTECARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLNotecardBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_ANIMATION: - if(!(inv_type == LLInventoryType::IT_ANIMATION)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLAnimationBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_GESTURE: - if(!(inv_type == LLInventoryType::IT_GESTURE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLGestureBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_LSL_TEXT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLSLTextBridge(inventory, root, uuid); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - if(!(inv_type == LLInventoryType::IT_WEARABLE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, (LLWearableType::EType)flags); - break; - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // Create a link folder handler instead. - new_listener = new LLLinkFolderBridge(inventory, root, uuid); - break; - } - new_listener = new LLFolderBridge(inventory, root, uuid); - break; - case LLAssetType::AT_LINK: - case LLAssetType::AT_LINK_FOLDER: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, root, uuid); - break; - default: - llinfos << "Unhandled asset type (llassetstorage.h): " - << (S32)asset_type << llendl; - break; - } - - if (new_listener) - { - new_listener->mInvType = inv_type; - } - - return new_listener; -} - -void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) -{ - LLInventoryCategory* cat = model->getCategory(uuid); - if (cat) - { - model->purgeDescendentsOf(uuid); - model->notifyObservers(); - } - LLInventoryObject* obj = model->getObject(uuid); - if (obj) - { - model->purgeObject(uuid); - model->notifyObservers(); - } -} - -BOOL LLInvFVBridge::canShare() const -{ - if (!isAgentInventory()) return FALSE; - - const LLInventoryModel* model = getInventoryModel(); - if (!model) return FALSE; - - const LLViewerInventoryItem *item = model->getItem(mUUID); - if (item) - { - if (!LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) - return FALSE; - return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item); - } - - // Categories can be given. - if (model->getCategory(mUUID)) return TRUE; - - return FALSE; -} - -// +=================================================+ -// | InventoryFVBridgeBuilder | -// +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - U32 flags /* = 0x00 */) const -{ - return LLInvFVBridge::createBridge(asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); -} - -// +=================================================+ -// | LLItemBridge | -// +=================================================+ - -void LLItemBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(); - } - - if ("open" == action || "open_original" == action) - { - openItem(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restoreToWorld" == action) - { - restoreToWorld(); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } - else if ("copy_uuid" == action) - { - // Single item only - LLViewerInventoryItem* item = static_cast(getItem()); - if(!item) return; - LLUUID asset_id = item->getProtectedAssetUUID(); - std::string buffer; - asset_id.toString(buffer); - - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("cut" == action) - { - cutToClipboard(); - return; - } - else if ("paste" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteLinkFromClipboard(); - return; - } -} - -void LLItemBridge::selectItem() -{ - LLViewerInventoryItem* item = static_cast(getItem()); - if(item && !item->isFinished()) - { - item->fetchFromServer(); - } -} - -void LLItemBridge::restoreItem() -{ - LLViewerInventoryItem* item = static_cast(getItem()); - if(item) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); - // do not restamp on restore. - LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); - } -} - -void LLItemBridge::restoreToWorld() -{ - //Similar functionality to the drag and drop rez logic - bool remove_from_inventory = false; - - LLViewerInventoryItem* itemp = static_cast(getItem()); - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("RezRestoreToWorld"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_InventoryData); - itemp->packMessage(msg); - msg->sendReliable(gAgent.getRegion()->getHost()); - - //remove local inventory copy, sim will deal with permissions and removing the item - //from the actual inventory if its a no-copy etc - if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - remove_from_inventory = true; - } - - // Check if it's in the trash. (again similar to the normal rez logic) - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) - { - remove_from_inventory = true; - } - } - - if(remove_from_inventory) - { - gInventory.deleteObject(itemp->getUUID()); - gInventory.notifyObservers(); - } -} - -void LLItemBridge::gotoItem() -{ - LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); - if (active_panel) - { - active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); - } - } -} - -LLUIImagePtr LLItemBridge::getIcon() const -{ - LLInventoryObject *obj = getInventoryObject(); - if (obj) - { - return LLInventoryIcon::getIcon(obj->getType(), - LLInventoryType::IT_NONE, - mIsLink); - } - - return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT); -} - -PermissionMask LLItemBridge::getPermissionMask() const -{ - LLViewerInventoryItem* item = getItem(); - PermissionMask perm_mask = 0; - if (item) perm_mask = item->getPermissionMask(); - return perm_mask; -} - -const std::string& LLItemBridge::getDisplayName() const -{ - if(mDisplayName.empty()) - { - buildDisplayName(getItem(), mDisplayName); - } - return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) -{ - if(item) - { - name.assign(item->getName()); - } - else - { - name.assign(LLStringUtil::null); - } -} - -LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - const LLViewerInventoryItem* item = getItem(); - - if (get_is_item_worn(mUUID)) - { - // llinfos << "BOLD" << llendl; - font |= LLFontGL::BOLD; - } - else if(item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - - return (LLFontGL::StyleFlags)font; -} - -std::string LLItemBridge::getLabelSuffix() const -{ - // String table is loaded before login screen and inventory items are - // loaded after login, so LLTrans should be ready. - static std::string NO_COPY =LLTrans::getString("no_copy"); - static std::string NO_MOD = LLTrans::getString("no_modify"); - static std::string NO_XFER = LLTrans::getString("no_transfer"); - static std::string LINK = LLTrans::getString("link"); - static std::string BROKEN_LINK = LLTrans::getString("broken_link"); - std::string suffix; - LLInventoryItem* item = getItem(); - if(item) - { - // it's a bit confusing to put nocopy/nomod/etc on calling cards. - if(LLAssetType::AT_CALLINGCARD != item->getType() - && item->getPermissions().getOwner() == gAgent.getID()) - { - BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); - if (broken_link) return BROKEN_LINK; - - BOOL link = item->getIsLinkType(); - if (link) return LINK; - - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - if (!copy) - { - suffix += NO_COPY; - } - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - if (!mod) - { - suffix += NO_MOD; - } - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - if (!xfer) - { - suffix += NO_XFER; - } - } - } - return suffix; -} - -time_t LLItemBridge::getCreationDate() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - return item->getCreationDate(); - } - return 0; -} - - -BOOL LLItemBridge::isItemRenameable() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // (For now) Don't allow calling card rename since that may confuse users as to - // what the calling card points to. - if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) - { - return FALSE; - } - - if (!item->isFinished()) // EXT-8662 - { - return FALSE; - } - - return (item->getPermissions().allowModifyBy(gAgent.getID())); - } - return FALSE; -} - -BOOL LLItemBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - - -BOOL LLItemBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - - - // move it to the trash - LLPreview::hide(mUUID, TRUE); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLViewerInventoryItem* item = getItem(); - if (!item) return FALSE; - - // Already in trash - if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE; - - LLNotification::Params params("ConfirmItemDeleteHasLinks"); - params.functor.function(boost::bind(&LLItemBridge::confirmRemoveItem, this, _1, _2)); - - // Check if this item has any links. If generic inventory linking is enabled, - // we can't do this check because we may have items in a folder somewhere that is - // not yet in memory, so we don't want false negatives. (If disabled, then we - // know we only have links in the Outfits folder which we explicitly fetch.) -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-06-01 (Catznip-2.2.0a) | Added: Catznip-2.0.1a - // Users move folders around and reuse links that way... if we know something has links then it's just bad not to warn them :| -// [/SL:KB] -// if (!gSavedSettings.getBOOL("InventoryLinking")) - { - if (!item->getIsLinkType()) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLLinkedItemIDMatches is_linked_item_match(mUUID); - gInventory.collectDescendentsIf(gInventory.getRootFolderID(), - cat_array, - item_array, - LLInventoryModel::INCLUDE_TRASH, - is_linked_item_match); - - const U32 num_links = cat_array.size() + item_array.size(); - if (num_links > 0) - { - // Warn if the user is will break any links when deleting this item. - LLNotifications::instance().add(params); - return FALSE; - } - } - } - - LLNotifications::instance().forceResponse(params, 0); - return TRUE; -} - -BOOL LLItemBridge::confirmRemoveItem(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return FALSE; - - LLInventoryModel* model = getInventoryModel(); - if (!model) return FALSE; - - LLViewerInventoryItem* item = getItem(); - if (!item) return FALSE; - - const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - // if item is not already in trash - if(item && !model->isObjectDescendentOf(mUUID, trash_id)) - { - // move to trash, and restamp - LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); - // delete was successful - return TRUE; - } - return FALSE; -} - -BOOL LLItemBridge::isItemCopyable() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { -/* - // Can't copy worn objects. DEV-15183 - if(get_is_item_worn(mUUID)) - { - return FALSE; - } - -*/ - -// // You can never copy a link. -// if (item->getIsLinkType()) -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - // We'll allow copying a link if: - // - its target is available - // - it doesn't point to another link [see LLViewerInventoryItem::getLinkedItem() which returns NULL in that case] - if ( (item->getIsLinkType()) && (!item->getLinkedItem()) ) -// [/SL:KB] - { - return FALSE; - } - - // All items can be copied in god mode since you can - // at least paste-as-link the item, though you - // still may not be able paste the item. -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - // User can copy the item if: - // - the item (or its target in the case of a link) is "copy" - // - and/or if the item (or its target in the case of a link) has a linkable asset type - // NOTE: we do *not* want to return TRUE on everything like LL seems to do in SL-2.1.0 because not all types are "linkable" - return (item->getPermissions().allowCopyBy(gAgent.getID())) || (LLAssetType::lookupCanLink(item->getType())); -// [/SL:KB] -// return TRUE; - // return (item->getPermissions().allowCopyBy(gAgent.getID())); - } - return FALSE; -} - -BOOL LLItemBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -LLViewerInventoryItem* LLItemBridge::getItem() const -{ - LLViewerInventoryItem* item = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - item = (LLViewerInventoryItem*)model->getItem(mUUID); - } - return item; -} - -BOOL LLItemBridge::isItemPermissive() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - return item->getIsFullPerm(); - } - return FALSE; -} - -bool LLItemBridge::isAddAction(std::string action) const -{ - return ("wear" == action || "attach" == action || "activate" == action); -} - -bool LLItemBridge::isRemoveAction(std::string action) const -{ - return ("take_off" == action || "detach" == action || "deactivate" == action); -} - -// +=================================================+ -// | LLFolderBridge | -// +=================================================+ - -LLHandle LLFolderBridge::sSelf; - -// Can be moved to another folder -BOOL LLFolderBridge::isItemMovable() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { -// return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0b) | Added: RLVa-1.3.0b - return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())) && - ((!rlv_handler_t::isEnabled()) || (!RlvFolderLocks::instance().isLockedFolder(obj->getUUID(), RLV_LOCK_ANY))); -// [/RLVa:KB] - } - return FALSE; -} - -void LLFolderBridge::selectItem() -{ -} - - -// Iterate through a folder's children to determine if -// all the children are removable. -class LLIsItemRemovable : public LLFolderViewFunctor -{ -public: - LLIsItemRemovable() : mPassed(TRUE) {} - virtual void doFolder(LLFolderViewFolder* folder) - { - mPassed &= folder->getListener()->isItemRemovable(); - } - virtual void doItem(LLFolderViewItem* item) - { - mPassed &= item->getListener()->isItemRemovable(); - } - BOOL mPassed; -}; - -// Can be destroyed (or moved to trash) -BOOL LLFolderBridge::isItemRemovable() const -{ - if (!get_is_category_removable(getInventoryModel(), mUUID)) - { - return FALSE; - } - - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewFolder* folderp = dynamic_cast(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); - if (folderp) - { - LLIsItemRemovable folder_test; - folderp->applyFunctorToChildren(folder_test); - if (!folder_test.mPassed) - { - return FALSE; - } - } - - return TRUE; -} - -BOOL LLFolderBridge::isUpToDate() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - - return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; -} - -BOOL LLFolderBridge::isItemCopyable() const -{ - if (gSavedSettings.getBOOL("InventoryLinking")) - { - // Can copy folders to paste-as-link, but not for straight paste. - return TRUE; - } - return FALSE; -} - -BOOL LLFolderBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -BOOL LLFolderBridge::isClipboardPasteable() const -{ - if ( ! LLInvFVBridge::isClipboardPasteable() ) - return FALSE; - - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) - { - LLInventoryModel* model = getInventoryModel(); - if ( !model ) - { - return FALSE; - } - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - const LLViewerInventoryCategory *current_cat = getCategory(); - - // Search for the direct descendent of current Friends subfolder among all pasted items, - // and return false if is found. - for(S32 i = objects.count() - 1; i >= 0; --i) - { - const LLUUID &obj_id = objects.get(i); - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - - } - return TRUE; -} - -BOOL LLFolderBridge::isClipboardPasteableAsLink() const -{ - // Check normal paste-as-link permissions - if (!LLInvFVBridge::isClipboardPasteableAsLink()) - { - return FALSE; - } - - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLViewerInventoryCategory *current_cat = getCategory(); - if (current_cat) - { - const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); - const LLUUID ¤t_cat_id = current_cat->getUUID(); - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &obj_id = objects.get(i); - const LLInventoryCategory *cat = model->getCategory(obj_id); - if (cat) - { - const LLUUID &cat_id = cat->getUUID(); - // Don't allow recursive pasting - if ((cat_id == current_cat_id) || - model->isObjectDescendentOf(current_cat_id, cat_id)) - { - return FALSE; - } - } - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( is_in_friend_folder ) - { - // If object is direct descendent of current Friends subfolder than return false. - // Note: We can't use 'const LLInventoryCategory *cat', because it may be null - // in case type of obj_id is LLInventoryItem. - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - } - } - return TRUE; - -} - -BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) -{ - - LLInventoryModel* model = getInventoryModel(); - - if (!inv_cat) return FALSE; // shouldn't happen, but in case item is incorrectly parented in which case inv_cat will be NULL - if (!model) return FALSE; - if (!isAgentAvatarValid()) return FALSE; - if (!isAgentInventory()) return FALSE; // cannot drag categories into library - - - // check to make sure source is agent inventory, and is represented there. - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) - && (LLToolDragAndDrop::SOURCE_AGENT == source); - - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - - BOOL accept = FALSE; - if (is_agent_inventory) - { - const LLUUID &cat_id = inv_cat->getUUID(); - const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - - const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); - const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); - - //-------------------------------------------------------------------------------- - // Determine if folder can be moved. - // - - BOOL is_movable = TRUE; - if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) - is_movable = FALSE; - if (move_is_into_outfit) - is_movable = FALSE; - if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) - is_movable = FALSE; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); - for (S32 i=0; i < descendent_categories.count(); ++i) - { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - // Can't move "special folders" (e.g. Textures Folder). - is_movable = FALSE; - break; - } - } - if (move_is_into_trash) - { - for (S32 i=0; i < descendent_items.count(); ++i) - { - LLInventoryItem* item = descendent_items[i]; - if (get_is_item_worn(item->getUUID())) - { - is_movable = FALSE; - break; // It's generally movable, but not into the trash. - } - } - } - if (move_is_into_landmarks) - { - for (S32 i=0; i < descendent_items.count(); ++i) - { - LLViewerInventoryItem* item = descendent_items[i]; - - // Don't move anything except landmarks and categories into Landmarks folder. - // We use getType() instead of getActua;Type() to allow links to landmarks and folders. - if (LLAssetType::AT_LANDMARK != item->getType() && LLAssetType::AT_CATEGORY != item->getType()) - { - is_movable = FALSE; - break; // It's generally movable, but not into Landmarks. - } - } - } - - // - //-------------------------------------------------------------------------------- - - accept = is_movable - && (mUUID != cat_id) // Can't move a folder into itself - && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing - && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity - if (accept && drop) - { - // Look for any gestures and deactivate them - if (move_is_into_trash) - { - for (S32 i=0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureMgr::instance().isGestureActive(item->getUUID())) - { - LLGestureMgr::instance().deactivateGesture(item->getUUID()); - } - } - } - // if target is an outfit or current outfit folder we use link - if (move_is_into_current_outfit || move_is_into_outfit) - { - if (inv_cat->getPreferredType() == LLFolderType::FT_NONE) - { - if (move_is_into_current_outfit) - { - // traverse category and add all contents to currently worn. - BOOL append = true; - LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append); - } - else - { - // Recursively create links in target outfit. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); - LLAppearanceMgr::instance().linkAll(mUUID,items,NULL); - } - } - else - { -#if SUPPORT_ENSEMBLES - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceMgr::instance().addEnsembleLink(inv_cat); - } - else - { - LLPointer cb = NULL; - const std::string empty_description = ""; - link_inventory_item( - gAgent.getID(), - inv_cat->getUUID(), - mUUID, - inv_cat->getName(), - empty_description, - LLAssetType::AT_LINK_FOLDER, - cb); - } -#endif - } - } - else - { - - // Reparent the folder and restamp children if it's moving - // into trash. - LLInvFVBridge::changeCategoryParent( - model, - (LLViewerInventoryCategory*)inv_cat, - mUUID, - move_is_into_trash); - } - } - } - else if (LLToolDragAndDrop::SOURCE_WORLD == source) - { - // content category has same ID as object itself - LLUUID object_id = inv_cat->getUUID(); - LLUUID category_id = mUUID; - accept = move_inv_category_world_to_agent(object_id, category_id, drop); - } - else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) - { - // Accept folders that contain complete outfits. - accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID()); - - if (accept && drop) - { - LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, true, false); - } - } - - return accept; -} - -void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) -{ - const char* dialog = NULL; - if (object->flagScripted()) - { - dialog = "MoveInventoryFromScriptedObject"; - } - else - { - dialog = "MoveInventoryFromObject"; - } - LLNotificationsUtil::add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); -} - -// Move/copy all inventory items from the Contents folder of an in-world -// object to the agent's inventory, inside a given category. -BOOL move_inv_category_world_to_agent(const LLUUID& object_id, - const LLUUID& category_id, - BOOL drop, - void (*callback)(S32, void*), - void* user_data) -{ - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - // content category has same ID as object itself - LLViewerObject* object = gObjectList.findObject(object_id); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // this folder is coming from an object, as there is only one folder in an object, the root, - // we need to collect the entire contents and handle them as a group - LLInventoryObject::object_list_t inventory_objects; - object->getInventoryContents(inventory_objects); - - if (inventory_objects.empty()) - { - llinfos << "Object contents not found for drop." << llendl; - return FALSE; - } - - BOOL accept = TRUE; - BOOL is_move = FALSE; - - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLInventoryObject::object_list_t::iterator it = inventory_objects.begin(); - LLInventoryObject::object_list_t::iterator end = inventory_objects.end(); - for ( ; it != end; ++it) - { - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - else - { - accept = FALSE; - break; - } - } - - if(drop && accept) - { - it = inventory_objects.begin(); - LLInventoryObject::object_list_t::iterator first_it = inventory_objects.begin(); - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = object_id; - move_inv->mCategoryID = category_id; - move_inv->mCallback = callback; - move_inv->mUserData = user_data; - - for ( ; it != end; ++it) - { - two_uuids_t two(category_id, (*it)->getUUID()); - move_inv->mMoveList.push_back(two); - } - - if(is_move) - { - // Callback called from within here. - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - return accept; -} - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver -{ -public: - LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : - LLInventoryFetchItemsObserver(ids), - mCopyItems(false) - { }; - LLRightClickInventoryFetchObserver(const uuid_vec_t& ids, - const LLUUID& cat_id, - bool copy_items) : - LLInventoryFetchItemsObserver(ids), - mCatID(cat_id), - mCopyItems(copy_items) - { }; - virtual void done() - { - // we've downloaded all the items, so repaint the dialog - LLFolderBridge::staticFolderOptionsMenu(); - - gInventory.removeObserver(this); - delete this; - } - - -protected: - LLUUID mCatID; - bool mCopyItems; - -}; - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: - LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids, - bool copy_items) : - LLInventoryFetchDescendentsObserver(ids), - mCopyItems(copy_items) - {} - ~LLRightClickInventoryFetchDescendentsObserver() {} - virtual void done(); -protected: - bool mCopyItems; -}; - -void LLRightClickInventoryFetchDescendentsObserver::done() -{ - // Avoid passing a NULL-ref as mCompleteFolders.front() down to - // gInventory.collectDescendents() - if( mComplete.empty() ) - { - llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } - - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mComplete.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.count(); -#if 0 // HACK/TODO: Why? - // This early causes a giant menu to get produced, and doesn't seem to be needed. - if(!count) - { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() - << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } -#endif - - uuid_vec_t ids; - for(S32 i = 0; i < count; ++i) - { - ids.push_back(item_array.get(i)->getUUID()); - } - - LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems); - - // clean up, and remove this as an observer since the call to the - // outfit could notify observers and throw us into an infinite - // loop. - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - - // increment busy count and either tell the inventory to check & - // call done, or add this object to the inventory for observation. - inc_busy_count(); - - // do the fetch - outfit->startFetch(); - outfit->done(); //Not interested in waiting and this will be right 99% of the time. -//Uncomment the following code for laggy Inventory UI. -/* if(outfit->isFinished()) - { - // everything is already here - call done. - outfit->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfit); - }*/ -} - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryWearObserver -// -// Observer for "copy and wear" operation to support knowing -// when the all of the contents have been added to inventory. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryCopyAndWearObserver : public LLInventoryObserver -{ -public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) : - mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} - virtual ~LLInventoryCopyAndWearObserver() {} - virtual void changed(U32 mask); - -protected: - LLUUID mCatID; - int mContentsCount; - BOOL mFolderAdded; -}; - - - -void LLInventoryCopyAndWearObserver::changed(U32 mask) -{ - if((mask & (LLInventoryObserver::ADD)) != 0) - { - if (!mFolderAdded) - { - const std::set& changed_items = gInventory.getChangedIDs(); - - std::set::const_iterator id_it = changed_items.begin(); - std::set::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) - { - if ((*id_it) == mCatID) - { - mFolderAdded = TRUE; - break; - } - } - } - - if (mFolderAdded) - { - LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - - if (NULL == category) - { - llwarns << "gInventory.getCategory(" << mCatID - << ") was NULL" << llendl; - } - else - { - if (category->getDescendentCount() == - mContentsCount) - { - gInventory.removeObserver(this); - LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, FALSE); - delete this; - } - } - } - - } -} - - - -void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ("open" == action) - { - LLFolderViewFolder *f = dynamic_cast(mRoot->getItemByID(mUUID)); - if (f) - { - f->setOpen(TRUE); - } - - return; - } - else if ("paste" == action) - { - pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - pasteLinkFromClipboard(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("replaceoutfit" == action) - { - modifyOutfit(FALSE); - return; - } -#if SUPPORT_ENSEMBLES - else if ("wearasensemble" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - LLAppearanceMgr::instance().addEnsembleLink(cat,true); - return; - } -#endif - else if ("addtooutfit" == action) - { - modifyOutfit(TRUE); - return; - } -//-TT Patch: ReplaceWornItemsOnly - else if ("replaceitems" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - gInventory.wearItemsOnAvatar(cat); - // modifyOutfit(TRUE, TRUE); - return; - } -//-TT - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("cut" == action) - { - cutToClipboard(); - return; - } - else if ("removefromoutfit" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - remove_inventory_category_from_avatar ( cat ); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } -#ifndef LL_RELEASE_FOR_DOWNLOAD - else if ("delete_system_folder" == action) - { - removeSystemFolder(); - } -#endif -} - -void LLFolderBridge::openItem() -{ - lldebugs << "LLFolderBridge::openItem()" << llendl; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - if(mUUID.isNull()) return; - bool fetching_inventory = model->fetchDescendentsOf(mUUID); - // Only change folder type if we have the folder contents. - if (!fetching_inventory) - { - // Disabling this for now, it's causing crash when new items are added to folders - // since folder type may change before new item item has finished processing. - // determineFolderType(); - } -} - -void LLFolderBridge::closeItem() -{ - determineFolderType(); -} - -void LLFolderBridge::determineFolderType() -{ - if (isUpToDate()) - { - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryCategory* category = model->getCategory(mUUID); - if (category) - { - category->determineFolderType(); - } - } -} - -BOOL LLFolderBridge::isItemRenameable() const -{ - return get_is_category_renameable(getInventoryModel(), mUUID); -} - -void LLFolderBridge::restoreItem() -{ - LLViewerInventoryCategory* cat; - cat = (LLViewerInventoryCategory*)getCategory(); - if(cat) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); - // do not restamp children on restore - LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); - } -} - -LLFolderType::EType LLFolderBridge::getPreferredType() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - - return preferred_type; -} - -// Icons for folders are based on the preferred type -LLUIImagePtr LLFolderBridge::getIcon() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - return getIcon(preferred_type); -} - -// static -LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) -{ - return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); -} - -LLUIImagePtr LLFolderBridge::getOpenIcon() const -{ - return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); - -} - -BOOL LLFolderBridge::renameItem(const std::string& new_name) -{ - rename_category(getInventoryModel(), mUUID, new_name); - - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -BOOL LLFolderBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - const LLViewerInventoryCategory *cat = getCategory(); - - LLSD payload; - LLSD args; - args["FOLDERNAME"] = cat->getName(); - - LLNotification::Params params("ConfirmDeleteProtectedCategory"); - params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); - LLNotifications::instance().forceResponse(params, 0); - return TRUE; -} - - -BOOL LLFolderBridge::removeSystemFolder() -{ - const LLViewerInventoryCategory *cat = getCategory(); - if (!LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - return FALSE; - } - - LLSD payload; - LLSD args; - args["FOLDERNAME"] = cat->getName(); - - LLNotification::Params params("ConfirmDeleteProtectedCategory"); - params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); - { - LLNotifications::instance().add(params); - } - return TRUE; -} - -bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - - // if they choose delete, do it. Otherwise, don't do anything - if(option == 0) - { - // move it to the trash - LLPreview::hide(mUUID); - remove_category(getInventoryModel(), mUUID); - return TRUE; - } - return FALSE; -} - -void LLFolderBridge::pasteFromClipboard() -{ - LLInventoryModel* model = getInventoryModel(); - if(model && isClipboardPasteable()) - { - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - - const LLUUID parent_id(mUUID); - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - for (LLDynamicArray::const_iterator iter = objects.begin(); - iter != objects.end(); - ++iter) - { - const LLUUID& item_id = (*iter); - LLInventoryItem *item = model->getItem(item_id); - if (item) - { - if (move_is_into_current_outfit || move_is_into_outfit) - { - if (can_move_to_outfit(item, move_is_into_current_outfit)) - { - dropToOutfit(item, move_is_into_current_outfit); - } - } - else if(LLInventoryClipboard::instance().isCutMode()) - { - // move_inventory_item() is not enough, - //we have to update inventory locally too - LLViewerInventoryItem* viitem = dynamic_cast(item); - llassert(viitem); - if (viitem) - { - changeItemParent(model, viitem, parent_id, FALSE); - } - } - else - { -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - if (item->getPermissions().allowCopyBy(gAgent.getID())) - { -// [/SL:KB] - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - parent_id, - std::string(), - LLPointer(NULL)); -// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a - } - else if (LLAssetType::lookupIsLinkType(item->getActualType())) - { - link_inventory_item( - gAgent.getID(), - item->getLinkedUUID(), - parent_id, - item->getName(), - item->getDescription(), - item->getActualType(), - LLPointer(NULL)); - } -// [/SL:KB] - } - } - - LLInventoryCategory *cat = model->getCategory(item_id); - if (cat) - { - if (move_is_into_current_outfit || move_is_into_outfit) - { - // do something clever to add folder to outfit - } - else if(LLInventoryClipboard::instance().isCutMode()) - { - // move_inventory_item() is not enough, - //we have to update inventory locally too - LLViewerInventoryCategory* vicat = dynamic_cast(cat); - llassert(vicat); - if (vicat) - { - changeCategoryParent(model, vicat, parent_id, FALSE); - } - } - else - { - // implemement copy_inventory_category - } - } - - } - } -} - -void LLFolderBridge::pasteLinkFromClipboard() -{ - LLInventoryModel* model = getInventoryModel(); - if(model) - { - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - - const LLUUID parent_id(mUUID); - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - for (LLDynamicArray::const_iterator iter = objects.begin(); - iter != objects.end(); - ++iter) - { - const LLUUID &object_id = (*iter); - if (move_is_into_current_outfit || move_is_into_outfit) - { - LLInventoryItem *item = model->getItem(object_id); - if (item && can_move_to_outfit(item, move_is_into_current_outfit)) - { - dropToOutfit(item, move_is_into_current_outfit); - } - } - else if (LLInventoryCategory *cat = model->getCategory(object_id)) - { - const std::string empty_description = ""; - link_inventory_item( - gAgent.getID(), - cat->getUUID(), - parent_id, - cat->getName(), - empty_description, - LLAssetType::AT_LINK_FOLDER, - LLPointer(NULL)); - } - else if (LLInventoryItem *item = model->getItem(object_id)) - { - link_inventory_item( - gAgent.getID(), - item->getLinkedUUID(), - parent_id, - item->getName(), - item->getDescription(), - LLAssetType::AT_LINK, - LLPointer(NULL)); - } - } - } -} - -void LLFolderBridge::staticFolderOptionsMenu() -{ - LLFolderBridge* selfp = sSelf.get(); - if (selfp) - { - selfp->folderOptionsMenu(); - } -} - -void LLFolderBridge::folderOptionsMenu() -{ - menuentry_vec_t disabled_items; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - const LLInventoryCategory* category = model->getCategory(mUUID); - if(!category) return; - - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - if (trash_id == mUUID) return; - if (isItemInTrash()) return; - if (!isAgentInventory()) return; - - LLFolderType::EType type = category->getPreferredType(); - const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); - // BAP change once we're no longer treating regular categories as ensembles. - const bool is_ensemble = (type == LLFolderType::FT_NONE || - LLFolderType::lookupIsEnsembleType(type)); -// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.5.0a) | Added: Catznip-2.4.0e - const bool is_outfit = (type == LLFolderType::FT_OUTFIT); -// [/SL:KB] - - // Only enable calling-card related options for non-system folders. - if (!is_system_folder) - { - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) - { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); - } - } - -#ifndef LL_RELEASE_FOR_DOWNLOAD - if (LLFolderType::lookupIsProtectedType(type)) - { - mItems.push_back(std::string("Delete System Folder")); - } -#endif - - // wearables related functionality for folders. - //is_wearable - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (mWearables || - checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mItems.push_back(std::string("Folder Wearables Separator")); - - // Only enable add/replace outfit for non-system folders. - if (!is_system_folder) - { - // Adding an outfit onto another (versus replacing) doesn't make sense. - if (type != LLFolderType::FT_OUTFIT) - { - mItems.push_back(std::string("Add To Outfit")); -//-TT Patch: ReplaceWornItemsOnly - mItems.push_back(std::string("Wear Items")); -//-TT - } - mItems.push_back(std::string("Replace Outfit")); - } - if (is_ensemble) - { - mItems.push_back(std::string("Wear As Ensemble")); - } - mItems.push_back(std::string("Remove From Outfit")); - if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) - { - disabled_items.push_back(std::string("Remove From Outfit")); - } -// if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) -// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.5.0a) | Added: Catznip-2.4.0e - if ( ((is_outfit) && (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))) || - ((!is_outfit) && (gAgentWearables.isCOFChangeInProgress())) ) -// [/SL:KB] - { - disabled_items.push_back(std::string("Replace Outfit")); - } - mItems.push_back(std::string("Outfit Separator")); - } - LLMenuGL* menup = dynamic_cast(mMenu.get()); - if (menup) - { - hide_context_entries(*menup, mItems, disabled_items, TRUE); - - // Reposition the menu, in case we're adding items to an existing menu. - menup->needsArrange(); - menup->arrangeAndClear(); - } -} - -BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - model->collectDescendentsIf(mUUID, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_type); - return ((item_array.count() > 0) ? TRUE : FALSE ); -} - -// Flags unused -void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - mItems.clear(); - mDisabledItems.clear(); - - lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; - -// menuentry_vec_t disabled_items; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - - if (lost_and_found_id == mUUID) - { - // This is the lost+found folder. - mItems.push_back(std::string("Empty Lost And Found")); - - mDisabledItems.push_back(std::string("New Folder")); - mDisabledItems.push_back(std::string("New Script")); - mDisabledItems.push_back(std::string("New Note")); - mDisabledItems.push_back(std::string("New Gesture")); - mDisabledItems.push_back(std::string("New Clothes")); - mDisabledItems.push_back(std::string("New Body Parts")); - } - - // clear out old menu and folder pointers - mMenu.markDead(); - sSelf.markDead(); - - if(trash_id == mUUID) - { - // This is the trash. - mItems.push_back(std::string("Empty Trash")); - } - else if(isItemInTrash()) - { - // This is a folder in the trash. - mItems.clear(); // clear any items that used to exist - addTrashContextMenuOptions(mItems, mDisabledItems); - } - else if(isAgentInventory()) // do not allow creating in library - { - LLViewerInventoryCategory *cat = getCategory(); - // BAP removed protected check to re-enable standard ops in untyped folders. - // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) - { - // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. - if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) - mItems.push_back(std::string("New Folder")); - mItems.push_back(std::string("New Script")); - mItems.push_back(std::string("New Note")); - mItems.push_back(std::string("New Gesture")); - mItems.push_back(std::string("New Clothes")); - mItems.push_back(std::string("New Body Parts")); - -#if SUPPORT_ENSEMBLES - // Changing folder types is an unfinished unsupported feature - // and can lead to unexpected behavior if enabled. - mItems.push_back(std::string("Change Type")); - const LLViewerInventoryCategory *cat = getCategory(); - if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - mDisabledItems.push_back(std::string("Change Type")); - } -#endif - getClipboardEntries(false, mItems, mDisabledItems, flags); - } - else - { - // Want some but not all of the items from getClipboardEntries for outfits. - if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) - { - mItems.push_back(std::string("Rename")); - - addDeleteContextMenuOptions(mItems, mDisabledItems); - // EXT-4030: disallow deletion of currently worn outfit - const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); - if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) - { - mDisabledItems.push_back(std::string("Delete")); - } - } - } - - //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 - mCallingCards = mWearables = FALSE; - - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (checkFolderForContentsOfType(model, is_callingcard)) - { - mCallingCards=TRUE; - } - - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mWearables=TRUE; - } - } - - // Preemptively disable system folder removal if more than one item selected. - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - mDisabledItems.push_back(std::string("Delete System Folder")); - } - - mItems.push_back(std::string("Share")); - if (!canShare()) - { - mDisabledItems.push_back(std::string("Share")); - } - - hide_context_entries(menu, mItems, mDisabledItems); - - // Add menu items that are dependent on the contents of the folder. - uuid_vec_t folders; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if (category) - { - folders.push_back(category->getUUID()); - } - - mMenu = menu.getHandle(); - sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); - fetch->startFetch(); - inc_busy_count(); - if(fetch->isFinished()) - { - // everything is already here - call done. - fetch->done(); - } - else - { - // it's all on its way - add an observer, and the inventory will call done for us when everything is here. - gInventory.addObserver(fetch); - } -} - -BOOL LLFolderBridge::hasChildren() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLInventoryModel::EHasChildren has_children; - has_children = gInventory.categoryHasChildren(mUUID); - return has_children != LLInventoryModel::CHILDREN_NO; -} - -BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; - - //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; - BOOL accept = FALSE; - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_CALLINGCARD: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_CLOTHING: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - accept = dragItemIntoFolder(inv_item, drop); - break; - case DAD_LINK: - // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER. - // If we have an item of AT_LINK_FOLDER type we should process the linked - // category being dragged or dropped into folder. - if (inv_item && LLAssetType::AT_LINK_FOLDER == inv_item->getActualType()) - { - LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID()); - if (linked_category) - { - accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop); - } - } - else - { - accept = dragItemIntoFolder(inv_item, drop); - } - break; - case DAD_CATEGORY: - if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) - { - accept = FALSE; - } - else - { - accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); - } - break; - default: - break; - } - return accept; -} - -LLViewerInventoryCategory* LLFolderBridge::getCategory() const -{ - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); - } - return cat; -} - - -// static -void LLFolderBridge::pasteClipboard(void* user_data) -{ - LLFolderBridge* self = (LLFolderBridge*)user_data; - if(self) self->pasteFromClipboard(); -} - -void LLFolderBridge::createNewCategory(void* user_data) -{ - LLFolderBridge* bridge = (LLFolderBridge*)user_data; - if(!bridge) return; - LLInventoryPanel* panel = dynamic_cast(bridge->mInventoryPanel.get()); - if (!panel) return; - LLInventoryModel* model = panel->getModel(); - if(!model) return; - LLUUID id; - id = model->createNewCategory(bridge->getUUID(), - LLFolderType::FT_NONE, - LLStringUtil::null); - model->notifyObservers(); - - // At this point, the bridge has probably been deleted, but the - // view is still there. - panel->setSelection(id, TAKE_FOCUS_YES); -} - -void LLFolderBridge::createNewShirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT); -} - -void LLFolderBridge::createNewPants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_PANTS); -} - -void LLFolderBridge::createNewShoes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHOES); -} - -void LLFolderBridge::createNewSocks(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SOCKS); -} - -void LLFolderBridge::createNewJacket(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_JACKET); -} - -void LLFolderBridge::createNewSkirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SKIRT); -} - -void LLFolderBridge::createNewGloves(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_GLOVES); -} - -void LLFolderBridge::createNewUndershirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_UNDERSHIRT); -} - -void LLFolderBridge::createNewUnderpants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_UNDERPANTS); -} - -void LLFolderBridge::createNewShape(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHAPE); -} - -void LLFolderBridge::createNewSkin(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SKIN); -} - -void LLFolderBridge::createNewHair(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_HAIR); -} - -void LLFolderBridge::createNewEyes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES); -} - -// static -void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type) -{ - if(!bridge) return; - LLUUID parent_id = bridge->getUUID(); - LLAgentWearables::createWearable(type, false, parent_id); -} - -void LLFolderBridge::modifyOutfit(BOOL append) -//-TT Patch: ReplaceWornItemsOnly -{ - modifyOutfit(append, false); -} - -void LLFolderBridge::modifyOutfit(BOOL append, BOOL replace) -//-TT -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append, replace ); -} - -// helper stuff -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) -{ - LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; - LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - if(option == 0 && object) - { - if (cat_and_wear && cat_and_wear->mWear) - { - LLInventoryObject::object_list_t inventory_objects; - object->getInventoryContents(inventory_objects); - int contents_count = inventory_objects.size()-1; //subtract one for containing folder - - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); - gInventory.addObserver(inventoryObserver); - } - - two_uuids_list_t::iterator move_it; - for (move_it = move_inv->mMoveList.begin(); - move_it != move_inv->mMoveList.end(); - ++move_it) - { - object->moveInventory(move_it->first, move_it->second); - } - - // update the UI. - dialog_refresh_all(); - } - - if (move_inv->mCallback) - { - move_inv->mCallback(option, move_inv->mUserData); - } - - delete move_inv; - return false; -} - -// Returns true if the item can be moved to Current Outfit or any outfit folder. -static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) -{ - if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) && - (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) && - (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) && - (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT)) - { - return FALSE; - } - - if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID())) - { - return FALSE; - } - - return TRUE; -} - -// Returns TRUE if item is a landmark or a link to a landmark -// and can be moved to Favorites or Landmarks folder. -static BOOL can_move_to_landmarks(LLInventoryItem* inv_item) -{ - // Need to get the linked item to know its type because LLInventoryItem::getType() - // returns actual type AT_LINK for links, not the asset type of a linked item. - if (LLAssetType::AT_LINK == inv_item->getType()) - { - LLInventoryItem* linked_item = gInventory.getItem(inv_item->getLinkedUUID()); - if (linked_item) - { - return LLAssetType::AT_LANDMARK == linked_item->getType(); - } - } - - return LLAssetType::AT_LANDMARK == inv_item->getType(); -} - -void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) -{ - // use callback to rearrange favorite landmarks after adding - // to have new one placed before target (on which it was dropped). See EXT-4312. - LLPointer cb = new AddFavoriteLandmarkCallback(); - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (drag_over_item && drag_over_item->getListener()) - { - cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); - } - - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - cb); -} - -void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) -{ - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceMgr::instance().wearItemOnAvatar(inv_item->getUUID(), true, true); - } - else - { - LLPointer cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_item->getLinkedUUID(), - mUUID, - inv_item->getName(), - inv_item->getDescription(), - LLAssetType::AT_LINK, - cb); - } -} - -// This is used both for testing whether an item can be dropped -// into the folder, as well as performing the actual drop, depending -// if drop == TRUE. -BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, - BOOL drop) -{ - LLInventoryModel* model = getInventoryModel(); - - if(!model || !inv_item) return FALSE; - if(!isAgentInventory()) return FALSE; // cannot drag into library - if (!isAgentAvatarValid()) return FALSE; - - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); - const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - const BOOL move_is_into_favorites = (mUUID == favorites_id); - const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); - - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL accept = FALSE; - LLViewerObject* object = NULL; - if(LLToolDragAndDrop::SOURCE_AGENT == source) - { - const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - - const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); - - //-------------------------------------------------------------------------------- - // Determine if item can be moved. - // - - BOOL is_movable = TRUE; - - switch (inv_item->getActualType()) - { - case LLAssetType::AT_CATEGORY: - is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); - break; - default: - break; - } - // Can't explicitly drag things out of the COF. - if (move_is_outof_current_outfit) - { - is_movable = FALSE; - } - -// [RLVa:KB] - Checked: 2010-05-27 (RLVa-1.2.0h) | Added: RLVa-1.2.0h - if ( (rlv_handler_t::isEnabled()) && (move_is_into_current_outfit) ) - { - // RELEASE-RLVa: [RLVa-1.2.1] Keep in sync with code below which calls LLAppearanceMgr::wearItemOnAvatar with "replace == true" - const LLViewerInventoryItem* pItem = dynamic_cast(inv_item); - is_movable = rlvPredCanWearItem(pItem, RLV_WEAR_REPLACE); - } -// [/RLVa:KB] - - if (move_is_into_trash) - { - is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID()); - } - if (is_movable) - { - // Don't allow creating duplicates in the Calling Card/Friends - // subfolders, see bug EXT-1599. Check is item direct descendent - // of target folder and forbid item's movement if it so. - // Note: isItemDirectDescendentOfCategory checks if - // passed category is in the Calling Card/Friends folder - is_movable &= !LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(inv_item, getCategory()); - } - - // - //-------------------------------------------------------------------------------- - - //-------------------------------------------------------------------------------- - // Determine if item can be moved & dropped - // - - accept = TRUE; - - if (!is_movable) - accept = FALSE; - if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) - accept = FALSE; - if (move_is_into_current_outfit || move_is_into_outfit) - { - accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); - } - else if (move_is_into_favorites || move_is_into_landmarks) - { - accept = can_move_to_landmarks(inv_item); - } - - if(accept && drop) - { - if (inv_item->getType() == LLAssetType::AT_GESTURE - && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) - { - LLGestureMgr::instance().deactivateGesture(inv_item->getUUID()); - } - // If an item is being dragged between windows, unselect everything in the active window - // so that we don't follow the selection to its new location (which is very annoying). - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); - if (active_panel) - { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - if (active_panel && (panel != active_panel)) - { - active_panel->unSelectAll(); - } - } - - //-------------------------------------------------------------------------------- - // Destination folder logic - // - - // REORDER - // (only reorder the item in Favorites folder) - if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites) - { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (itemp) - { - LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getListener()->getUUID(); - gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); - } - } - - // FAVORITES folder - // (copy the item) - else if (move_is_into_favorites) - { - dropToFavorites(inv_item); - } - // CURRENT OUTFIT or OUTFIT folder - // (link the item) - else if (move_is_into_current_outfit || move_is_into_outfit) - { - dropToOutfit(inv_item, move_is_into_current_outfit); - } - // NORMAL or TRASH folder - // (move the item, restamp if into trash) - else - { - LLInvFVBridge::changeItemParent( - model, - (LLViewerInventoryItem*)inv_item, - mUUID, - move_is_into_trash); - } - - // - //-------------------------------------------------------------------------------- - - } - } - else if (LLToolDragAndDrop::SOURCE_WORLD == source) - { - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(inv_item->getPermissions()); - BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) - // || gAgent.isGodlike()) - - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - - // Don't allow placing an original item into Current Outfit or an outfit folder - // because they must contain only links to wearable items. - // *TODO: Probably we should create a link to an item if it was dragged to outfit or COF. - if(move_is_into_current_outfit || move_is_into_outfit) - { - accept = FALSE; - } - // Don't allow to move a single item to Favorites or Landmarks - // if it is not a landmark or a link to a landmark. - else if ((move_is_into_favorites || move_is_into_landmarks) - && !can_move_to_landmarks(inv_item)) - { - accept = FALSE; - } - - if(drop && accept) - { - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = inv_item->getParentUUID(); - two_uuids_t item_pair(mUUID, inv_item->getUUID()); - move_inv->mMoveList.push_back(item_pair); - move_inv->mCallback = NULL; - move_inv->mUserData = NULL; - if(is_move) - { - warn_move_inventory(object, move_inv); - } - else - { - // store dad inventory item to select added one later. See EXT-4347 - set_dad_inventory_item(inv_item, mUUID); - - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - - } - else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) - { - // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder - // because they must contain only links to wearable items. - accept = !(move_is_into_current_outfit || move_is_into_outfit); - - if(drop) - { - copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), - LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); - } - } - else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; - if(item && item->isFinished()) - { - accept = TRUE; - - if (move_is_into_current_outfit || move_is_into_outfit) - { - accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); - } - // Don't allow to move a single item to Favorites or Landmarks - // if it is not a landmark or a link to a landmark. - else if (move_is_into_favorites || move_is_into_landmarks) - { - accept = can_move_to_landmarks(inv_item); - } - - if (accept && drop) - { - // FAVORITES folder - // (copy the item) - if (move_is_into_favorites) - { - dropToFavorites(inv_item); - } - // CURRENT OUTFIT or OUTFIT folder - // (link the item) - else if (move_is_into_current_outfit || move_is_into_outfit) - { - dropToOutfit(inv_item, move_is_into_current_outfit); - } - else - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer(NULL)); - } - } - } - } - else - { - llwarns << "unhandled drag source" << llendl; - } - return accept; -} - -// +=================================================+ -// | LLTextureBridge | -// +=================================================+ - -LLUIImagePtr LLTextureBridge::getIcon() const -{ - return LLInventoryIcon::getIcon(LLAssetType::AT_TEXTURE, mInvType); -} - -void LLTextureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -bool LLTextureBridge::canSaveTexture(void) -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) - { - return false; - } - - const LLViewerInventoryItem *item = model->getItem(mUUID); - if (item) - { - return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); - } - return false; -} - -void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - - addOpenRightClickMenuOption(items); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Texture Separator")); - items.push_back(std::string("Save As")); - if (!canSaveTexture()) - { - disabled_items.push_back(std::string("Save As")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -// virtual -void LLTextureBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ("save_as" == action) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance("preview_texture", mUUID); - if (preview_texture) - { - preview_texture->openToSave(); - } - } - else LLItemBridge::performAction(model, action); -} - -// +=================================================+ -// | LLSoundBridge | -// +=================================================+ - -void LLSoundBridge::openItem() -{ - const LLViewerInventoryItem* item = getItem(); - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -void LLSoundBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - send_sound_trigger(item->getAssetUUID(), 1.0); - } -} - -void LLSoundBridge::openSoundPreview(void* which) -{ - LLSoundBridge *me = (LLSoundBridge *)which; - LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); -} - -void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLSoundBridge::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Sound Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Sound Separator")); - items.push_back(std::string("Sound Play")); - - hide_context_entries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLLandmarkBridge | -// +=================================================+ - -LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - U32 flags/* = 0x00*/) : - LLItemBridge(inventory, root, uuid) -{ - mVisited = FALSE; - if (flags & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED) - { - mVisited = TRUE; - } -} - -LLUIImagePtr LLLandmarkBridge::getIcon() const -{ - return LLInventoryIcon::getIcon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); -} - -void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Landmark Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Landmark Separator")); - items.push_back(std::string("About Landmark")); - - // Disable "About Landmark" menu item for - // multiple landmarks selected. Only one landmark - // info panel can be shown at a time. - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("About Landmark")); - } - - hide_context_entries(menu, items, disabled_items); -} - -// Convenience function for the two functions below. -void teleport_via_landmark(const LLUUID& asset_id) -{ - gAgent.teleportViaLandmark( asset_id ); - - // we now automatically track the landmark you're teleporting to - // because you'll probably arrive at a telehub instead - LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - if( floater_world_map ) - { - floater_world_map->trackLandmark( asset_id ); - } -} - -// virtual -void LLLandmarkBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ("teleport" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - teleport_via_landmark(item->getAssetUUID()); - } - } - else if ("about" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLSD key; - key["type"] = "landmark"; - key["id"] = item->getUUID(); - - LLSideTray::getInstance()->showPanel("panel_places", key); - } - } - else - { - LLItemBridge::performAction(model, action); - } -} - -static bool open_landmark_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); - if (option == 0) - { - teleport_via_landmark(asset_id); - } - - return false; -} -static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); - - -void LLLandmarkBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - - -// +=================================================+ -// | LLCallingCardObserver | -// +=================================================+ -class LLCallingCardObserver : public LLFriendObserver -{ -public: - LLCallingCardObserver(LLCallingCardBridge* bridge) : mBridgep(bridge) {} - virtual ~LLCallingCardObserver() { mBridgep = NULL; } - virtual void changed(U32 mask) - { - mBridgep->refreshFolderViewItem(); - } -protected: - LLCallingCardBridge* mBridgep; -}; - -// +=================================================+ -// | LLCallingCardBridge | -// +=================================================+ - -LLCallingCardBridge::LLCallingCardBridge(LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid ) : - LLItemBridge(inventory, root, uuid) -{ - mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); -} - -LLCallingCardBridge::~LLCallingCardBridge() -{ - LLAvatarTracker::instance().removeObserver(mObserver); - delete mObserver; -} - -void LLCallingCardBridge::refreshFolderViewItem() -{ - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; - if (itemp) - { - itemp->refresh(); - } -} - -// virtual -void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ("begin_im" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - std::string callingcard_name; - gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); - // IDEVO - LLAvatarName av_name; - if (LLAvatarNameCache::useDisplayNames() - && LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) - { - callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")"; - } - LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); - if (session_id != LLUUID::null) - { - LLIMFloater::show(session_id); - } - } - } - else if ("lure" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - LLAvatarActions::offerTeleport(item->getCreatorUUID()); - } - } - else LLItemBridge::performAction(model, action); -} - -LLUIImagePtr LLCallingCardBridge::getIcon() const -{ - BOOL online = FALSE; - LLViewerInventoryItem* item = getItem(); - if(item) - { - online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); - } - return LLInventoryIcon::getIcon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); -} - -std::string LLCallingCardBridge::getLabelSuffix() const -{ - LLViewerInventoryItem* item = getItem(); - if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) - { - return LLItemBridge::getLabelSuffix() + " (online)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void LLCallingCardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if(item && !item->getCreatorUUID().isNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } -*/ -} - -void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - addOpenRightClickMenuOption(items); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLInventoryItem* item = getItem(); - BOOL good_card = (item - && (LLUUID::null != item->getCreatorUUID()) - && (item->getCreatorUUID() != gAgent.getID())); - BOOL user_online = FALSE; - if (item) - { - user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); - } - items.push_back(std::string("Send Instant Message Separator")); - items.push_back(std::string("Send Instant Message")); - items.push_back(std::string("Offer Teleport...")); - items.push_back(std::string("Conference Chat")); - - if (!good_card) - { - disabled_items.push_back(std::string("Send Instant Message")); - } - if (!good_card || !user_online) - { - disabled_items.push_back(std::string("Offer Teleport...")); - disabled_items.push_back(std::string("Conference Chat")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - LLViewerInventoryItem* item = getItem(); - BOOL rv = FALSE; - if(item) - { - // check the type - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_CLOTHING: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - { - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; - const LLPermissions& perm = inv_item->getPermissions(); - if(gInventory.getItem(inv_item->getUUID()) - && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) - { - rv = TRUE; - if(drop) - { - LLGiveInventory::doGiveInventoryItem(item->getCreatorUUID(), - (LLInventoryItem*)cargo_data); - } - } - 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. - rv = FALSE; - } - break; - } - case DAD_CATEGORY: - { - LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; - if( gInventory.getCategory( inv_cat->getUUID() ) ) - { - rv = TRUE; - if(drop) - { - LLGiveInventory::doGiveInventoryCategory( - item->getCreatorUUID(), - inv_cat); - } - } - 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. - rv = FALSE; - } - break; - } - default: - break; - } - } - return rv; -} - -// +=================================================+ -// | LLNotecardBridge | -// +=================================================+ - -void LLNotecardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -// +=================================================+ -// | LLGestureBridge | -// +=================================================+ - -LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const -{ - if( LLGestureMgr::instance().isGestureActive(mUUID) ) - { - return LLFontGL::BOLD; - } - else - { - return LLFontGL::NORMAL; - } -} - -std::string LLGestureBridge::getLabelSuffix() const -{ - if( LLGestureMgr::instance().isGestureActive(mUUID) ) - { - LLStringUtil::format_map_t args; - args["[GESLABEL]"] = LLItemBridge::getLabelSuffix(); - return LLTrans::getString("ActiveGesture", args); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -// virtual -void LLGestureBridge::performAction(LLInventoryModel* model, std::string action) -{ - if (isAddAction(action)) - { - LLGestureMgr::instance().activateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else if (isRemoveAction(action)) - { - LLGestureMgr::instance().deactivateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else if("play" == action) - { - if(!LLGestureMgr::instance().isGestureActive(mUUID)) - { - // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList. - BOOL inform_server = TRUE; - BOOL deactivate_similar = FALSE; - LLGestureMgr::instance().setGestureLoadedCallback(mUUID, boost::bind(&LLGestureBridge::playGesture, mUUID)); - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - llassert(item); - if (item) - { - LLGestureMgr::instance().activateGestureWithAsset(mUUID, item->getAssetUUID(), inform_server, deactivate_similar); - } - } - else - { - playGesture(mUUID); - } - } - else LLItemBridge::performAction(model, action); -} - -void LLGestureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } -*/ -} - -BOOL LLGestureBridge::removeItem() -{ - // Grab class information locally since *this may be deleted - // within this function. Not a great pattern... - const LLInventoryModel* model = getInventoryModel(); - if(!model) - { - return FALSE; - } - const LLUUID item_id = mUUID; - - // This will also force close the preview window, if it exists. - // This may actually delete *this, if mUUID is in the COF. - LLGestureMgr::instance().deactivateGesture(item_id); - - // If deactivateGesture deleted *this, then return out immediately. - if (!model->getObject(item_id)) - { - return TRUE; - } - - return LLItemBridge::removeItem(); -} - -void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - - addOpenRightClickMenuOption(items); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Gesture Separator")); - if (LLGestureMgr::instance().isGestureActive(getUUID())) - { - items.push_back(std::string("Deactivate")); - } - else - { - items.push_back(std::string("Activate")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -// static -void LLGestureBridge::playGesture(const LLUUID& item_id) -{ - if (LLGestureMgr::instance().isGesturePlaying(item_id)) - { - LLGestureMgr::instance().stopGesture(item_id); - } - else - { - LLGestureMgr::instance().playGesture(item_id); - } -} - - -// +=================================================+ -// | LLAnimationBridge | -// +=================================================+ - -void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Animation Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Animation Separator")); - items.push_back(std::string("Animation Play")); - items.push_back(std::string("Animation Audition")); - - hide_context_entries(menu, items, disabled_items); - -} - -// virtual -void LLAnimationBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ((action == "playworld") || (action == "playlocal")) - { - if (getItem()) - { - LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; - if ("playworld" == action) activate = LLPreviewAnim::PLAY; - if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; - - LLPreviewAnim* preview = LLFloaterReg::showTypedInstance("preview_anim", LLSD(mUUID)); - if (preview) - { - preview->activate(activate); - } - } - } - else - { - LLItemBridge::performAction(model, action); - } -} - -void LLAnimationBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } -*/ -} - -// +=================================================+ -// | LLObjectBridge | -// +=================================================+ - -// static -LLUUID LLObjectBridge::sContextMenuItemID; - -LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - LLInventoryType::EType type, - U32 flags) : - LLItemBridge(inventory, root, uuid) -{ - mAttachPt = (flags & 0xff); // low bye of inventory flags - mIsMultiObject = ( flags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; - mInvType = type; -} - -LLUIImagePtr LLObjectBridge::getIcon() const -{ - return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject); -} - -LLInventoryObject* LLObjectBridge::getObject() const -{ - LLInventoryObject* object = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - object = (LLInventoryObject*)model->getObject(mUUID); - } - return object; -} - -// virtual -void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) -{ - if (isAddAction(action)) - { - LLUUID object_id = mUUID; - LLViewerInventoryItem* item; - item = (LLViewerInventoryItem*)gInventory.getItem(object_id); - if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) - { - rez_attachment(item, NULL, true); // Replace if "Wear"ing. - } - else if(item && item->isFinished()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer cb = new RezAttachmentCallback(0); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - gFocusMgr.setKeyboardFocus(NULL); - } - else if ("wear_add" == action) - { - LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. - } -// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-08-25 (Catznip-2.2.0a) | Added: Catznip-2.1.2a - else if ("edit" == action) - { - handle_attachment_edit(mUUID); - } -// [/SL:KB] - else if (isRemoveAction(action)) - { - LLInventoryItem* item = gInventory.getItem(mUUID); - if(item) - { - LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID()); - } - } - else LLItemBridge::performAction(model, action); -} - -void LLObjectBridge::openItem() -{ - // object double-click action is to wear/unwear object - performAction(getInventoryModel(), - get_is_item_worn(mUUID) ? "detach" : "attach"); -} - -std::string LLObjectBridge::getLabelSuffix() const -{ - if (get_is_item_worn(mUUID)) - { - if (!isAgentAvatarValid()) // Error condition, can't figure out attach point - { - return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); - } - std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); - if (attachment_point_name == LLStringUtil::null) // Error condition, invalid attach point - { - attachment_point_name = "Invalid Attachment"; - } - // e.g. "(worn on ...)" / "(attached to ...)" - LLStringUtil::format_map_t args; - args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); - - return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); - } - return LLItemBridge::getLabelSuffix(); -} - -void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace) -{ -// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1a) | Added: RLVa-1.2.1a - // If no attachment point was specified, try looking it up from the item name - if ( (rlv_handler_t::isEnabled()) && (!attachment) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) - { - attachment = RlvAttachPtLookup::getAttachPoint(item); - } -// [/RLVa:KB] - - const LLUUID& item_id = item->getLinkedUUID(); - - // Check for duplicate request. - if (isAgentAvatarValid() && - (gAgentAvatarp->attachmentWasRequested(item_id) || - gAgentAvatarp->isWearingAttachment(item_id))) - { - llwarns << "duplicate attachment request, ignoring" << llendl; - return; - } - gAgentAvatarp->addAttachmentRequest(item_id); - - S32 attach_pt = 0; - if (isAgentAvatarValid() && attachment) - { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) - { - if (iter->second == attachment) - { - attach_pt = iter->first; - break; - } - } - } - - LLSD payload; - payload["item_id"] = item_id; // Wear the base object in case this is a link. - payload["attachment_point"] = attach_pt; - payload["is_add"] = !replace; - - if (replace && - (attachment && attachment->getNumObjects() > 0)) - { -// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a - // Block if we can't "replace wear" what's currently there - if ( (rlv_handler_t::isEnabled()) && ((gRlvAttachmentLocks.canAttach(attachment) & RLV_WEAR_REPLACE) == 0) ) - return; -// [/RLVa:KB] - LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_attachment_rez); - } - else - { -// [RLVa:KB] - Checked: 2010-08-07 (RLVa-1.2.0i) | Modified: RLVa-1.2.0i - // Block wearing anything on a non-attachable attachment point - if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachmentPoint(attach_pt, RLV_LOCK_ADD)) ) - return; -// [/RLVa:KB] - LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); - } -} - -bool confirm_attachment_rez(const LLSD& notification, const LLSD& response) -{ - if (!gAgentAvatarp->canAttachMoreObjects()) - { - LLSD args; - args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); - LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args); - return false; - } - - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0/*YES*/) - { - LLUUID item_id = notification["payload"]["item_id"].asUUID(); - LLViewerInventoryItem* itemp = gInventory.getItem(item_id); - - if (itemp) - { - /* - { - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); -// [RLVa:KB] - Checked: 2010-08-06 (RLVa-1.2.0i) | Added: RLVa-1.2.0i - // NOTE: we're letting our callers decide whether or not to use ATTACHMENT_ADD - if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) && - ((!notification["payload"].has("rlv_force")) || (!notification["payload"]["rlv_force"].asBoolean())) ) - { - ERlvWearMask eWearAction = (attachment_pt & ATTACHMENT_ADD) ? RLV_WEAR_ADD : RLV_WEAR_REPLACE; - RlvAttachmentLockWatchdog::instance().onWearAttachment(itemp, eWearAction);; - - attachment_pt |= ATTACHMENT_ADD; - } -// [/RLVa:KB] - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); - msg->addStringFast(_PREHASH_Name, itemp->getName()); - msg->addStringFast(_PREHASH_Description, itemp->getDescription()); - msg->sendReliable(gAgent.getRegion()->getHost()); - return false; - } - */ - - // Queue up attachments to be sent in next idle tick, this way the - // attachments are batched up all into one message versus each attachment - // being sent in its own separate attachments message. - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); - BOOL is_add = notification["payload"]["is_add"].asBoolean(); - - LLAttachmentsMgr::instance().addAttachment(item_id, - attachment_pt, - is_add); - } - } - return false; -} -static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_attachment_rez); - -void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - menuentry_vec_t items; - menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLObjectBridge::sContextMenuItemID = mUUID; - - LLInventoryItem *item = getItem(); - if(item) - { - if (!isAgentAvatarValid()) return; - - if( get_is_item_worn( mUUID ) ) - { - items.push_back(std::string("Wearable And Object Separator")); -// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-08-25 (Catznip-2.2.0a) | Added: Catznip-2.1.2a - // TOOD-Catznip: should really be "Wearable And Object Edit" if we ever plan on pushing this upstream - items.push_back(std::string("Wearable Edit")); -// [/SL:KB] - items.push_back(std::string("Detach From Yourself")); -// [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a - if ( (rlv_handler_t::isEnabled()) && (!gRlvAttachmentLocks.canDetach(item)) ) - disabled_items.push_back(std::string("Detach From Yourself")); -// [/RLVa:KB] - } - else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder()) - { - items.push_back(std::string("Wearable And Object Separator")); - items.push_back(std::string("Wearable And Object Wear")); - items.push_back(std::string("Wearable Add")); - items.push_back(std::string("Attach To")); - items.push_back(std::string("Attach To HUD")); - // commented out for DEV-32347 - //items.push_back(std::string("Restore to Last Position")); - - if (!gAgentAvatarp->canAttachMoreObjects()) - { - disabled_items.push_back(std::string("Wearable And Object Wear")); - disabled_items.push_back(std::string("Wearable Add")); - disabled_items.push_back(std::string("Attach To")); - disabled_items.push_back(std::string("Attach To HUD")); - } -// [RLVa:KB] - Checked: 2010-09-03 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a - else if (rlv_handler_t::isEnabled()) - { - ERlvWearMask eWearMask = gRlvAttachmentLocks.canAttach(item); - if ((eWearMask & RLV_WEAR_REPLACE) == 0) - disabled_items.push_back(std::string("Wearable And Object Wear")); - if ((eWearMask & RLV_WEAR_ADD) == 0) - disabled_items.push_back(std::string("Wearable Add")); - } -// [/RLVa:KB] - - LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); - LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); - if (attach_menu - && (attach_menu->getChildCount() == 0) - && attach_hud_menu - && (attach_hud_menu->getChildCount() == 0) - && isAgentAvatarValid()) - { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - LLMenuItemCallGL::Params p; - std::string submenu_name = attachment->getName(); - if (LLTrans::getString(submenu_name) != "") - { - p.name = (" ")+LLTrans::getString(submenu_name)+" "; - } - else - { - p.name = submenu_name; - } - LLSD cbparams; - cbparams["index"] = curiter->first; - cbparams["label"] = p.name; - p.on_click.function_name = "Inventory.AttachObject"; - p.on_click.parameter = LLSD(attachment->getName()); - p.on_enable.function_name = "Attachment.Label"; - p.on_enable.parameter = cbparams; - LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; - LLUICtrlFactory::create(p, parent); - } - } - } - } - } - hide_context_entries(menu, items, disabled_items); -} - -BOOL LLObjectBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - - if (isAgentAvatarValid()) - { - LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() ); - if(obj) - { - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); - LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); - LLSelectMgr::getInstance()->deselectAll(); - } - } - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -// +=================================================+ -// | LLLSLTextBridge | -// +=================================================+ - -void LLLSLTextBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -// +=================================================+ -// | LLWearableBridge | -// +=================================================+ - -LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - LLAssetType::EType asset_type, - LLInventoryType::EType inv_type, - LLWearableType::EType wearable_type) : - LLItemBridge(inventory, root, uuid), - mAssetType( asset_type ), - mWearableType(wearable_type) -{ - mInvType = inv_type; -} - -void remove_inventory_category_from_avatar( LLInventoryCategory* category ) -{ - if(!category) return; - lldebugs << "remove_inventory_category_from_avatar( " << category->getName() - << " )" << llendl; - - - if (gAgentCamera.cameraCustomizeAvatar()) - { - // switching to outfit editor should automagically save any currently edited wearable - LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit")); - } - - remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); -} - -struct OnRemoveStruct -{ - LLUUID mUUID; - OnRemoveStruct(const LLUUID& uuid): - mUUID(uuid) - { - } -}; - -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) -{ - - // Find all the wearables that are in the category's subtree. - lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; - if(proceed) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLFindWearables is_wearable; - gInventory.collectDescendentsIf(category_id, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_wearable); - S32 i; - S32 wearable_count = item_array.count(); - - LLInventoryModel::cat_array_t obj_cat_array; - LLInventoryModel::item_array_t obj_item_array; - LLIsType is_object( LLAssetType::AT_OBJECT ); - gInventory.collectDescendentsIf(category_id, - obj_cat_array, - obj_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_object); - S32 obj_count = obj_item_array.count(); - - // Find all gestures in this folder - LLInventoryModel::cat_array_t gest_cat_array; - LLInventoryModel::item_array_t gest_item_array; - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - gInventory.collectDescendentsIf(category_id, - gest_cat_array, - gest_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_gesture); - S32 gest_count = gest_item_array.count(); - - if (wearable_count > 0) //Loop through wearables. If worn, remove. - { - for(i = 0; i < wearable_count; ++i) - { - LLViewerInventoryItem *item = item_array.get(i); - if (item->getType() == LLAssetType::AT_BODYPART) - continue; - if (gAgent.isTeen() && item->isWearableType() && - (item->getWearableType() == LLWearableType::WT_UNDERPANTS || item->getWearableType() == LLWearableType::WT_UNDERSHIRT)) - continue; - if (get_is_item_worn(item->getUUID())) - { -/* -// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0c) | Modified: RLVa-0.2.2a - if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) - continue; -// [/RLVa:KB] - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item->getLinkedUUID())); -*/ -// [SL:KB] - Patch: Appearance-RemoveWearableFromAvatar | Checked: 2010-08-13 (Catznip-2.5.0a) | Added: Catznip-2.1.1d - LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); -// [/SL:KB] - } - } - } - - if (obj_count > 0) - { - for(i = 0; i < obj_count; ++i) - { - LLViewerInventoryItem *obj_item = obj_item_array.get(i); - if (get_is_item_worn(obj_item->getUUID())) - { - LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID()); - } - } - } - - if (gest_count > 0) - { - for(i = 0; i < gest_count; ++i) - { - LLViewerInventoryItem *gest_item = gest_item_array.get(i); - if (get_is_item_worn(gest_item->getUUID())) - { - LLGestureMgr::instance().deactivateGesture( gest_item->getLinkedUUID() ); - gInventory.updateItem( gest_item ); - gInventory.notifyObservers(); - } - - } - } - } -} - -BOOL LLWearableBridge::renameItem(const std::string& new_name) -{ - if (get_is_item_worn(mUUID)) - { - gAgentWearables.setWearableName( mUUID, new_name ); - } - return LLItemBridge::renameItem(new_name); -} - -std::string LLWearableBridge::getLabelSuffix() const -{ - if (get_is_item_worn(mUUID)) - { - // e.g. "(worn)" - return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -LLUIImagePtr LLWearableBridge::getIcon() const -{ - return LLInventoryIcon::getIcon(mAssetType, mInvType, mWearableType, FALSE); -} - -// virtual -void LLWearableBridge::performAction(LLInventoryModel* model, std::string action) -{ - if (isAddAction(action)) - { - wearOnAvatar(); - } - else if ("wear_add" == action) - { - wearAddOnAvatar(); - } - else if ("edit" == action) - { - editOnAvatar(); - return; - } - else if (isRemoveAction(action)) - { - removeFromAvatar(); - return; - } - else LLItemBridge::performAction(model, action); -} - -void LLWearableBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere - BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM); - - // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 - LLViewerInventoryItem* item = getItem(); - if (can_open && item) - { - can_open = (item->getType() != LLAssetType::AT_CLOTHING) && - (item->getType() != LLAssetType::AT_BODYPART); - } - if (isLinkedObjectMissing()) - { - can_open = FALSE; - } - items.push_back(std::string("Share")); - if (!canShare()) - { - disabled_items.push_back(std::string("Share")); - } - - if (can_open) - { - addOpenRightClickMenuOption(items); - } - else - { - disabled_items.push_back(std::string("Open")); - disabled_items.push_back(std::string("Open Original")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Wearable And Object Separator")); - - items.push_back(std::string("Wearable Edit")); - - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Wearable Edit")); - } - // Don't allow items to be worn if their baseobj is in the trash. - if (isLinkedObjectInTrash() || isLinkedObjectMissing() || isCOFFolder()) - { - disabled_items.push_back(std::string("Wearable And Object Wear")); - disabled_items.push_back(std::string("Wearable Add")); - disabled_items.push_back(std::string("Wearable Edit")); - } - - // Disable wear and take off based on whether the item is worn. - if(item) - { - switch (item->getType()) - { - case LLAssetType::AT_CLOTHING: - items.push_back(std::string("Take Off")); - // Fallthrough since clothing and bodypart share wear options - case LLAssetType::AT_BODYPART: - if (get_is_item_worn(item->getUUID())) - { - disabled_items.push_back(std::string("Wearable And Object Wear")); - disabled_items.push_back(std::string("Wearable Add")); -// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0c) | Added: RLVa-1.2.0c - if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) - disabled_items.push_back(std::string("Take Off")); -// [/RLVa:KB] - } - else - { - items.push_back(std::string("Wearable And Object Wear")); - items.push_back(std::string("Wearable Add")); - disabled_items.push_back(std::string("Take Off")); - disabled_items.push_back(std::string("Wearable Edit")); - -// [RLVa:KB] - Checked: 2010-06-09 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g - if (rlv_handler_t::isEnabled()) - { - ERlvWearMask eWearMask = gRlvWearableLocks.canWear(item); - if ((eWearMask & RLV_WEAR_REPLACE) == 0) - disabled_items.push_back(std::string("Wearable And Object Wear")); - if ((eWearMask & RLV_WEAR_ADD) == 0) - disabled_items.push_back(std::string("Wearable Add")); - } -// [/RLVa:KB] - } - break; - default: - break; - } - } - } - hide_context_entries(menu, items, disabled_items); -} - -// Called from menus -// static -BOOL LLWearableBridge::canWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - if(!self->isAgentInventory()) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); - if(!item || !item->isFinished()) return FALSE; - } - return (!get_is_item_worn(self->mUUID)); -} - -// Called from menus -// static -void LLWearableBridge::onWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - self->wearOnAvatar(); -} - -void LLWearableBridge::wearOnAvatar() -{ - // TODO: investigate wearables may not be loaded at this point EXT-8231 - - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true); - } -} - -void LLWearableBridge::wearAddOnAvatar() -{ - // TODO: investigate wearables may not be loaded at this point EXT-8231 - - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, false); - } -} - -// static -/* -void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - gAgentWearables.setWearableItem(item, wearable); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} -*/ - -// static -// BAP remove the "add" code path once everything is fully COF-ified. -/* -void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - bool do_append = true; - gAgentWearables.setWearableItem(item, wearable, do_append); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} -*/ - -// static -BOOL LLWearableBridge::canEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - - return (get_is_item_worn(self->mUUID)); -} - -// static -void LLWearableBridge::onEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(self) - { - self->editOnAvatar(); - } -} - -void LLWearableBridge::editOnAvatar() -{ - LLAgentWearables::editWearable(mUUID); -} - -// static -BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) - { - return get_is_item_worn( self->mUUID ); - } - return FALSE; -} - -// static -/* -void LLWearableBridge::onRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - if(get_is_item_worn(self->mUUID)) - { - LLViewerInventoryItem* item = self->getItem(); - if (item) - { - LLUUID parent_id = item->getParentUUID(); - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - onRemoveFromAvatarArrived, - new OnRemoveStruct(LLUUID(self->mUUID))); - } - } -} -*/ - -// static -/* -void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, - void* userdata) -{ - OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; - const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); - -// [RLVa:KB] - Checked: 2010-03-20 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a - if ( (rlv_handler_t::isEnabled()) && ((!wearable) || (!gRlvWearableLocks.canRemove(gInventory.getItem(item_id)))) ) - { - delete on_remove_struct; - return; - } -// [/RLVa:KB] - - if(wearable) - { - if( get_is_item_worn( item_id ) ) - { - LLWearableType::EType type = wearable->getType(); - - if( !(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES ) ) //&& - //!((!gAgent.isTeen()) && ( type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT )) ) - { - bool do_remove_all = false; - U32 index = gAgentWearables.getWearableIndex(wearable); - gAgentWearables.removeWearable( type, do_remove_all, index ); - } - } - } - - // Find and remove this item from the COF. - LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); - gInventory.notifyObservers(); - - delete on_remove_struct; -} -*/ - -// static -void LLWearableBridge::removeAllClothesFromAvatar() -{ - // Remove COF links. - for (S32 itype = LLWearableType::WT_SHAPE; itype < LLWearableType::WT_COUNT; ++itype) - { - if (itype == LLWearableType::WT_SHAPE || itype == LLWearableType::WT_SKIN || itype == LLWearableType::WT_HAIR || itype == LLWearableType::WT_EYES) - continue; - -// for (S32 index = gAgentWearables.getWearableCount(itype)-1; index >= 0 ; --index) -// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-09-04 (Catznip-2.5.0a) | Added: Catznip-2.1.2a - for (S32 index = gAgentWearables.getWearableCount((LLWearableType::EType)itype)-1; index >= 0 ; --index) -// [/SL:KB] - { - LLViewerInventoryItem *item = dynamic_cast( - gAgentWearables.getWearableInventoryItem((LLWearableType::EType)itype, index)); - if (!item) - continue; - const LLUUID &item_id = item->getUUID(); - const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id); - if (!wearable) - continue; - -// [RLVa:KB] - Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g - if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) - continue; -// [/RLVa:KB] - - // Find and remove this item from the COF. - LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); - } - } - gInventory.notifyObservers(); - - // Remove wearables from gAgentWearables -// LLAgentWearables::userRemoveAllClothes(); -// [RLVa:KB] - Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g - LLAppearanceMgr::instance().updateAppearanceFromCOF(); -// [/RLVa:KB] -} - -// static -void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item) -{ - if (item) - { -/* - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item->getUUID())); -*/ -// [SL:KB] - Patch: Appearance-RemoveWearableFromAvatar | Checked: 2010-08-13 (Catznip-2.5.0a) | Added: Catznip-2.1.1d - LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); -// [/SL:KB] - } -} - -void LLWearableBridge::removeFromAvatar() -{ - if (get_is_item_worn(mUUID)) - { - LLViewerInventoryItem* item = getItem(); - removeItemFromAvatar(item); - } -} - -// +=================================================+ -// | LLLinkItemBridge | -// +=================================================+ -// For broken item links - -std::string LLLinkItemBridge::sPrefix("Link: "); - -void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - items.push_back(std::string("Find Original")); - disabled_items.push_back(std::string("Find Original")); - - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Properties")); - addDeleteContextMenuOptions(items, disabled_items); - } - hide_context_entries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLLinkBridge | -// +=================================================+ -// For broken folder links. -std::string LLLinkFolderBridge::sPrefix("Link: "); -LLUIImagePtr LLLinkFolderBridge::getIcon() const -{ - LLFolderType::EType folder_type = LLFolderType::FT_NONE; - const LLInventoryObject *obj = getInventoryObject(); - if (obj) - { - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - cat = (LLViewerInventoryCategory*)model->getCategory(obj->getLinkedUUID()); - if (cat) - { - folder_type = cat->getPreferredType(); - } - } - } - return LLFolderBridge::getIcon(folder_type); -} - -void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - if (isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else - { - items.push_back(std::string("Find Original")); - addDeleteContextMenuOptions(items, disabled_items); - } - hide_context_entries(menu, items, disabled_items); -} -void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(); - return; - } - LLItemBridge::performAction(model,action); -} -void LLLinkFolderBridge::gotoItem() -{ - const LLUUID &cat_uuid = getFolderID(); - if (!cat_uuid.isNull()) - { - if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) - { - if (LLInventoryModel* model = getInventoryModel()) - { - model->fetchDescendentsOf(cat_uuid); - } - base_folder->setOpen(TRUE); - mRoot->setSelectionFromRoot(base_folder,TRUE); - mRoot->scrollToShowSelection(); - } - } -} -const LLUUID &LLLinkFolderBridge::getFolderID() const -{ - if (LLViewerInventoryItem *link_item = getItem()) - { - if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) - { - const LLUUID& cat_uuid = cat->getUUID(); - return cat_uuid; - } - } - return LLUUID::null; -} - -/******************************************************************************** - ** - ** BRIDGE ACTIONS - **/ - -// static -void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, - const LLUUID& uuid, - LLInventoryModel* model) -{ - // Perform indirection in case of link. - const LLUUID& linked_uuid = gInventory.getLinkedItemID(uuid); - - LLInvFVBridgeAction* action = createAction(asset_type,linked_uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -// static -void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) -{ - llassert(model); - LLViewerInventoryItem* item = model->getItem(uuid); - llassert(item); - if (item) - { - LLAssetType::EType asset_type = item->getType(); - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } - } -} - -LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const -{ - if (mModel) - return (LLViewerInventoryItem*)mModel->getItem(mUUID); - return NULL; -} - -class LLTextureBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - if (getItem()) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLTextureBridgeAction(){} -protected: - LLTextureBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLSoundBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLSoundBridgeAction(){} -protected: - LLSoundBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLLandmarkBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - - LLSD args; - args["LOCATION"] = item->getName(); - - LLNotificationsUtil::add("TeleportFromLandmark", args, payload); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLLandmarkBridgeAction(){} -protected: - LLLandmarkBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLCallingCardBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item && item->getCreatorUUID().notNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLCallingCardBridgeAction(){} -protected: - LLCallingCardBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} - -}; - -class LLNotecardBridgeAction -: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLNotecardBridgeAction(){} -protected: - LLNotecardBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLGestureBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLGestureBridgeAction(){} -protected: - LLGestureBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLAnimationBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLAnimationBridgeAction(){} -protected: - LLAnimationBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLObjectBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - /* - LLFloaterReg::showInstance("properties", mUUID); - */ - LLInvFVBridgeAction::doIt(); - } - virtual ~LLObjectBridgeAction(){} -protected: - LLObjectBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLLSLTextBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - LLInvFVBridgeAction::doIt(); - } - virtual ~LLLSLTextBridgeAction(){} -protected: - LLLSLTextBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} -}; - -class LLWearableBridgeAction: public LLInvFVBridgeAction -{ - friend class LLInvFVBridgeAction; -public: - virtual void doIt() - { +/** + * @file llinventorybridge.cpp + * @brief Implementation of the Inventory-Folder-View-Bridge classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llinventorybridge.h" + +// external projects +#include "lltransfersourceasset.h" +#include "llavatarnamecache.h" // IDEVO + +#include "llagent.h" +#include "llagentcamera.h" +#include "llagentwearables.h" +#include "llappearancemgr.h" +#include "llattachmentsmgr.h" +#include "llavataractions.h" +#include "llfloateropenobject.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llfriendcard.h" +#include "llgesturemgr.h" +#include "llgiveinventory.h" +#include "llimfloater.h" +#include "llimview.h" +#include "llinventoryclipboard.h" +#include "llinventorydefines.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpreviewanim.h" +#include "llpreviewgesture.h" +#include "llpreviewtexture.h" +#include "llselectmgr.h" +#include "llsidepanelappearance.h" +#include "llsidetray.h" +#include "lltrans.h" +#include "llviewerassettype.h" +#include "llviewerfoldertype.h" +#include "llviewermenu.h" +#include "llviewermessage.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llvoavatarself.h" +#include "llwearablelist.h" +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) +#include "rlvhandler.h" +#include "rlvlocks.h" +// [/RLVa:KB] + +typedef std::pair two_uuids_t; +typedef std::list two_uuids_list_t; + +struct LLMoveInv +{ + LLUUID mObjectID; + LLUUID mCategoryID; + two_uuids_list_t mMoveList; + void (*mCallback)(S32, void*); + void* mUserData; +}; + +using namespace LLOldEvents; + +// Helpers +// bug in busy count inc/dec right now, logic is complex... do we really need it? +void inc_busy_count() +{ +// gViewerWindow->getWindow()->incBusyCount(); +// check balance of these calls if this code is changed to ever actually +// *do* something! +} +void dec_busy_count() +{ +// gViewerWindow->getWindow()->decBusyCount(); +// check balance of these calls if this code is changed to ever actually +// *do* something! +} + +// Function declarations +void remove_inventory_category_from_avatar(LLInventoryCategory* category); +void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); +//-TT Patch: ReplaceWornItemsOnly +void wear_inventory_category_on_avatar(LLInventoryCategory* category); +//-TT +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); +bool confirm_attachment_rez(const LLSD& notification, const LLSD& response); +void teleport_via_landmark(const LLUUID& asset_id); +static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); + +// +=================================================+ +// | LLInvFVBridge | +// +=================================================+ + +LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid) : + mUUID(uuid), + mRoot(root), + mInvType(LLInventoryType::IT_NONE), + mIsLink(FALSE) +{ + mInventoryPanel = inventory->getHandle(); + const LLInventoryObject* obj = getInventoryObject(); + mIsLink = obj && obj->getIsLinkType(); +} + +const std::string& LLInvFVBridge::getName() const +{ + const LLInventoryObject* obj = getInventoryObject(); + if(obj) + { + return obj->getName(); + } + return LLStringUtil::null; +} + +const std::string& LLInvFVBridge::getDisplayName() const +{ + return getName(); +} + +// Folders have full perms +PermissionMask LLInvFVBridge::getPermissionMask() const +{ + return PERM_ALL; +} + +// virtual +LLFolderType::EType LLInvFVBridge::getPreferredType() const +{ + return LLFolderType::FT_NONE; +} + + +// Folders don't have creation dates. +time_t LLInvFVBridge::getCreationDate() const +{ + return 0; +} + +// Can be destroyed (or moved to trash) +BOOL LLInvFVBridge::isItemRemovable() const +{ + return get_is_item_removable(getInventoryModel(), mUUID); +} + +// Can be moved to another folder +BOOL LLInvFVBridge::isItemMovable() const +{ + return TRUE; +} + +BOOL LLInvFVBridge::isLink() const +{ + return mIsLink; +} + +/*virtual*/ +/** + * @brief Adds this item into clipboard storage + */ +void LLInvFVBridge::cutToClipboard() +{ + if(isItemMovable()) + { + LLInventoryClipboard::instance().cut(mUUID); + } +} +// *TODO: make sure this does the right thing +void LLInvFVBridge::showProperties() +{ + //show_item_profile(mUUID); + + // Disable old properties floater; this is replaced by the sidepanel. + /**/ + //-TT Experiment. + LLFloaterReg::showInstance("properties", mUUID); +} + +void LLInvFVBridge::removeBatch(LLDynamicArray& batch) +{ + // Deactivate gestures when moving them into Trash + LLInvFVBridge* bridge; + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + S32 count = batch.count(); + S32 i,j; + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if (item) + { + if(LLAssetType::AT_GESTURE == item->getType()) + { + LLGestureMgr::instance().deactivateGesture(item->getUUID()); + } + } + } + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + if (cat) + { + gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); + for (j=0; jgetType()) + { + LLGestureMgr::instance().deactivateGesture(descendent_items[j]->getUUID()); + } + } + } + } + removeBatchNoCheck(batch); +} + +void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray& batch) +{ + // this method moves a bunch of items and folders to the trash. As + // per design guidelines for the inventory model, the message is + // built and the accounting is performed first. After all of that, + // we call LLInventoryModel::moveObject() to move everything + // around. + LLInvFVBridge* bridge; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLMessageSystem* msg = gMessageSystem; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLViewerInventoryItem* item = NULL; + uuid_vec_t move_ids; + LLInventoryModel::update_map_t update; + bool start_new_message = true; + S32 count = batch.count(); + S32 i; + + // first, hide any 'preview' floaters that correspond to the items + // being deleted. + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if(item) + { + LLPreview::hide(item->getUUID()); + } + } + + // do the inventory move to trash + + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if(item) + { + if(item->getParentUUID() == trash_id) continue; + move_ids.push_back(item->getUUID()); + --update[item->getParentUUID()]; + ++update[trash_id]; + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOLFast(_PREHASH_Stamp, TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); + msg->addUUIDFast(_PREHASH_FolderID, trash_id); + msg->addString("NewName", NULL); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + } + } + if(!start_new_message) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + if(cat) + { + if(cat->getParentUUID() == trash_id) continue; + move_ids.push_back(cat->getUUID()); + --update[cat->getParentUUID()]; + ++update[trash_id]; + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOL("Stamp", TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); + msg->addUUIDFast(_PREHASH_ParentID, trash_id); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + } + } + if(!start_new_message) + { + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + } + + // move everything. + uuid_vec_t::iterator it = move_ids.begin(); + uuid_vec_t::iterator end = move_ids.end(); + for(; it != end; ++it) + { + gInventory.moveObject((*it), trash_id); + } + + // notify inventory observers. + model->notifyObservers(); +} + +BOOL LLInvFVBridge::isClipboardPasteable() const +{ + if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + { + return FALSE; + } + LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + const LLUUID &agent_id = gAgent.getID(); + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &item_id = objects.get(i); + + // Can't paste folders <-- why not? +// const LLInventoryCategory *cat = model->getCategory(item_id); +// if (cat) +// { +// return FALSE; +// } + +// const LLInventoryItem *item = model->getItem(item_id); + const LLViewerInventoryItem *item = model->getItem(item_id); + if (item) + { +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + // Can't copy worn objects. DEV-15183 [see P-JIRA: http://jira.secondlife.com/browse/VWR-6110] + // TODO-Catznip: [SL-2.2.0] I don't think preventing copying worn items would prevent the bug that actually occurred? +// if ( (!item->getIsLinkType()) && (get_is_item_worn(item->getUUID())) ) +// { +// return FALSE; +// } +// [/SL:KB] + + if (!item->getPermissions().allowCopyBy(agent_id)) + { +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + // We allow copy/pasting of links as long as their target is available + // (and disallow if the user is trying to paste a folder link pointing to the current folder) + if ( (!item->getIsLinkType()) || (!item->getLinkedItem()) || + ((LLAssetType::AT_LINK_FOLDER == item->getActualType()) && (item->getLinkedUUID() == mUUID)) ) + { + return FALSE; + } +// [/SL:KB] +// return FALSE; + } + } + } + return TRUE; +} + +BOOL LLInvFVBridge::isClipboardPasteableAsLink() const +{ + if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + { + return FALSE; + } + const LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLInventoryItem *item = model->getItem(objects.get(i)); + if (item) + { + if (!LLAssetType::lookupCanLink(item->getActualType())) + { + return FALSE; + } + } + const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); + if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + return FALSE; + } + } + return TRUE; +} + +void hide_context_entries(LLMenuGL& menu, + const menuentry_vec_t &entries_to_show, + const menuentry_vec_t &disabled_entries, + BOOL append) // If append is TRUE, then new enabled entries +{ + const LLView::child_list_t *list = menu.getChildList(); + + // For removing double separators or leading separator. Start at true so that + // if the first element is a separator, it will not be shown. + BOOL is_previous_entry_separator = TRUE; + + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + std::string name = menu_item->getName(); + + // descend into split menus: + LLMenuItemBranchGL* branchp = dynamic_cast(menu_item); + if ((name == "More") && branchp) + { + hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); + } + + + bool found = false; + menuentry_vec_t::const_iterator itor2; + for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) + { + if (*itor2 == name) + { + found = true; + } + } + + // Don't allow multiple separators in a row (e.g. such as if there are no items + // between two separators). + if (found) + { + const BOOL is_entry_separator = (dynamic_cast(menu_item) != NULL); + if (is_entry_separator && is_previous_entry_separator) + found = false; + is_previous_entry_separator = is_entry_separator; + } + + if (!found) + { + if (!menu_item->getLastVisible()) + { + menu_item->setVisible(FALSE); + } + menu_item->setEnabled(FALSE); + } + else + { + menu_item->setVisible(TRUE); + // A bit of a hack so we can remember that some UI element explicitly set this to be visible + // so that some other UI element from multi-select doesn't later set this invisible. + menu_item->pushVisible(TRUE); + if (append) + { + menu_item->setEnabled(TRUE); + } + for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) + { + if (*itor2 == name) + { + menu_item->setEnabled(FALSE); + } + } + } + } +} + +// Helper for commonly-used entries +void LLInvFVBridge::getClipboardEntries(bool show_asset_id, + menuentry_vec_t &items, + menuentry_vec_t &disabled_items, U32 flags) +{ + const LLInventoryObject *obj = getInventoryObject(); + + if (obj) + { + if (obj->getIsLinkType()) + { + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + } + else + { + if (LLAssetType::lookupCanLink(obj->getType())) + { + items.push_back(std::string("Find Links")); + } + items.push_back(std::string("Rename")); + if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Rename")); + } + + if (show_asset_id) + { + items.push_back(std::string("Copy Asset UUID")); + + bool is_asset_knowable = false; + + LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); + if (inv_item) + { + is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType()); + } + if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 + || (! ( isItemPermissive() || gAgent.isGodlike() ) ) + || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Copy Asset UUID")); + } + } +/* + items.push_back(std::string("Copy Separator")); + + items.push_back(std::string("Copy")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Copy")); + } +*/ + items.push_back(std::string("Cut")); + } + } + +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + items.push_back(std::string("Copy Separator")); + + items.push_back(std::string("Copy")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Copy")); + } +// [/SL:KB] + + + // Don't allow items to be pasted directly into the COF. + if (!isCOFFolder()) + { + items.push_back(std::string("Paste")); + } + if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0)) + { + disabled_items.push_back(std::string("Paste")); + } + + if (gSavedSettings.getBOOL("InventoryLinking")) + { + items.push_back(std::string("Paste As Link")); + if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Paste As Link")); + } + } + + items.push_back(std::string("Paste Separator")); + + addDeleteContextMenuOptions(items, disabled_items); + + // If multiple items are selected, disable properties (if it exists). + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Properties")); + } +} + +void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + + addOpenRightClickMenuOption(items); + items.push_back(std::string("Properties")); + +// [RLVa:KB] - Checked: 2010-03-01 (RLVa-1.2.0b) | Modified: RLVa-1.1.0a + if (rlv_handler_t::isEnabled()) + { + const LLInventoryObject* pItem = getInventoryObject(); + if ( (pItem) && + ( ((LLAssetType::AT_NOTECARD == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE))) || + ((LLAssetType::AT_LSL_TEXT == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT))) || + ((LLAssetType::AT_TEXTURE == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))) ) ) + { + disabled_items.push_back(std::string("Open")); + } + } +// [/RLVa:KB] + + getClipboardEntries(true, items, disabled_items, flags); + } + hide_context_entries(menu, items, disabled_items); +} + +void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items, + menuentry_vec_t &disabled_items) +{ + const LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + } + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + items.push_back(std::string("Restore Item")); +} + +void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, + menuentry_vec_t &disabled_items) +{ + + const LLInventoryObject *obj = getInventoryObject(); + + // Don't allow delete as a direct option from COF folder. + if (obj && obj->getIsLinkType() && isCOFFolder() && get_is_item_worn(mUUID)) + { + return; + } + + // "Remove link" and "Delete" are the same operation. + if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) + { + items.push_back(std::string("Remove Link")); + } + else + { + items.push_back(std::string("Delete")); + } + + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } +} + +void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items) +{ + const LLInventoryObject *obj = getInventoryObject(); + const BOOL is_link = (obj && obj->getIsLinkType()); + + if (is_link) + items.push_back(std::string("Open Original")); + else + items.push_back(std::string("Open")); +} + +// *TODO: remove this +BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const +{ + BOOL rv = FALSE; + + const LLInventoryObject* obj = getInventoryObject(); + + if(obj) + { + *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); + if(*type == DAD_NONE) + { + return FALSE; + } + + *id = obj->getUUID(); + //object_ids.put(obj->getUUID()); + + if (*type == DAD_CATEGORY) + { + LLInventoryModelBackgroundFetch::instance().start(obj->getUUID()); + } + + rv = TRUE; + } + + return rv; +} + +LLInventoryObject* LLInvFVBridge::getInventoryObject() const +{ + LLInventoryObject* obj = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + obj = (LLInventoryObject*)model->getObject(mUUID); + } + return obj; +} + +LLInventoryModel* LLInvFVBridge::getInventoryModel() const +{ + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + return panel ? panel->getModel() : NULL; +} + +BOOL LLInvFVBridge::isItemInTrash() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + return model->isObjectDescendentOf(mUUID, trash_id); +} + +BOOL LLInvFVBridge::isLinkedObjectInTrash() const +{ + if (isItemInTrash()) return TRUE; + + const LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); + } + return FALSE; +} + +BOOL LLInvFVBridge::isLinkedObjectMissing() const +{ + const LLInventoryObject *obj = getInventoryObject(); + if (!obj) + { + return TRUE; + } + if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType())) + { + return TRUE; + } + return FALSE; +} + +BOOL LLInvFVBridge::isAgentInventory() const +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); +} + +BOOL LLInvFVBridge::isCOFFolder() const +{ + return LLAppearanceMgr::instance().getIsInCOF(mUUID); +} + +BOOL LLInvFVBridge::isItemPermissive() const +{ + return FALSE; +} + +// static +void LLInvFVBridge::changeItemParent(LLInventoryModel* model, + LLViewerInventoryItem* item, + const LLUUID& new_parent_id, + BOOL restamp) +{ + change_item_parent(model, item, new_parent_id, restamp); +} + +// static +void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, + LLViewerInventoryCategory* cat, + const LLUUID& new_parent_id, + BOOL restamp) +{ + change_category_parent(model, cat, new_parent_id, restamp); +} + +LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + U32 flags) +{ + LLInvFVBridge* new_listener = NULL; + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLTextureBridge(inventory, root, uuid, inv_type); + break; + + case LLAssetType::AT_SOUND: + if(!(inv_type == LLInventoryType::IT_SOUND)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLSoundBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_LANDMARK: + if(!(inv_type == LLInventoryType::IT_LANDMARK)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLLandmarkBridge(inventory, root, uuid, flags); + break; + + case LLAssetType::AT_CALLINGCARD: + if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLCallingCardBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_SCRIPT: + if(!(inv_type == LLInventoryType::IT_LSL)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLItemBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_OBJECT: + if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLObjectBridge(inventory, root, uuid, inv_type, flags); + break; + + case LLAssetType::AT_NOTECARD: + if(!(inv_type == LLInventoryType::IT_NOTECARD)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLNotecardBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_ANIMATION: + if(!(inv_type == LLInventoryType::IT_ANIMATION)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLAnimationBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_GESTURE: + if(!(inv_type == LLInventoryType::IT_GESTURE)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLGestureBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_LSL_TEXT: + if(!(inv_type == LLInventoryType::IT_LSL)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLLSLTextBridge(inventory, root, uuid); + break; + + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + if(!(inv_type == LLInventoryType::IT_WEARABLE)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, (LLWearableType::EType)flags); + break; + case LLAssetType::AT_CATEGORY: + if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) + { + // Create a link folder handler instead. + new_listener = new LLLinkFolderBridge(inventory, root, uuid); + break; + } + new_listener = new LLFolderBridge(inventory, root, uuid); + break; + case LLAssetType::AT_LINK: + case LLAssetType::AT_LINK_FOLDER: + // Only should happen for broken links. + new_listener = new LLLinkItemBridge(inventory, root, uuid); + break; + default: + llinfos << "Unhandled asset type (llassetstorage.h): " + << (S32)asset_type << llendl; + break; + } + + if (new_listener) + { + new_listener->mInvType = inv_type; + } + + return new_listener; +} + +void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) +{ + LLInventoryCategory* cat = model->getCategory(uuid); + if (cat) + { + model->purgeDescendentsOf(uuid); + model->notifyObservers(); + } + LLInventoryObject* obj = model->getObject(uuid); + if (obj) + { + model->purgeObject(uuid); + model->notifyObservers(); + } +} + +BOOL LLInvFVBridge::canShare() const +{ + if (!isAgentInventory()) return FALSE; + + const LLInventoryModel* model = getInventoryModel(); + if (!model) return FALSE; + + const LLViewerInventoryItem *item = model->getItem(mUUID); + if (item) + { + if (!LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) + return FALSE; + return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item); + } + + // Categories can be given. + if (model->getCategory(mUUID)) return TRUE; + + return FALSE; +} + +// +=================================================+ +// | InventoryFVBridgeBuilder | +// +=================================================+ +LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + U32 flags /* = 0x00 */) const +{ + return LLInvFVBridge::createBridge(asset_type, + actual_asset_type, + inv_type, + inventory, + root, + uuid, + flags); +} + +// +=================================================+ +// | LLItemBridge | +// +=================================================+ + +void LLItemBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(); + } + + if ("open" == action || "open_original" == action) + { + openItem(); + return; + } + else if ("properties" == action) + { + showProperties(); + return; + } + else if ("purge" == action) + { + purgeItem(model, mUUID); + return; + } + else if ("restoreToWorld" == action) + { + restoreToWorld(); + return; + } + else if ("restore" == action) + { + restoreItem(); + return; + } + else if ("copy_uuid" == action) + { + // Single item only + LLViewerInventoryItem* item = static_cast(getItem()); + if(!item) return; + LLUUID asset_id = item->getProtectedAssetUUID(); + std::string buffer; + asset_id.toString(buffer); + + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); + return; + } + else if ("copy" == action) + { + copyToClipboard(); + return; + } + else if ("cut" == action) + { + cutToClipboard(); + return; + } + else if ("paste" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteFromClipboard(); + return; + } + else if ("paste_link" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteLinkFromClipboard(); + return; + } +} + +void LLItemBridge::selectItem() +{ + LLViewerInventoryItem* item = static_cast(getItem()); + if(item && !item->isFinished()) + { + item->fetchFromServer(); + } +} + +void LLItemBridge::restoreItem() +{ + LLViewerInventoryItem* item = static_cast(getItem()); + if(item) + { + LLInventoryModel* model = getInventoryModel(); + const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); + // do not restamp on restore. + LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); + } +} + +void LLItemBridge::restoreToWorld() +{ + //Similar functionality to the drag and drop rez logic + bool remove_from_inventory = false; + + LLViewerInventoryItem* itemp = static_cast(getItem()); + if (itemp) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("RezRestoreToWorld"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_InventoryData); + itemp->packMessage(msg); + msg->sendReliable(gAgent.getRegion()->getHost()); + + //remove local inventory copy, sim will deal with permissions and removing the item + //from the actual inventory if its a no-copy etc + if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + remove_from_inventory = true; + } + + // Check if it's in the trash. (again similar to the normal rez logic) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) + { + remove_from_inventory = true; + } + } + + if(remove_from_inventory) + { + gInventory.deleteObject(itemp->getUUID()); + gInventory.notifyObservers(); + } +} + +void LLItemBridge::gotoItem() +{ + LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); + if (active_panel) + { + active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); + } + } +} + +LLUIImagePtr LLItemBridge::getIcon() const +{ + LLInventoryObject *obj = getInventoryObject(); + if (obj) + { + return LLInventoryIcon::getIcon(obj->getType(), + LLInventoryType::IT_NONE, + mIsLink); + } + + return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT); +} + +PermissionMask LLItemBridge::getPermissionMask() const +{ + LLViewerInventoryItem* item = getItem(); + PermissionMask perm_mask = 0; + if (item) perm_mask = item->getPermissionMask(); + return perm_mask; +} + +const std::string& LLItemBridge::getDisplayName() const +{ + if(mDisplayName.empty()) + { + buildDisplayName(getItem(), mDisplayName); + } + return mDisplayName; +} + +void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +{ + if(item) + { + name.assign(item->getName()); + } + else + { + name.assign(LLStringUtil::null); + } +} + +LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const +{ + U8 font = LLFontGL::NORMAL; + const LLViewerInventoryItem* item = getItem(); + + if (get_is_item_worn(mUUID)) + { + // llinfos << "BOLD" << llendl; + font |= LLFontGL::BOLD; + } + else if(item && item->getIsLinkType()) + { + font |= LLFontGL::ITALIC; + } + + return (LLFontGL::StyleFlags)font; +} + +std::string LLItemBridge::getLabelSuffix() const +{ + // String table is loaded before login screen and inventory items are + // loaded after login, so LLTrans should be ready. + static std::string NO_COPY =LLTrans::getString("no_copy"); + static std::string NO_MOD = LLTrans::getString("no_modify"); + static std::string NO_XFER = LLTrans::getString("no_transfer"); + static std::string LINK = LLTrans::getString("link"); + static std::string BROKEN_LINK = LLTrans::getString("broken_link"); + std::string suffix; + LLInventoryItem* item = getItem(); + if(item) + { + // it's a bit confusing to put nocopy/nomod/etc on calling cards. + if(LLAssetType::AT_CALLINGCARD != item->getType() + && item->getPermissions().getOwner() == gAgent.getID()) + { + BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); + if (broken_link) return BROKEN_LINK; + + BOOL link = item->getIsLinkType(); + if (link) return LINK; + + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + if (!copy) + { + suffix += NO_COPY; + } + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + if (!mod) + { + suffix += NO_MOD; + } + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + if (!xfer) + { + suffix += NO_XFER; + } + } + } + return suffix; +} + +time_t LLItemBridge::getCreationDate() const +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + return item->getCreationDate(); + } + return 0; +} + + +BOOL LLItemBridge::isItemRenameable() const +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + // (For now) Don't allow calling card rename since that may confuse users as to + // what the calling card points to. + if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) + { + return FALSE; + } + + if (!item->isFinished()) // EXT-8662 + { + return FALSE; + } + +// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g + if ( (rlv_handler_t::isEnabled()) && (!RlvFolderLocks::instance().canRenameItem(mUUID)) ) + { + return FALSE; + } +// [/RLVa:KB] + + return (item->getPermissions().allowModifyBy(gAgent.getID())); + } + return FALSE; +} + +BOOL LLItemBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLPreview::dirty(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryItem* item = getItem(); + if(item && (item->getName() != new_name)) + { + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + buildDisplayName(new_item, mDisplayName); + new_item->updateServer(FALSE); + model->updateItem(new_item); + + model->notifyObservers(); + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + + +BOOL LLItemBridge::removeItem() +{ + if(!isItemRemovable()) + { + return FALSE; + } + + + // move it to the trash + LLPreview::hide(mUUID, TRUE); + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLViewerInventoryItem* item = getItem(); + if (!item) return FALSE; + + // Already in trash + if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE; + + LLNotification::Params params("ConfirmItemDeleteHasLinks"); + params.functor.function(boost::bind(&LLItemBridge::confirmRemoveItem, this, _1, _2)); + + // Check if this item has any links. If generic inventory linking is enabled, + // we can't do this check because we may have items in a folder somewhere that is + // not yet in memory, so we don't want false negatives. (If disabled, then we + // know we only have links in the Outfits folder which we explicitly fetch.) +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-06-01 (Catznip-2.2.0a) | Added: Catznip-2.0.1a + // Users move folders around and reuse links that way... if we know something has links then it's just bad not to warn them :| +// [/SL:KB] +// if (!gSavedSettings.getBOOL("InventoryLinking")) + { + if (!item->getIsLinkType()) + { + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + LLLinkedItemIDMatches is_linked_item_match(mUUID); + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), + cat_array, + item_array, + LLInventoryModel::INCLUDE_TRASH, + is_linked_item_match); + + const U32 num_links = cat_array.size() + item_array.size(); + if (num_links > 0) + { + // Warn if the user is will break any links when deleting this item. + LLNotifications::instance().add(params); + return FALSE; + } + } + } + + LLNotifications::instance().forceResponse(params, 0); + return TRUE; +} + +BOOL LLItemBridge::confirmRemoveItem(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return FALSE; + + LLInventoryModel* model = getInventoryModel(); + if (!model) return FALSE; + + LLViewerInventoryItem* item = getItem(); + if (!item) return FALSE; + + const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + // if item is not already in trash + if(item && !model->isObjectDescendentOf(mUUID, trash_id)) + { + // move to trash, and restamp + LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); + // delete was successful + return TRUE; + } + return FALSE; +} + +BOOL LLItemBridge::isItemCopyable() const +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { +/* + // Can't copy worn objects. DEV-15183 + if(get_is_item_worn(mUUID)) + { + return FALSE; + } + +*/ + +// // You can never copy a link. +// if (item->getIsLinkType()) +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + // We'll allow copying a link if: + // - its target is available + // - it doesn't point to another link [see LLViewerInventoryItem::getLinkedItem() which returns NULL in that case] + if ( (item->getIsLinkType()) && (!item->getLinkedItem()) ) +// [/SL:KB] + { + return FALSE; + } + + // All items can be copied in god mode since you can + // at least paste-as-link the item, though you + // still may not be able paste the item. +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + // User can copy the item if: + // - the item (or its target in the case of a link) is "copy" + // - and/or if the item (or its target in the case of a link) has a linkable asset type + // NOTE: we do *not* want to return TRUE on everything like LL seems to do in SL-2.1.0 because not all types are "linkable" + return (item->getPermissions().allowCopyBy(gAgent.getID())) || (LLAssetType::lookupCanLink(item->getType())); +// [/SL:KB] +// return TRUE; + // return (item->getPermissions().allowCopyBy(gAgent.getID())); + } + return FALSE; +} + +BOOL LLItemBridge::copyToClipboard() const +{ + if(isItemCopyable()) + { + LLInventoryClipboard::instance().add(mUUID); + return TRUE; + } + return FALSE; +} + +LLViewerInventoryItem* LLItemBridge::getItem() const +{ + LLViewerInventoryItem* item = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + item = (LLViewerInventoryItem*)model->getItem(mUUID); + } + return item; +} + +BOOL LLItemBridge::isItemPermissive() const +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + return item->getIsFullPerm(); + } + return FALSE; +} + +bool LLItemBridge::isAddAction(std::string action) const +{ + return ("wear" == action || "attach" == action || "activate" == action); +} + +bool LLItemBridge::isRemoveAction(std::string action) const +{ + return ("take_off" == action || "detach" == action || "deactivate" == action); +} + +// +=================================================+ +// | LLFolderBridge | +// +=================================================+ + +LLHandle LLFolderBridge::sSelf; + +// Can be moved to another folder +BOOL LLFolderBridge::isItemMovable() const +{ + LLInventoryObject* obj = getInventoryObject(); + if(obj) + { + return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); + } + return FALSE; +} + +void LLFolderBridge::selectItem() +{ +} + + +// Iterate through a folder's children to determine if +// all the children are removable. +class LLIsItemRemovable : public LLFolderViewFunctor +{ +public: + LLIsItemRemovable() : mPassed(TRUE) {} + virtual void doFolder(LLFolderViewFolder* folder) + { + mPassed &= folder->getListener()->isItemRemovable(); + } + virtual void doItem(LLFolderViewItem* item) + { + mPassed &= item->getListener()->isItemRemovable(); + } + BOOL mPassed; +}; + +// Can be destroyed (or moved to trash) +BOOL LLFolderBridge::isItemRemovable() const +{ + if (!get_is_category_removable(getInventoryModel(), mUUID)) + { + return FALSE; + } + + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewFolder* folderp = dynamic_cast(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); + if (folderp) + { + LLIsItemRemovable folder_test; + folderp->applyFunctorToChildren(folder_test); + if (!folder_test.mPassed) + { + return FALSE; + } + } + + return TRUE; +} + +BOOL LLFolderBridge::isUpToDate() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if( !category ) + { + return FALSE; + } + + return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; +} + +BOOL LLFolderBridge::isItemCopyable() const +{ + if (gSavedSettings.getBOOL("InventoryLinking")) + { + // Can copy folders to paste-as-link, but not for straight paste. + return TRUE; + } + return FALSE; +} + +BOOL LLFolderBridge::copyToClipboard() const +{ + if(isItemCopyable()) + { + LLInventoryClipboard::instance().add(mUUID); + return TRUE; + } + return FALSE; +} + +BOOL LLFolderBridge::isClipboardPasteable() const +{ + if ( ! LLInvFVBridge::isClipboardPasteable() ) + return FALSE; + + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) + { + LLInventoryModel* model = getInventoryModel(); + if ( !model ) + { + return FALSE; + } + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + const LLViewerInventoryCategory *current_cat = getCategory(); + + // Search for the direct descendent of current Friends subfolder among all pasted items, + // and return false if is found. + for(S32 i = objects.count() - 1; i >= 0; --i) + { + const LLUUID &obj_id = objects.get(i); + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + + } + return TRUE; +} + +BOOL LLFolderBridge::isClipboardPasteableAsLink() const +{ + // Check normal paste-as-link permissions + if (!LLInvFVBridge::isClipboardPasteableAsLink()) + { + return FALSE; + } + + const LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + const LLViewerInventoryCategory *current_cat = getCategory(); + if (current_cat) + { + const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); + const LLUUID ¤t_cat_id = current_cat->getUUID(); + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &obj_id = objects.get(i); + const LLInventoryCategory *cat = model->getCategory(obj_id); + if (cat) + { + const LLUUID &cat_id = cat->getUUID(); + // Don't allow recursive pasting + if ((cat_id == current_cat_id) || + model->isObjectDescendentOf(current_cat_id, cat_id)) + { + return FALSE; + } + } + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( is_in_friend_folder ) + { + // If object is direct descendent of current Friends subfolder than return false. + // Note: We can't use 'const LLInventoryCategory *cat', because it may be null + // in case type of obj_id is LLInventoryItem. + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + } + } + return TRUE; + +} + +BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, + BOOL drop) +{ + + LLInventoryModel* model = getInventoryModel(); + + if (!inv_cat) return FALSE; // shouldn't happen, but in case item is incorrectly parented in which case inv_cat will be NULL + if (!model) return FALSE; + if (!isAgentAvatarValid()) return FALSE; + if (!isAgentInventory()) return FALSE; // cannot drag categories into library + + + // check to make sure source is agent inventory, and is represented there. + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) + && (LLToolDragAndDrop::SOURCE_AGENT == source); + + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + + BOOL accept = FALSE; + if (is_agent_inventory) + { + const LLUUID &cat_id = inv_cat->getUUID(); + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); + + const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); + const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); + const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); + + //-------------------------------------------------------------------------------- + // Determine if folder can be moved. + // + + BOOL is_movable = TRUE; + if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + is_movable = FALSE; + if (move_is_into_outfit) + is_movable = FALSE; + if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) + is_movable = FALSE; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); + for (S32 i=0; i < descendent_categories.count(); ++i) + { + LLInventoryCategory* category = descendent_categories[i]; + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + { + // Can't move "special folders" (e.g. Textures Folder). + is_movable = FALSE; + break; + } + } + if (move_is_into_trash) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (get_is_item_worn(item->getUUID())) + { + is_movable = FALSE; + break; // It's generally movable, but not into the trash. + } + } + } + if (move_is_into_landmarks) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLViewerInventoryItem* item = descendent_items[i]; + + // Don't move anything except landmarks and categories into Landmarks folder. + // We use getType() instead of getActua;Type() to allow links to landmarks and folders. + if (LLAssetType::AT_LANDMARK != item->getType() && LLAssetType::AT_CATEGORY != item->getType()) + { + is_movable = FALSE; + break; // It's generally movable, but not into Landmarks. + } + } + } + +// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g + if ( (is_movable) && (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) ) + { + is_movable = RlvFolderLocks::instance().canMoveFolder(cat_id, mUUID); + } +// [/RLVa:KB] + + // + //-------------------------------------------------------------------------------- + + accept = is_movable + && (mUUID != cat_id) // Can't move a folder into itself + && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing + && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity + if (accept && drop) + { + // Look for any gestures and deactivate them + if (move_is_into_trash) + { + for (S32 i=0; i < descendent_items.count(); i++) + { + LLInventoryItem* item = descendent_items[i]; + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(item->getUUID())) + { + LLGestureMgr::instance().deactivateGesture(item->getUUID()); + } + } + } + // if target is an outfit or current outfit folder we use link + if (move_is_into_current_outfit || move_is_into_outfit) + { + if (inv_cat->getPreferredType() == LLFolderType::FT_NONE) + { + if (move_is_into_current_outfit) + { + // traverse category and add all contents to currently worn. + BOOL append = true; + LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append); + } + else + { + // Recursively create links in target outfit. + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); + LLAppearanceMgr::instance().linkAll(mUUID,items,NULL); + } + } + else + { +#if SUPPORT_ENSEMBLES + // BAP - should skip if dup. + if (move_is_into_current_outfit) + { + LLAppearanceMgr::instance().addEnsembleLink(inv_cat); + } + else + { + LLPointer cb = NULL; + const std::string empty_description = ""; + link_inventory_item( + gAgent.getID(), + inv_cat->getUUID(), + mUUID, + inv_cat->getName(), + empty_description, + LLAssetType::AT_LINK_FOLDER, + cb); + } +#endif + } + } + else + { + + // Reparent the folder and restamp children if it's moving + // into trash. + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + move_is_into_trash); + } + } + } + else if (LLToolDragAndDrop::SOURCE_WORLD == source) + { + // content category has same ID as object itself + LLUUID object_id = inv_cat->getUUID(); + LLUUID category_id = mUUID; + accept = move_inv_category_world_to_agent(object_id, category_id, drop); + } + else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + // Accept folders that contain complete outfits. + accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID()); + + if (accept && drop) + { + LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, true, false); + } + } + + return accept; +} + +void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) +{ + const char* dialog = NULL; + if (object->flagScripted()) + { + dialog = "MoveInventoryFromScriptedObject"; + } + else + { + dialog = "MoveInventoryFromObject"; + } + LLNotificationsUtil::add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); +} + +// Move/copy all inventory items from the Contents folder of an in-world +// object to the agent's inventory, inside a given category. +BOOL move_inv_category_world_to_agent(const LLUUID& object_id, + const LLUUID& category_id, + BOOL drop, + void (*callback)(S32, void*), + void* user_data) +{ + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + // content category has same ID as object itself + LLViewerObject* object = gObjectList.findObject(object_id); + if(!object) + { + llinfos << "Object not found for drop." << llendl; + return FALSE; + } + + // this folder is coming from an object, as there is only one folder in an object, the root, + // we need to collect the entire contents and handle them as a group + LLInventoryObject::object_list_t inventory_objects; + object->getInventoryContents(inventory_objects); + + if (inventory_objects.empty()) + { + llinfos << "Object contents not found for drop." << llendl; + return FALSE; + } + + BOOL accept = TRUE; + BOOL is_move = FALSE; + + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLInventoryObject::object_list_t::iterator it = inventory_objects.begin(); + LLInventoryObject::object_list_t::iterator end = inventory_objects.end(); + for ( ; it != end; ++it) + { + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); + if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) +// || gAgent.isGodlike()) + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + is_move = TRUE; + accept = TRUE; + } + else + { + accept = FALSE; + break; + } + } + + if(drop && accept) + { + it = inventory_objects.begin(); + LLInventoryObject::object_list_t::iterator first_it = inventory_objects.begin(); + LLMoveInv* move_inv = new LLMoveInv; + move_inv->mObjectID = object_id; + move_inv->mCategoryID = category_id; + move_inv->mCallback = callback; + move_inv->mUserData = user_data; + + for ( ; it != end; ++it) + { + two_uuids_t two(category_id, (*it)->getUUID()); + move_inv->mMoveList.push_back(two); + } + + if(is_move) + { + // Callback called from within here. + warn_move_inventory(object, move_inv); + } + else + { + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + } + } + return accept; +} + +//Used by LLFolderBridge as callback for directory recursion. +class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver +{ +public: + LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : + LLInventoryFetchItemsObserver(ids), + mCopyItems(false) + { }; + LLRightClickInventoryFetchObserver(const uuid_vec_t& ids, + const LLUUID& cat_id, + bool copy_items) : + LLInventoryFetchItemsObserver(ids), + mCatID(cat_id), + mCopyItems(copy_items) + { }; + virtual void done() + { + // we've downloaded all the items, so repaint the dialog + LLFolderBridge::staticFolderOptionsMenu(); + + gInventory.removeObserver(this); + delete this; + } + + +protected: + LLUUID mCatID; + bool mCopyItems; + +}; + +//Used by LLFolderBridge as callback for directory recursion. +class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver +{ +public: + LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids, + bool copy_items) : + LLInventoryFetchDescendentsObserver(ids), + mCopyItems(copy_items) + {} + ~LLRightClickInventoryFetchDescendentsObserver() {} + virtual void done(); +protected: + bool mCopyItems; +}; + +void LLRightClickInventoryFetchDescendentsObserver::done() +{ + // Avoid passing a NULL-ref as mCompleteFolders.front() down to + // gInventory.collectDescendents() + if( mComplete.empty() ) + { + llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } + + // What we do here is get the complete information on the items in + // the library, and set up an observer that will wait for that to + // happen. + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(mComplete.front(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + S32 count = item_array.count(); +#if 0 // HACK/TODO: Why? + // This early causes a giant menu to get produced, and doesn't seem to be needed. + if(!count) + { + llwarns << "Nothing fetched in category " << mCompleteFolders.front() + << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } +#endif + + uuid_vec_t ids; + for(S32 i = 0; i < count; ++i) + { + ids.push_back(item_array.get(i)->getUUID()); + } + + LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems); + + // clean up, and remove this as an observer since the call to the + // outfit could notify observers and throw us into an infinite + // loop. + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + + // increment busy count and either tell the inventory to check & + // call done, or add this object to the inventory for observation. + inc_busy_count(); + + // do the fetch + outfit->startFetch(); + outfit->done(); //Not interested in waiting and this will be right 99% of the time. +//Uncomment the following code for laggy Inventory UI. +/* if(outfit->isFinished()) + { + // everything is already here - call done. + outfit->done(); + } + else + { + // it's all on it's way - add an observer, and the inventory + // will call done for us when everything is here. + gInventory.addObserver(outfit); + }*/ +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryWearObserver +// +// Observer for "copy and wear" operation to support knowing +// when the all of the contents have been added to inventory. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryCopyAndWearObserver : public LLInventoryObserver +{ +public: + LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) : + mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} + virtual ~LLInventoryCopyAndWearObserver() {} + virtual void changed(U32 mask); + +protected: + LLUUID mCatID; + int mContentsCount; + BOOL mFolderAdded; +}; + + + +void LLInventoryCopyAndWearObserver::changed(U32 mask) +{ + if((mask & (LLInventoryObserver::ADD)) != 0) + { + if (!mFolderAdded) + { + const std::set& changed_items = gInventory.getChangedIDs(); + + std::set::const_iterator id_it = changed_items.begin(); + std::set::const_iterator id_end = changed_items.end(); + for (;id_it != id_end; ++id_it) + { + if ((*id_it) == mCatID) + { + mFolderAdded = TRUE; + break; + } + } + } + + if (mFolderAdded) + { + LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); + + if (NULL == category) + { + llwarns << "gInventory.getCategory(" << mCatID + << ") was NULL" << llendl; + } + else + { + if (category->getDescendentCount() == + mContentsCount) + { + gInventory.removeObserver(this); + LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, FALSE); + delete this; + } + } + } + + } +} + + + +void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("open" == action) + { + LLFolderViewFolder *f = dynamic_cast(mRoot->getItemByID(mUUID)); + if (f) + { + f->setOpen(TRUE); + } + + return; + } + else if ("paste" == action) + { + pasteFromClipboard(); + return; + } + else if ("paste_link" == action) + { + pasteLinkFromClipboard(); + return; + } + else if ("properties" == action) + { + showProperties(); + return; + } + else if ("replaceoutfit" == action) + { + modifyOutfit(FALSE); + return; + } +#if SUPPORT_ENSEMBLES + else if ("wearasensemble" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + LLAppearanceMgr::instance().addEnsembleLink(cat,true); + return; + } +#endif + else if ("addtooutfit" == action) + { + modifyOutfit(TRUE); + return; + } +//-TT Patch: ReplaceWornItemsOnly + else if ("replaceitems" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + gInventory.wearItemsOnAvatar(cat); + // modifyOutfit(TRUE, TRUE); + return; + } +//-TT + else if ("copy" == action) + { + copyToClipboard(); + return; + } + else if ("cut" == action) + { + cutToClipboard(); + return; + } + else if ("removefromoutfit" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + remove_inventory_category_from_avatar ( cat ); + return; + } + else if ("purge" == action) + { + purgeItem(model, mUUID); + return; + } + else if ("restore" == action) + { + restoreItem(); + return; + } +#ifndef LL_RELEASE_FOR_DOWNLOAD + else if ("delete_system_folder" == action) + { + removeSystemFolder(); + } +#endif +} + +void LLFolderBridge::openItem() +{ + lldebugs << "LLFolderBridge::openItem()" << llendl; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + if(mUUID.isNull()) return; + bool fetching_inventory = model->fetchDescendentsOf(mUUID); + // Only change folder type if we have the folder contents. + if (!fetching_inventory) + { + // Disabling this for now, it's causing crash when new items are added to folders + // since folder type may change before new item item has finished processing. + // determineFolderType(); + } +} + +void LLFolderBridge::closeItem() +{ + determineFolderType(); +} + +void LLFolderBridge::determineFolderType() +{ + if (isUpToDate()) + { + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryCategory* category = model->getCategory(mUUID); + if (category) + { + category->determineFolderType(); + } + } +} + +BOOL LLFolderBridge::isItemRenameable() const +{ + return get_is_category_renameable(getInventoryModel(), mUUID); +} + +void LLFolderBridge::restoreItem() +{ + LLViewerInventoryCategory* cat; + cat = (LLViewerInventoryCategory*)getCategory(); + if(cat) + { + LLInventoryModel* model = getInventoryModel(); + const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); + // do not restamp children on restore + LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); + } +} + +LLFolderType::EType LLFolderBridge::getPreferredType() const +{ + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + preferred_type = cat->getPreferredType(); + } + + return preferred_type; +} + +// Icons for folders are based on the preferred type +LLUIImagePtr LLFolderBridge::getIcon() const +{ + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + preferred_type = cat->getPreferredType(); + } + return getIcon(preferred_type); +} + +// static +LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) +{ + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); +} + +LLUIImagePtr LLFolderBridge::getOpenIcon() const +{ + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); + +} + +BOOL LLFolderBridge::renameItem(const std::string& new_name) +{ + rename_category(getInventoryModel(), mUUID, new_name); + + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + +BOOL LLFolderBridge::removeItem() +{ + if(!isItemRemovable()) + { + return FALSE; + } + const LLViewerInventoryCategory *cat = getCategory(); + + LLSD payload; + LLSD args; + args["FOLDERNAME"] = cat->getName(); + + LLNotification::Params params("ConfirmDeleteProtectedCategory"); + params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); + LLNotifications::instance().forceResponse(params, 0); + return TRUE; +} + + +BOOL LLFolderBridge::removeSystemFolder() +{ + const LLViewerInventoryCategory *cat = getCategory(); + if (!LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + return FALSE; + } + + LLSD payload; + LLSD args; + args["FOLDERNAME"] = cat->getName(); + + LLNotification::Params params("ConfirmDeleteProtectedCategory"); + params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); + { + LLNotifications::instance().add(params); + } + return TRUE; +} + +bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + // if they choose delete, do it. Otherwise, don't do anything + if(option == 0) + { + // move it to the trash + LLPreview::hide(mUUID); + remove_category(getInventoryModel(), mUUID); + return TRUE; + } + return FALSE; +} + +void LLFolderBridge::pasteFromClipboard() +{ + LLInventoryModel* model = getInventoryModel(); + if(model && isClipboardPasteable()) + { + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + + const LLUUID parent_id(mUUID); + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + for (LLDynamicArray::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); + if (item) + { + if (move_is_into_current_outfit || move_is_into_outfit) + { + if (can_move_to_outfit(item, move_is_into_current_outfit)) + { + dropToOutfit(item, move_is_into_current_outfit); + } + } + else if(LLInventoryClipboard::instance().isCutMode()) + { + // move_inventory_item() is not enough, + //we have to update inventory locally too + LLViewerInventoryItem* viitem = dynamic_cast(item); + llassert(viitem); + if (viitem) + { + changeItemParent(model, viitem, parent_id, FALSE); + } + } + else + { +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + if (item->getPermissions().allowCopyBy(gAgent.getID())) + { +// [/SL:KB] + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + parent_id, + std::string(), + LLPointer(NULL)); +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + } + else if (LLAssetType::lookupIsLinkType(item->getActualType())) + { + link_inventory_item( + gAgent.getID(), + item->getLinkedUUID(), + parent_id, + item->getName(), + item->getDescription(), + item->getActualType(), + LLPointer(NULL)); + } +// [/SL:KB] + } + } + + LLInventoryCategory *cat = model->getCategory(item_id); + if (cat) + { + if (move_is_into_current_outfit || move_is_into_outfit) + { + // do something clever to add folder to outfit + } + else if(LLInventoryClipboard::instance().isCutMode()) + { + // move_inventory_item() is not enough, + //we have to update inventory locally too + LLViewerInventoryCategory* vicat = dynamic_cast(cat); + llassert(vicat); + if (vicat) + { + changeCategoryParent(model, vicat, parent_id, FALSE); + } + } + else + { + // implemement copy_inventory_category + } + } + + } + } +} + +void LLFolderBridge::pasteLinkFromClipboard() +{ + LLInventoryModel* model = getInventoryModel(); + if(model) + { + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + + const LLUUID parent_id(mUUID); + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + for (LLDynamicArray::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + const LLUUID &object_id = (*iter); + if (move_is_into_current_outfit || move_is_into_outfit) + { + LLInventoryItem *item = model->getItem(object_id); + if (item && can_move_to_outfit(item, move_is_into_current_outfit)) + { + dropToOutfit(item, move_is_into_current_outfit); + } + } + else if (LLInventoryCategory *cat = model->getCategory(object_id)) + { + const std::string empty_description = ""; + link_inventory_item( + gAgent.getID(), + cat->getUUID(), + parent_id, + cat->getName(), + empty_description, + LLAssetType::AT_LINK_FOLDER, + LLPointer(NULL)); + } + else if (LLInventoryItem *item = model->getItem(object_id)) + { + link_inventory_item( + gAgent.getID(), + item->getLinkedUUID(), + parent_id, + item->getName(), + item->getDescription(), + LLAssetType::AT_LINK, + LLPointer(NULL)); + } + } + } +} + +void LLFolderBridge::staticFolderOptionsMenu() +{ + LLFolderBridge* selfp = sSelf.get(); + if (selfp) + { + selfp->folderOptionsMenu(); + } +} + +void LLFolderBridge::folderOptionsMenu() +{ + menuentry_vec_t disabled_items; + + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + + const LLInventoryCategory* category = model->getCategory(mUUID); + if(!category) return; + + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id == mUUID) return; + if (isItemInTrash()) return; + if (!isAgentInventory()) return; + + LLFolderType::EType type = category->getPreferredType(); + const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); + // BAP change once we're no longer treating regular categories as ensembles. + const bool is_ensemble = (type == LLFolderType::FT_NONE || + LLFolderType::lookupIsEnsembleType(type)); +// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.5.0a) | Added: Catznip-2.4.0e + const bool is_outfit = (type == LLFolderType::FT_OUTFIT); +// [/SL:KB] + + // Only enable calling-card related options for non-system folders. + if (!is_system_folder) + { + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) + { + mItems.push_back(std::string("Calling Card Separator")); + mItems.push_back(std::string("Conference Chat Folder")); + mItems.push_back(std::string("IM All Contacts In Folder")); + } + } + +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (LLFolderType::lookupIsProtectedType(type)) + { + mItems.push_back(std::string("Delete System Folder")); + } +#endif + + // wearables related functionality for folders. + //is_wearable + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (mWearables || + checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mItems.push_back(std::string("Folder Wearables Separator")); + + // Only enable add/replace outfit for non-system folders. + if (!is_system_folder) + { + // Adding an outfit onto another (versus replacing) doesn't make sense. + if (type != LLFolderType::FT_OUTFIT) + { + mItems.push_back(std::string("Add To Outfit")); +//-TT Patch: ReplaceWornItemsOnly + mItems.push_back(std::string("Wear Items")); +//-TT + } + mItems.push_back(std::string("Replace Outfit")); + } + if (is_ensemble) + { + mItems.push_back(std::string("Wear As Ensemble")); + } + mItems.push_back(std::string("Remove From Outfit")); + if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) + { + disabled_items.push_back(std::string("Remove From Outfit")); + } +// if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) +// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.5.0a) | Added: Catznip-2.4.0e + if ( ((is_outfit) && (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))) || + ((!is_outfit) && (gAgentWearables.isCOFChangeInProgress())) ) +// [/SL:KB] + { + disabled_items.push_back(std::string("Replace Outfit")); + } + mItems.push_back(std::string("Outfit Separator")); + } + LLMenuGL* menup = dynamic_cast(mMenu.get()); + if (menup) + { + hide_context_entries(*menup, mItems, disabled_items, TRUE); + + // Reposition the menu, in case we're adding items to an existing menu. + menup->needsArrange(); + menup->arrangeAndClear(); + } +} + +BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + model->collectDescendentsIf(mUUID, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_type); + return ((item_array.count() > 0) ? TRUE : FALSE ); +} + +// Flags unused +void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + mItems.clear(); + mDisabledItems.clear(); + + lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; + +// menuentry_vec_t disabled_items; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + + if (lost_and_found_id == mUUID) + { + // This is the lost+found folder. + mItems.push_back(std::string("Empty Lost And Found")); + + mDisabledItems.push_back(std::string("New Folder")); + mDisabledItems.push_back(std::string("New Script")); + mDisabledItems.push_back(std::string("New Note")); + mDisabledItems.push_back(std::string("New Gesture")); + mDisabledItems.push_back(std::string("New Clothes")); + mDisabledItems.push_back(std::string("New Body Parts")); + } + + // clear out old menu and folder pointers + mMenu.markDead(); + sSelf.markDead(); + + if(trash_id == mUUID) + { + // This is the trash. + mItems.push_back(std::string("Empty Trash")); + } + else if(isItemInTrash()) + { + // This is a folder in the trash. + mItems.clear(); // clear any items that used to exist + addTrashContextMenuOptions(mItems, mDisabledItems); + } + else if(isAgentInventory()) // do not allow creating in library + { + LLViewerInventoryCategory *cat = getCategory(); + // BAP removed protected check to re-enable standard ops in untyped folders. + // Not sure what the right thing is to do here. + if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) + { + // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. + if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) + mItems.push_back(std::string("New Folder")); + mItems.push_back(std::string("New Script")); + mItems.push_back(std::string("New Note")); + mItems.push_back(std::string("New Gesture")); + mItems.push_back(std::string("New Clothes")); + mItems.push_back(std::string("New Body Parts")); + +#if SUPPORT_ENSEMBLES + // Changing folder types is an unfinished unsupported feature + // and can lead to unexpected behavior if enabled. + mItems.push_back(std::string("Change Type")); + const LLViewerInventoryCategory *cat = getCategory(); + if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + mDisabledItems.push_back(std::string("Change Type")); + } +#endif + getClipboardEntries(false, mItems, mDisabledItems, flags); + } + else + { + // Want some but not all of the items from getClipboardEntries for outfits. + if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) + { + mItems.push_back(std::string("Rename")); + + addDeleteContextMenuOptions(mItems, mDisabledItems); + // EXT-4030: disallow deletion of currently worn outfit + const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) + { + mDisabledItems.push_back(std::string("Delete")); + } + } + } + + //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 + mCallingCards = mWearables = FALSE; + + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (checkFolderForContentsOfType(model, is_callingcard)) + { + mCallingCards=TRUE; + } + + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mWearables=TRUE; + } + } + + // Preemptively disable system folder removal if more than one item selected. + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + mDisabledItems.push_back(std::string("Delete System Folder")); + } + + mItems.push_back(std::string("Share")); + if (!canShare()) + { + mDisabledItems.push_back(std::string("Share")); + } + + hide_context_entries(menu, mItems, mDisabledItems); + + // Add menu items that are dependent on the contents of the folder. + uuid_vec_t folders; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (category) + { + folders.push_back(category->getUUID()); + } + + mMenu = menu.getHandle(); + sSelf = getHandle(); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + fetch->startFetch(); + inc_busy_count(); + if(fetch->isFinished()) + { + // everything is already here - call done. + fetch->done(); + } + else + { + // it's all on its way - add an observer, and the inventory will call done for us when everything is here. + gInventory.addObserver(fetch); + } +} + +BOOL LLFolderBridge::hasChildren() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLInventoryModel::EHasChildren has_children; + has_children = gInventory.categoryHasChildren(mUUID); + return has_children != LLInventoryModel::CHILDREN_NO; +} + +BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + + //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; + BOOL accept = FALSE; + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_CALLINGCARD: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_CLOTHING: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + accept = dragItemIntoFolder(inv_item, drop); + break; + case DAD_LINK: + // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER. + // If we have an item of AT_LINK_FOLDER type we should process the linked + // category being dragged or dropped into folder. + if (inv_item && LLAssetType::AT_LINK_FOLDER == inv_item->getActualType()) + { + LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID()); + if (linked_category) + { + accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop); + } + } + else + { + accept = dragItemIntoFolder(inv_item, drop); + } + break; + case DAD_CATEGORY: + if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) + { + accept = FALSE; + } + else + { + accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); + } + break; + default: + break; + } + return accept; +} + +LLViewerInventoryCategory* LLFolderBridge::getCategory() const +{ + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); + } + return cat; +} + + +// static +void LLFolderBridge::pasteClipboard(void* user_data) +{ + LLFolderBridge* self = (LLFolderBridge*)user_data; + if(self) self->pasteFromClipboard(); +} + +void LLFolderBridge::createNewCategory(void* user_data) +{ + LLFolderBridge* bridge = (LLFolderBridge*)user_data; + if(!bridge) return; + LLInventoryPanel* panel = dynamic_cast(bridge->mInventoryPanel.get()); + if (!panel) return; + LLInventoryModel* model = panel->getModel(); + if(!model) return; + LLUUID id; + id = model->createNewCategory(bridge->getUUID(), + LLFolderType::FT_NONE, + LLStringUtil::null); + model->notifyObservers(); + + // At this point, the bridge has probably been deleted, but the + // view is still there. + panel->setSelection(id, TAKE_FOCUS_YES); +} + +void LLFolderBridge::createNewShirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT); +} + +void LLFolderBridge::createNewPants(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_PANTS); +} + +void LLFolderBridge::createNewShoes(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHOES); +} + +void LLFolderBridge::createNewSocks(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SOCKS); +} + +void LLFolderBridge::createNewJacket(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_JACKET); +} + +void LLFolderBridge::createNewSkirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SKIRT); +} + +void LLFolderBridge::createNewGloves(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_GLOVES); +} + +void LLFolderBridge::createNewUndershirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_UNDERSHIRT); +} + +void LLFolderBridge::createNewUnderpants(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_UNDERPANTS); +} + +void LLFolderBridge::createNewShape(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHAPE); +} + +void LLFolderBridge::createNewSkin(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SKIN); +} + +void LLFolderBridge::createNewHair(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_HAIR); +} + +void LLFolderBridge::createNewEyes(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES); +} + +// static +void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type) +{ + if(!bridge) return; + LLUUID parent_id = bridge->getUUID(); + LLAgentWearables::createWearable(type, false, parent_id); +} + +void LLFolderBridge::modifyOutfit(BOOL append) +//-TT Patch: ReplaceWornItemsOnly +{ + modifyOutfit(append, false); +} + +void LLFolderBridge::modifyOutfit(BOOL append, BOOL replace) +//-TT +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append, replace ); +} + +// helper stuff +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) +{ + LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; + LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if(option == 0 && object) + { + if (cat_and_wear && cat_and_wear->mWear) + { + LLInventoryObject::object_list_t inventory_objects; + object->getInventoryContents(inventory_objects); + int contents_count = inventory_objects.size()-1; //subtract one for containing folder + + LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); + gInventory.addObserver(inventoryObserver); + } + + two_uuids_list_t::iterator move_it; + for (move_it = move_inv->mMoveList.begin(); + move_it != move_inv->mMoveList.end(); + ++move_it) + { + object->moveInventory(move_it->first, move_it->second); + } + + // update the UI. + dialog_refresh_all(); + } + + if (move_inv->mCallback) + { + move_inv->mCallback(option, move_inv->mUserData); + } + + delete move_inv; + return false; +} + +// Returns true if the item can be moved to Current Outfit or any outfit folder. +static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) +{ + if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) && + (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) && + (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) && + (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT)) + { + return FALSE; + } + + if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID())) + { + return FALSE; + } + + return TRUE; +} + +// Returns TRUE if item is a landmark or a link to a landmark +// and can be moved to Favorites or Landmarks folder. +static BOOL can_move_to_landmarks(LLInventoryItem* inv_item) +{ + // Need to get the linked item to know its type because LLInventoryItem::getType() + // returns actual type AT_LINK for links, not the asset type of a linked item. + if (LLAssetType::AT_LINK == inv_item->getType()) + { + LLInventoryItem* linked_item = gInventory.getItem(inv_item->getLinkedUUID()); + if (linked_item) + { + return LLAssetType::AT_LANDMARK == linked_item->getType(); + } + } + + return LLAssetType::AT_LANDMARK == inv_item->getType(); +} + +void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) +{ + // use callback to rearrange favorite landmarks after adding + // to have new one placed before target (on which it was dropped). See EXT-4312. + LLPointer cb = new AddFavoriteLandmarkCallback(); + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (drag_over_item && drag_over_item->getListener()) + { + cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); + } + + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + mUUID, + std::string(), + cb); +} + +void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) +{ + // BAP - should skip if dup. + if (move_is_into_current_outfit) + { + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item->getUUID(), true, true); + } + else + { + LLPointer cb = NULL; + link_inventory_item( + gAgent.getID(), + inv_item->getLinkedUUID(), + mUUID, + inv_item->getName(), + inv_item->getDescription(), + LLAssetType::AT_LINK, + cb); + } +} + +// This is used both for testing whether an item can be dropped +// into the folder, as well as performing the actual drop, depending +// if drop == TRUE. +BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, + BOOL drop) +{ + LLInventoryModel* model = getInventoryModel(); + + if(!model || !inv_item) return FALSE; + if(!isAgentInventory()) return FALSE; // cannot drag into library + if (!isAgentAvatarValid()) return FALSE; + + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); + + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_favorites = (mUUID == favorites_id); + const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); + + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + BOOL accept = FALSE; + LLViewerObject* object = NULL; + if(LLToolDragAndDrop::SOURCE_AGENT == source) + { + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); + + const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); + const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); + + //-------------------------------------------------------------------------------- + // Determine if item can be moved. + // + + BOOL is_movable = TRUE; + + switch (inv_item->getActualType()) + { + case LLAssetType::AT_CATEGORY: + is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); + break; + default: + break; + } + // Can't explicitly drag things out of the COF. + if (move_is_outof_current_outfit) + { + is_movable = FALSE; + } + +// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g + if ( (rlv_handler_t::isEnabled()) && (is_movable) ) + { + if (move_is_into_current_outfit) + { + // RELEASE-RLVa: [RLVa-1.3.0] Keep sync'ed with code below => LLAppearanceMgr::wearItemOnAvatar() with "replace == true" + const LLViewerInventoryItem* pItem = dynamic_cast(inv_item); + is_movable = rlvPredCanWearItem(pItem, RLV_WEAR_REPLACE); + } + if (is_movable) + { + is_movable = (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && + (RlvFolderLocks::instance().canMoveItem(inv_item->getUUID(), mUUID)); + } + } +// [/RLVa:KB] + + if (move_is_into_trash) + { + is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID()); + } + if (is_movable) + { + // Don't allow creating duplicates in the Calling Card/Friends + // subfolders, see bug EXT-1599. Check is item direct descendent + // of target folder and forbid item's movement if it so. + // Note: isItemDirectDescendentOfCategory checks if + // passed category is in the Calling Card/Friends folder + is_movable &= !LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(inv_item, getCategory()); + } + + // + //-------------------------------------------------------------------------------- + + //-------------------------------------------------------------------------------- + // Determine if item can be moved & dropped + // + + accept = TRUE; + + if (!is_movable) + accept = FALSE; + if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + accept = FALSE; + if (move_is_into_current_outfit || move_is_into_outfit) + { + accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); + } + else if (move_is_into_favorites || move_is_into_landmarks) + { + accept = can_move_to_landmarks(inv_item); + } + + if(accept && drop) + { + if (inv_item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) + { + LLGestureMgr::instance().deactivateGesture(inv_item->getUUID()); + } + // If an item is being dragged between windows, unselect everything in the active window + // so that we don't follow the selection to its new location (which is very annoying). + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + if (active_panel) + { + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + if (active_panel && (panel != active_panel)) + { + active_panel->unSelectAll(); + } + } + + //-------------------------------------------------------------------------------- + // Destination folder logic + // + + // REORDER + // (only reorder the item in Favorites folder) + if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites) + { + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (itemp) + { + LLUUID srcItemId = inv_item->getUUID(); + LLUUID destItemId = itemp->getListener()->getUUID(); + gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); + } + } + + // FAVORITES folder + // (copy the item) + else if (move_is_into_favorites) + { + dropToFavorites(inv_item); + } + // CURRENT OUTFIT or OUTFIT folder + // (link the item) + else if (move_is_into_current_outfit || move_is_into_outfit) + { + dropToOutfit(inv_item, move_is_into_current_outfit); + } + // NORMAL or TRASH folder + // (move the item, restamp if into trash) + else + { + LLInvFVBridge::changeItemParent( + model, + (LLViewerInventoryItem*)inv_item, + mUUID, + move_is_into_trash); + } + + // + //-------------------------------------------------------------------------------- + + } + } + else if (LLToolDragAndDrop::SOURCE_WORLD == source) + { + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + object = gObjectList.findObject(inv_item->getParentUUID()); + if(!object) + { + llinfos << "Object not found for drop." << llendl; + return FALSE; + } + + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(inv_item->getPermissions()); + BOOL is_move = FALSE; + if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) + // || gAgent.isGodlike()) + + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + is_move = TRUE; + accept = TRUE; + } + + // Don't allow placing an original item into Current Outfit or an outfit folder + // because they must contain only links to wearable items. + // *TODO: Probably we should create a link to an item if it was dragged to outfit or COF. + if(move_is_into_current_outfit || move_is_into_outfit) + { + accept = FALSE; + } + // Don't allow to move a single item to Favorites or Landmarks + // if it is not a landmark or a link to a landmark. + else if ((move_is_into_favorites || move_is_into_landmarks) + && !can_move_to_landmarks(inv_item)) + { + accept = FALSE; + } + + if(drop && accept) + { + LLMoveInv* move_inv = new LLMoveInv; + move_inv->mObjectID = inv_item->getParentUUID(); + two_uuids_t item_pair(mUUID, inv_item->getUUID()); + move_inv->mMoveList.push_back(item_pair); + move_inv->mCallback = NULL; + move_inv->mUserData = NULL; + if(is_move) + { + warn_move_inventory(object, move_inv); + } + else + { + // store dad inventory item to select added one later. See EXT-4347 + set_dad_inventory_item(inv_item, mUUID); + + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + } + } + + } + else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) + { + // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder + // because they must contain only links to wearable items. + accept = !(move_is_into_current_outfit || move_is_into_outfit); + + if(drop) + { + copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), + LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); + } + } + else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; + if(item && item->isFinished()) + { + accept = TRUE; + + if (move_is_into_current_outfit || move_is_into_outfit) + { + accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); + } + // Don't allow to move a single item to Favorites or Landmarks + // if it is not a landmark or a link to a landmark. + else if (move_is_into_favorites || move_is_into_landmarks) + { + accept = can_move_to_landmarks(inv_item); + } + + if (accept && drop) + { + // FAVORITES folder + // (copy the item) + if (move_is_into_favorites) + { + dropToFavorites(inv_item); + } + // CURRENT OUTFIT or OUTFIT folder + // (link the item) + else if (move_is_into_current_outfit || move_is_into_outfit) + { + dropToOutfit(inv_item, move_is_into_current_outfit); + } + else + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + mUUID, + std::string(), + LLPointer(NULL)); + } + } + } + } + else + { + llwarns << "unhandled drag source" << llendl; + } + return accept; +} + +// +=================================================+ +// | LLTextureBridge | +// +=================================================+ + +LLUIImagePtr LLTextureBridge::getIcon() const +{ + return LLInventoryIcon::getIcon(LLAssetType::AT_TEXTURE, mInvType); +} + +void LLTextureBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +bool LLTextureBridge::canSaveTexture(void) +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return false; + } + + const LLViewerInventoryItem *item = model->getItem(mUUID); + if (item) + { + return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + } + return false; +} + +void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + + addOpenRightClickMenuOption(items); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Texture Separator")); + items.push_back(std::string("Save As")); + if (!canSaveTexture()) + { + disabled_items.push_back(std::string("Save As")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +// virtual +void LLTextureBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("save_as" == action) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance("preview_texture", mUUID); + if (preview_texture) + { + preview_texture->openToSave(); + } + } + else LLItemBridge::performAction(model, action); +} + +// +=================================================+ +// | LLSoundBridge | +// +=================================================+ + +void LLSoundBridge::openItem() +{ + const LLViewerInventoryItem* item = getItem(); + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +void LLSoundBridge::previewItem() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + send_sound_trigger(item->getAssetUUID(), 1.0); + } +} + +void LLSoundBridge::openSoundPreview(void* which) +{ + LLSoundBridge *me = (LLSoundBridge *)which; + LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); +} + +void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLSoundBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Sound Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Sound Separator")); + items.push_back(std::string("Sound Play")); + + hide_context_entries(menu, items, disabled_items); +} + +// +=================================================+ +// | LLLandmarkBridge | +// +=================================================+ + +LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + U32 flags/* = 0x00*/) : + LLItemBridge(inventory, root, uuid) +{ + mVisited = FALSE; + if (flags & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED) + { + mVisited = TRUE; + } +} + +LLUIImagePtr LLLandmarkBridge::getIcon() const +{ + return LLInventoryIcon::getIcon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); +} + +void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Landmark Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Landmark Separator")); + items.push_back(std::string("About Landmark")); + + // Disable "About Landmark" menu item for + // multiple landmarks selected. Only one landmark + // info panel can be shown at a time. + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("About Landmark")); + } + + hide_context_entries(menu, items, disabled_items); +} + +// Convenience function for the two functions below. +void teleport_via_landmark(const LLUUID& asset_id) +{ + gAgent.teleportViaLandmark( asset_id ); + + // we now automatically track the landmark you're teleporting to + // because you'll probably arrive at a telehub instead + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); + if( floater_world_map ) + { + floater_world_map->trackLandmark( asset_id ); + } +} + +// virtual +void LLLandmarkBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("teleport" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + teleport_via_landmark(item->getAssetUUID()); + } + } + else if ("about" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = item->getUUID(); + + LLSideTray::getInstance()->showPanel("panel_places", key); + } + } + else + { + LLItemBridge::performAction(model, action); + } +} + +static bool open_landmark_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); + if (option == 0) + { + teleport_via_landmark(asset_id); + } + + return false; +} +static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); + + +void LLLandmarkBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + + +// +=================================================+ +// | LLCallingCardObserver | +// +=================================================+ +class LLCallingCardObserver : public LLFriendObserver +{ +public: + LLCallingCardObserver(LLCallingCardBridge* bridge) : mBridgep(bridge) {} + virtual ~LLCallingCardObserver() { mBridgep = NULL; } + virtual void changed(U32 mask) + { + mBridgep->refreshFolderViewItem(); + } +protected: + LLCallingCardBridge* mBridgep; +}; + +// +=================================================+ +// | LLCallingCardBridge | +// +=================================================+ + +LLCallingCardBridge::LLCallingCardBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid ) : + LLItemBridge(inventory, root, uuid) +{ + mObserver = new LLCallingCardObserver(this); + LLAvatarTracker::instance().addObserver(mObserver); +} + +LLCallingCardBridge::~LLCallingCardBridge() +{ + LLAvatarTracker::instance().removeObserver(mObserver); + delete mObserver; +} + +void LLCallingCardBridge::refreshFolderViewItem() +{ + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; + if (itemp) + { + itemp->refresh(); + } +} + +// virtual +void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("begin_im" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + std::string callingcard_name; + gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); + // IDEVO + LLAvatarName av_name; + if (LLAvatarNameCache::useDisplayNames() + && LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) + { + callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")"; + } +// LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); +// if (session_id != LLUUID::null) +// { +// LLIMFloater::show(session_id); +// } +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + LLAvatarActions::startIM(item->getCreatorUUID()); +// [/RLVa:KB] + } + } + else if ("lure" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + LLAvatarActions::offerTeleport(item->getCreatorUUID()); + } + } + else LLItemBridge::performAction(model, action); +} + +LLUIImagePtr LLCallingCardBridge::getIcon() const +{ + BOOL online = FALSE; + LLViewerInventoryItem* item = getItem(); + if(item) + { + online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); + } + return LLInventoryIcon::getIcon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); +} + +std::string LLCallingCardBridge::getLabelSuffix() const +{ + LLViewerInventoryItem* item = getItem(); + if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) + { + return LLItemBridge::getLabelSuffix() + " (online)"; + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +void LLCallingCardBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if(item && !item->getCreatorUUID().isNull()) + { + LLAvatarActions::showProfile(item->getCreatorUUID()); + } +*/ +} + +void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + addOpenRightClickMenuOption(items); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + LLInventoryItem* item = getItem(); + BOOL good_card = (item + && (LLUUID::null != item->getCreatorUUID()) + && (item->getCreatorUUID() != gAgent.getID())); + BOOL user_online = FALSE; + if (item) + { + user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); + } + items.push_back(std::string("Send Instant Message Separator")); + items.push_back(std::string("Send Instant Message")); + items.push_back(std::string("Offer Teleport...")); + items.push_back(std::string("Conference Chat")); + + if (!good_card) + { + disabled_items.push_back(std::string("Send Instant Message")); + } + if (!good_card || !user_online) + { + disabled_items.push_back(std::string("Offer Teleport...")); + disabled_items.push_back(std::string("Conference Chat")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + LLViewerInventoryItem* item = getItem(); + BOOL rv = FALSE; + if(item) + { + // check the type + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_CLOTHING: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + { + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + const LLPermissions& perm = inv_item->getPermissions(); + if(gInventory.getItem(inv_item->getUUID()) + && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + rv = TRUE; + if(drop) + { + LLGiveInventory::doGiveInventoryItem(item->getCreatorUUID(), + (LLInventoryItem*)cargo_data); + } + } + 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. + rv = FALSE; + } + break; + } + case DAD_CATEGORY: + { + LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; + if( gInventory.getCategory( inv_cat->getUUID() ) ) + { + rv = TRUE; + if(drop) + { + LLGiveInventory::doGiveInventoryCategory( + item->getCreatorUUID(), + inv_cat); + } + } + 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. + rv = FALSE; + } + break; + } + default: + break; + } + } + return rv; +} + +// +=================================================+ +// | LLNotecardBridge | +// +=================================================+ + +void LLNotecardBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +// +=================================================+ +// | LLGestureBridge | +// +=================================================+ + +LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const +{ + if( LLGestureMgr::instance().isGestureActive(mUUID) ) + { + return LLFontGL::BOLD; + } + else + { + return LLFontGL::NORMAL; + } +} + +std::string LLGestureBridge::getLabelSuffix() const +{ + if( LLGestureMgr::instance().isGestureActive(mUUID) ) + { + LLStringUtil::format_map_t args; + args["[GESLABEL]"] = LLItemBridge::getLabelSuffix(); + return LLTrans::getString("ActiveGesture", args); + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +// virtual +void LLGestureBridge::performAction(LLInventoryModel* model, std::string action) +{ + if (isAddAction(action)) + { + LLGestureMgr::instance().activateGesture(mUUID); + + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if (!item) return; + + // Since we just changed the suffix to indicate (active) + // the server doesn't need to know, just the viewer. + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else if (isRemoveAction(action)) + { + LLGestureMgr::instance().deactivateGesture(mUUID); + + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if (!item) return; + + // Since we just changed the suffix to indicate (active) + // the server doesn't need to know, just the viewer. + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else if("play" == action) + { + if(!LLGestureMgr::instance().isGestureActive(mUUID)) + { + // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList. + BOOL inform_server = TRUE; + BOOL deactivate_similar = FALSE; + LLGestureMgr::instance().setGestureLoadedCallback(mUUID, boost::bind(&LLGestureBridge::playGesture, mUUID)); + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + llassert(item); + if (item) + { + LLGestureMgr::instance().activateGestureWithAsset(mUUID, item->getAssetUUID(), inform_server, deactivate_similar); + } + } + else + { + playGesture(mUUID); + } + } + else LLItemBridge::performAction(model, action); +} + +void LLGestureBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); + preview->setFocus(TRUE); + } +*/ +} + +BOOL LLGestureBridge::removeItem() +{ + // Grab class information locally since *this may be deleted + // within this function. Not a great pattern... + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + const LLUUID item_id = mUUID; + + // This will also force close the preview window, if it exists. + // This may actually delete *this, if mUUID is in the COF. + LLGestureMgr::instance().deactivateGesture(item_id); + + // If deactivateGesture deleted *this, then return out immediately. + if (!model->getObject(item_id)) + { + return TRUE; + } + + return LLItemBridge::removeItem(); +} + +void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + + addOpenRightClickMenuOption(items); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Gesture Separator")); + if (LLGestureMgr::instance().isGestureActive(getUUID())) + { + items.push_back(std::string("Deactivate")); + } + else + { + items.push_back(std::string("Activate")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +// static +void LLGestureBridge::playGesture(const LLUUID& item_id) +{ + if (LLGestureMgr::instance().isGesturePlaying(item_id)) + { + LLGestureMgr::instance().stopGesture(item_id); + } + else + { + LLGestureMgr::instance().playGesture(item_id); + } +} + + +// +=================================================+ +// | LLAnimationBridge | +// +=================================================+ + +void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Animation Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Animation Separator")); + items.push_back(std::string("Animation Play")); + items.push_back(std::string("Animation Audition")); + + hide_context_entries(menu, items, disabled_items); + +} + +// virtual +void LLAnimationBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ((action == "playworld") || (action == "playlocal")) + { + if (getItem()) + { + LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; + if ("playworld" == action) activate = LLPreviewAnim::PLAY; + if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; + + LLPreviewAnim* preview = LLFloaterReg::showTypedInstance("preview_anim", LLSD(mUUID)); + if (preview) + { + preview->activate(activate); + } + } + } + else + { + LLItemBridge::performAction(model, action); + } +} + +void LLAnimationBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + } +*/ +} + +// +=================================================+ +// | LLObjectBridge | +// +=================================================+ + +// static +LLUUID LLObjectBridge::sContextMenuItemID; + +LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + LLInventoryType::EType type, + U32 flags) : + LLItemBridge(inventory, root, uuid) +{ + mAttachPt = (flags & 0xff); // low bye of inventory flags + mIsMultiObject = ( flags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; + mInvType = type; +} + +LLUIImagePtr LLObjectBridge::getIcon() const +{ + return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject); +} + +LLInventoryObject* LLObjectBridge::getObject() const +{ + LLInventoryObject* object = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + object = (LLInventoryObject*)model->getObject(mUUID); + } + return object; +} + +// virtual +void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) +{ + if (isAddAction(action)) + { + LLUUID object_id = mUUID; + LLViewerInventoryItem* item; + item = (LLViewerInventoryItem*)gInventory.getItem(object_id); + if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) + { + rez_attachment(item, NULL, true); // Replace if "Wear"ing. + } + else if(item && item->isFinished()) + { + // must be in library. copy it to our inventory and put it on. + LLPointer cb = new RezAttachmentCallback(0); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + gFocusMgr.setKeyboardFocus(NULL); + } + else if ("wear_add" == action) + { + LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. + } +// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-08-25 (Catznip-2.2.0a) | Added: Catznip-2.1.2a + else if ("edit" == action) + { + handle_attachment_edit(mUUID); + } +// [/SL:KB] + else if (isRemoveAction(action)) + { + LLInventoryItem* item = gInventory.getItem(mUUID); + if(item) + { + LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID()); + } + } + else LLItemBridge::performAction(model, action); +} + +void LLObjectBridge::openItem() +{ + // object double-click action is to wear/unwear object + performAction(getInventoryModel(), + get_is_item_worn(mUUID) ? "detach" : "attach"); +} + +std::string LLObjectBridge::getLabelSuffix() const +{ + if (get_is_item_worn(mUUID)) + { + if (!isAgentAvatarValid()) // Error condition, can't figure out attach point + { + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); + } + std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); + if (attachment_point_name == LLStringUtil::null) // Error condition, invalid attach point + { + attachment_point_name = "Invalid Attachment"; + } + // e.g. "(worn on ...)" / "(attached to ...)" + LLStringUtil::format_map_t args; + args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); + + return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); + } + return LLItemBridge::getLabelSuffix(); +} + +void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace) +{ +// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1a) | Added: RLVa-1.2.1a + // If no attachment point was specified, try looking it up from the item name + if ( (rlv_handler_t::isEnabled()) && (!attachment) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) + { + attachment = RlvAttachPtLookup::getAttachPoint(item); + } +// [/RLVa:KB] + + const LLUUID& item_id = item->getLinkedUUID(); + + // Check for duplicate request. + if (isAgentAvatarValid() && + (gAgentAvatarp->attachmentWasRequested(item_id) || + gAgentAvatarp->isWearingAttachment(item_id))) + { + llwarns << "duplicate attachment request, ignoring" << llendl; + return; + } + gAgentAvatarp->addAttachmentRequest(item_id); + + S32 attach_pt = 0; + if (isAgentAvatarValid() && attachment) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) + { + if (iter->second == attachment) + { + attach_pt = iter->first; + break; + } + } + } + + LLSD payload; + payload["item_id"] = item_id; // Wear the base object in case this is a link. + payload["attachment_point"] = attach_pt; + payload["is_add"] = !replace; + + if (replace && + (attachment && attachment->getNumObjects() > 0)) + { +// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a + // Block if we can't "replace wear" what's currently there + if ( (rlv_handler_t::isEnabled()) && ((gRlvAttachmentLocks.canAttach(attachment) & RLV_WEAR_REPLACE) == 0) ) + return; +// [/RLVa:KB] + LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_attachment_rez); + } + else + { +// [RLVa:KB] - Checked: 2010-08-07 (RLVa-1.2.0i) | Modified: RLVa-1.2.0i + // Block wearing anything on a non-attachable attachment point + if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachmentPoint(attach_pt, RLV_LOCK_ADD)) ) + return; +// [/RLVa:KB] + LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); + } +} + +bool confirm_attachment_rez(const LLSD& notification, const LLSD& response) +{ + if (!gAgentAvatarp->canAttachMoreObjects()) + { + LLSD args; + args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); + LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args); + return false; + } + + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0/*YES*/) + { + LLUUID item_id = notification["payload"]["item_id"].asUUID(); + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + + if (itemp) + { + /* + { + U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); +// [RLVa:KB] - Checked: 2010-08-06 (RLVa-1.2.0i) | Added: RLVa-1.2.0i + // NOTE: we're letting our callers decide whether or not to use ATTACHMENT_ADD + if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) && + ((!notification["payload"].has("rlv_force")) || (!notification["payload"]["rlv_force"].asBoolean())) ) + { + ERlvWearMask eWearAction = (attachment_pt & ATTACHMENT_ADD) ? RLV_WEAR_ADD : RLV_WEAR_REPLACE; + RlvAttachmentLockWatchdog::instance().onWearAttachment(itemp, eWearAction);; + + attachment_pt |= ATTACHMENT_ADD; + } +// [/RLVa:KB] + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); + msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); + msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); + pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); + msg->addStringFast(_PREHASH_Name, itemp->getName()); + msg->addStringFast(_PREHASH_Description, itemp->getDescription()); + msg->sendReliable(gAgent.getRegion()->getHost()); + return false; + } + */ + + // Queue up attachments to be sent in next idle tick, this way the + // attachments are batched up all into one message versus each attachment + // being sent in its own separate attachments message. + U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); + BOOL is_add = notification["payload"]["is_add"].asBoolean(); + + LLAttachmentsMgr::instance().addAttachment(item_id, + attachment_pt, + is_add); + } + } + return false; +} +static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_attachment_rez); + +void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + LLObjectBridge::sContextMenuItemID = mUUID; + + LLInventoryItem *item = getItem(); + if(item) + { + if (!isAgentAvatarValid()) return; + + if( get_is_item_worn( mUUID ) ) + { + items.push_back(std::string("Wearable And Object Separator")); +// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-08-25 (Catznip-2.2.0a) | Added: Catznip-2.1.2a + // TOOD-Catznip: should really be "Wearable And Object Edit" if we ever plan on pushing this upstream + items.push_back(std::string("Wearable Edit")); +// [/SL:KB] + items.push_back(std::string("Detach From Yourself")); +// [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a + if ( (rlv_handler_t::isEnabled()) && (!gRlvAttachmentLocks.canDetach(item)) ) + disabled_items.push_back(std::string("Detach From Yourself")); +// [/RLVa:KB] + } + else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder()) + { + items.push_back(std::string("Wearable And Object Separator")); + items.push_back(std::string("Wearable And Object Wear")); + items.push_back(std::string("Wearable Add")); + items.push_back(std::string("Attach To")); + items.push_back(std::string("Attach To HUD")); + // commented out for DEV-32347 + //items.push_back(std::string("Restore to Last Position")); + + if (!gAgentAvatarp->canAttachMoreObjects()) + { + disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Add")); + disabled_items.push_back(std::string("Attach To")); + disabled_items.push_back(std::string("Attach To HUD")); + } +// [RLVa:KB] - Checked: 2010-09-03 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a + else if (rlv_handler_t::isEnabled()) + { + ERlvWearMask eWearMask = gRlvAttachmentLocks.canAttach(item); + if ((eWearMask & RLV_WEAR_REPLACE) == 0) + disabled_items.push_back(std::string("Wearable And Object Wear")); + if ((eWearMask & RLV_WEAR_ADD) == 0) + disabled_items.push_back(std::string("Wearable Add")); + } +// [/RLVa:KB] + + LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); + LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); + if (attach_menu + && (attach_menu->getChildCount() == 0) + && attach_hud_menu + && (attach_hud_menu->getChildCount() == 0) + && isAgentAvatarValid()) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + LLMenuItemCallGL::Params p; + std::string submenu_name = attachment->getName(); + if (LLTrans::getString(submenu_name) != "") + { + p.name = (" ")+LLTrans::getString(submenu_name)+" "; + } + else + { + p.name = submenu_name; + } + LLSD cbparams; + cbparams["index"] = curiter->first; + cbparams["label"] = p.name; + p.on_click.function_name = "Inventory.AttachObject"; + p.on_click.parameter = LLSD(attachment->getName()); + p.on_enable.function_name = "Attachment.Label"; + p.on_enable.parameter = cbparams; + LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; + LLUICtrlFactory::create(p, parent); + } + } + } + } + } + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLObjectBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLPreview::dirty(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryItem* item = getItem(); + if(item && (item->getName() != new_name)) + { + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + buildDisplayName(new_item, mDisplayName); + new_item->updateServer(FALSE); + model->updateItem(new_item); + + model->notifyObservers(); + + if (isAgentAvatarValid()) + { + LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() ); + if(obj) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); + LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); + LLSelectMgr::getInstance()->deselectAll(); + } + } + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + +// +=================================================+ +// | LLLSLTextBridge | +// +=================================================+ + +void LLLSLTextBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +// +=================================================+ +// | LLWearableBridge | +// +=================================================+ + +LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + LLAssetType::EType asset_type, + LLInventoryType::EType inv_type, + LLWearableType::EType wearable_type) : + LLItemBridge(inventory, root, uuid), + mAssetType( asset_type ), + mWearableType(wearable_type) +{ + mInvType = inv_type; +} + +void remove_inventory_category_from_avatar( LLInventoryCategory* category ) +{ + if(!category) return; + lldebugs << "remove_inventory_category_from_avatar( " << category->getName() + << " )" << llendl; + + + if (gAgentCamera.cameraCustomizeAvatar()) + { + // switching to outfit editor should automagically save any currently edited wearable + LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit")); + } + + remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); +} + +struct OnRemoveStruct +{ + LLUUID mUUID; + OnRemoveStruct(const LLUUID& uuid): + mUUID(uuid) + { + } +}; + +void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) +{ + + // Find all the wearables that are in the category's subtree. + lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; + if(proceed) + { + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + LLFindWearables is_wearable; + gInventory.collectDescendentsIf(category_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_wearable); + S32 i; + S32 wearable_count = item_array.count(); + + LLInventoryModel::cat_array_t obj_cat_array; + LLInventoryModel::item_array_t obj_item_array; + LLIsType is_object( LLAssetType::AT_OBJECT ); + gInventory.collectDescendentsIf(category_id, + obj_cat_array, + obj_item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_object); + S32 obj_count = obj_item_array.count(); + + // Find all gestures in this folder + LLInventoryModel::cat_array_t gest_cat_array; + LLInventoryModel::item_array_t gest_item_array; + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + gInventory.collectDescendentsIf(category_id, + gest_cat_array, + gest_item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_gesture); + S32 gest_count = gest_item_array.count(); + + if (wearable_count > 0) //Loop through wearables. If worn, remove. + { + for(i = 0; i < wearable_count; ++i) + { + LLViewerInventoryItem *item = item_array.get(i); + if (item->getType() == LLAssetType::AT_BODYPART) + continue; + if (gAgent.isTeen() && item->isWearableType() && + (item->getWearableType() == LLWearableType::WT_UNDERPANTS || item->getWearableType() == LLWearableType::WT_UNDERSHIRT)) + continue; + if (get_is_item_worn(item->getUUID())) + { +/* +// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0c) | Modified: RLVa-0.2.2a + if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) + continue; +// [/RLVa:KB] + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item->getLinkedUUID())); +*/ +// [SL:KB] - Patch: Appearance-RemoveWearableFromAvatar | Checked: 2010-08-13 (Catznip-2.5.0a) | Added: Catznip-2.1.1d + LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); +// [/SL:KB] + } + } + } + + if (obj_count > 0) + { + for(i = 0; i < obj_count; ++i) + { + LLViewerInventoryItem *obj_item = obj_item_array.get(i); + if (get_is_item_worn(obj_item->getUUID())) + { + LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID()); + } + } + } + + if (gest_count > 0) + { + for(i = 0; i < gest_count; ++i) + { + LLViewerInventoryItem *gest_item = gest_item_array.get(i); + if (get_is_item_worn(gest_item->getUUID())) + { + LLGestureMgr::instance().deactivateGesture( gest_item->getLinkedUUID() ); + gInventory.updateItem( gest_item ); + gInventory.notifyObservers(); + } + + } + } + } +} + +BOOL LLWearableBridge::renameItem(const std::string& new_name) +{ + if (get_is_item_worn(mUUID)) + { + gAgentWearables.setWearableName( mUUID, new_name ); + } + return LLItemBridge::renameItem(new_name); +} + +std::string LLWearableBridge::getLabelSuffix() const +{ + if (get_is_item_worn(mUUID)) + { + // e.g. "(worn)" + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +LLUIImagePtr LLWearableBridge::getIcon() const +{ + return LLInventoryIcon::getIcon(mAssetType, mInvType, mWearableType, FALSE); +} + +// virtual +void LLWearableBridge::performAction(LLInventoryModel* model, std::string action) +{ + if (isAddAction(action)) + { + wearOnAvatar(); + } + else if ("wear_add" == action) + { + wearAddOnAvatar(); + } + else if ("edit" == action) + { + editOnAvatar(); + return; + } + else if (isRemoveAction(action)) + { + removeFromAvatar(); + return; + } + else LLItemBridge::performAction(model, action); +} + +void LLWearableBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere + BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM); + + // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 + LLViewerInventoryItem* item = getItem(); + if (can_open && item) + { + can_open = (item->getType() != LLAssetType::AT_CLOTHING) && + (item->getType() != LLAssetType::AT_BODYPART); + } + if (isLinkedObjectMissing()) + { + can_open = FALSE; + } + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + + if (can_open) + { + addOpenRightClickMenuOption(items); + } + else + { + disabled_items.push_back(std::string("Open")); + disabled_items.push_back(std::string("Open Original")); + } + + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Wearable And Object Separator")); + + items.push_back(std::string("Wearable Edit")); + + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Wearable Edit")); + } + // Don't allow items to be worn if their baseobj is in the trash. + if (isLinkedObjectInTrash() || isLinkedObjectMissing() || isCOFFolder()) + { + disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Add")); + disabled_items.push_back(std::string("Wearable Edit")); + } + + // Disable wear and take off based on whether the item is worn. + if(item) + { + switch (item->getType()) + { + case LLAssetType::AT_CLOTHING: + items.push_back(std::string("Take Off")); + // Fallthrough since clothing and bodypart share wear options + case LLAssetType::AT_BODYPART: + if (get_is_item_worn(item->getUUID())) + { + disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Add")); +// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0c) | Added: RLVa-1.2.0c + if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) + disabled_items.push_back(std::string("Take Off")); +// [/RLVa:KB] + } + else + { + items.push_back(std::string("Wearable And Object Wear")); + items.push_back(std::string("Wearable Add")); + disabled_items.push_back(std::string("Take Off")); + disabled_items.push_back(std::string("Wearable Edit")); + +// [RLVa:KB] - Checked: 2010-06-09 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g + if (rlv_handler_t::isEnabled()) + { + ERlvWearMask eWearMask = gRlvWearableLocks.canWear(item); + if ((eWearMask & RLV_WEAR_REPLACE) == 0) + disabled_items.push_back(std::string("Wearable And Object Wear")); + if ((eWearMask & RLV_WEAR_ADD) == 0) + disabled_items.push_back(std::string("Wearable Add")); + } +// [/RLVa:KB] + } + break; + default: + break; + } + } + } + hide_context_entries(menu, items, disabled_items); +} + +// Called from menus +// static +BOOL LLWearableBridge::canWearOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return FALSE; + if(!self->isAgentInventory()) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); + if(!item || !item->isFinished()) return FALSE; + } + return (!get_is_item_worn(self->mUUID)); +} + +// Called from menus +// static +void LLWearableBridge::onWearOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return; + self->wearOnAvatar(); +} + +void LLWearableBridge::wearOnAvatar() +{ + // TODO: investigate wearables may not be loaded at this point EXT-8231 + + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true); + } +} + +void LLWearableBridge::wearAddOnAvatar() +{ + // TODO: investigate wearables may not be loaded at this point EXT-8231 + + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, false); + } +} + +// static +/* +void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) +{ + LLUUID* item_id = (LLUUID*) userdata; + if(wearable) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); + if(item) + { + if(item->getAssetUUID() == wearable->getAssetID()) + { + gAgentWearables.setWearableItem(item, wearable); + gInventory.notifyObservers(); + //self->getFolderItem()->refreshFromRoot(); + } + else + { + llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; + } + } + } + delete item_id; +} +*/ + +// static +// BAP remove the "add" code path once everything is fully COF-ified. +/* +void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) +{ + LLUUID* item_id = (LLUUID*) userdata; + if(wearable) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); + if(item) + { + if(item->getAssetUUID() == wearable->getAssetID()) + { + bool do_append = true; + gAgentWearables.setWearableItem(item, wearable, do_append); + gInventory.notifyObservers(); + //self->getFolderItem()->refreshFromRoot(); + } + else + { + llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; + } + } + } + delete item_id; +} +*/ + +// static +BOOL LLWearableBridge::canEditOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return FALSE; + + return (get_is_item_worn(self->mUUID)); +} + +// static +void LLWearableBridge::onEditOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(self) + { + self->editOnAvatar(); + } +} + +void LLWearableBridge::editOnAvatar() +{ + LLAgentWearables::editWearable(mUUID); +} + +// static +BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) + { + return get_is_item_worn( self->mUUID ); + } + return FALSE; +} + +// static +/* +void LLWearableBridge::onRemoveFromAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return; + if(get_is_item_worn(self->mUUID)) + { + LLViewerInventoryItem* item = self->getItem(); + if (item) + { + LLUUID parent_id = item->getParentUUID(); + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + onRemoveFromAvatarArrived, + new OnRemoveStruct(LLUUID(self->mUUID))); + } + } +} +*/ + +// static +/* +void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, + void* userdata) +{ + OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; + const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); + +// [RLVa:KB] - Checked: 2010-03-20 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a + if ( (rlv_handler_t::isEnabled()) && ((!wearable) || (!gRlvWearableLocks.canRemove(gInventory.getItem(item_id)))) ) + { + delete on_remove_struct; + return; + } +// [/RLVa:KB] + + if(wearable) + { + if( get_is_item_worn( item_id ) ) + { + LLWearableType::EType type = wearable->getType(); + + if( !(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES ) ) //&& + //!((!gAgent.isTeen()) && ( type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT )) ) + { + bool do_remove_all = false; + U32 index = gAgentWearables.getWearableIndex(wearable); + gAgentWearables.removeWearable( type, do_remove_all, index ); + } + } + } + + // Find and remove this item from the COF. + LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); + gInventory.notifyObservers(); + + delete on_remove_struct; +} +*/ + +// static +void LLWearableBridge::removeAllClothesFromAvatar() +{ + // Remove COF links. + for (S32 itype = LLWearableType::WT_SHAPE; itype < LLWearableType::WT_COUNT; ++itype) + { + if (itype == LLWearableType::WT_SHAPE || itype == LLWearableType::WT_SKIN || itype == LLWearableType::WT_HAIR || itype == LLWearableType::WT_EYES) + continue; + +// for (S32 index = gAgentWearables.getWearableCount(itype)-1; index >= 0 ; --index) +// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-09-04 (Catznip-2.5.0a) | Added: Catznip-2.1.2a + for (S32 index = gAgentWearables.getWearableCount((LLWearableType::EType)itype)-1; index >= 0 ; --index) +// [/SL:KB] + { + LLViewerInventoryItem *item = dynamic_cast( + gAgentWearables.getWearableInventoryItem((LLWearableType::EType)itype, index)); + if (!item) + continue; + const LLUUID &item_id = item->getUUID(); + const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id); + if (!wearable) + continue; + +// [RLVa:KB] - Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g + if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) + continue; +// [/RLVa:KB] + + // Find and remove this item from the COF. + LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); + } + } + gInventory.notifyObservers(); + + // Remove wearables from gAgentWearables +// LLAgentWearables::userRemoveAllClothes(); +// [RLVa:KB] - Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g + LLAppearanceMgr::instance().updateAppearanceFromCOF(); +// [/RLVa:KB] +} + +// static +void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item) +{ + if (item) + { +/* + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item->getUUID())); +*/ +// [SL:KB] - Patch: Appearance-RemoveWearableFromAvatar | Checked: 2010-08-13 (Catznip-2.5.0a) | Added: Catznip-2.1.1d + LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); +// [/SL:KB] + } +} + +void LLWearableBridge::removeFromAvatar() +{ + if (get_is_item_worn(mUUID)) + { + LLViewerInventoryItem* item = getItem(); + removeItemFromAvatar(item); + } +} + +// +=================================================+ +// | LLLinkItemBridge | +// +=================================================+ +// For broken item links + +std::string LLLinkItemBridge::sPrefix("Link: "); + +void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + items.push_back(std::string("Find Original")); + disabled_items.push_back(std::string("Find Original")); + + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Properties")); + addDeleteContextMenuOptions(items, disabled_items); + } + hide_context_entries(menu, items, disabled_items); +} + +// +=================================================+ +// | LLLinkBridge | +// +=================================================+ +// For broken folder links. +std::string LLLinkFolderBridge::sPrefix("Link: "); +LLUIImagePtr LLLinkFolderBridge::getIcon() const +{ + LLFolderType::EType folder_type = LLFolderType::FT_NONE; + const LLInventoryObject *obj = getInventoryObject(); + if (obj) + { + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + cat = (LLViewerInventoryCategory*)model->getCategory(obj->getLinkedUUID()); + if (cat) + { + folder_type = cat->getPreferredType(); + } + } + } + return LLFolderBridge::getIcon(folder_type); +} + +void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if (isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Find Original")); + addDeleteContextMenuOptions(items, disabled_items); + } + hide_context_entries(menu, items, disabled_items); +} +void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(); + return; + } + LLItemBridge::performAction(model,action); +} +void LLLinkFolderBridge::gotoItem() +{ + const LLUUID &cat_uuid = getFolderID(); + if (!cat_uuid.isNull()) + { + if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) + { + if (LLInventoryModel* model = getInventoryModel()) + { + model->fetchDescendentsOf(cat_uuid); + } + base_folder->setOpen(TRUE); + mRoot->setSelectionFromRoot(base_folder,TRUE); + mRoot->scrollToShowSelection(); + } + } +} +const LLUUID &LLLinkFolderBridge::getFolderID() const +{ + if (LLViewerInventoryItem *link_item = getItem()) + { + if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) + { + const LLUUID& cat_uuid = cat->getUUID(); + return cat_uuid; + } + } + return LLUUID::null; +} + +/******************************************************************************** + ** + ** BRIDGE ACTIONS + **/ + +// static +void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, + const LLUUID& uuid, + LLInventoryModel* model) +{ + // Perform indirection in case of link. + const LLUUID& linked_uuid = gInventory.getLinkedItemID(uuid); + + LLInvFVBridgeAction* action = createAction(asset_type,linked_uuid,model); + if(action) + { + action->doIt(); + delete action; + } +} + +// static +void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) +{ + llassert(model); + LLViewerInventoryItem* item = model->getItem(uuid); + llassert(item); + if (item) + { + LLAssetType::EType asset_type = item->getType(); + LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + if(action) + { + action->doIt(); + delete action; + } + } +} + +LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const +{ + if (mModel) + return (LLViewerInventoryItem*)mModel->getItem(mUUID); + return NULL; +} + +class LLTextureBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + if (getItem()) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLTextureBridgeAction(){} +protected: + LLTextureBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLSoundBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLSoundBridgeAction(){} +protected: + LLSoundBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLLandmarkBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + // Opening (double-clicking) a landmark immediately teleports, + // but warns you the first time. + LLSD payload; + payload["asset_id"] = item->getAssetUUID(); + + LLSD args; + args["LOCATION"] = item->getName(); + + LLNotificationsUtil::add("TeleportFromLandmark", args, payload); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLLandmarkBridgeAction(){} +protected: + LLLandmarkBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLCallingCardBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item && item->getCreatorUUID().notNull()) + { + LLAvatarActions::showProfile(item->getCreatorUUID()); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLCallingCardBridgeAction(){} +protected: + LLCallingCardBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} + +}; + +class LLNotecardBridgeAction +: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLNotecardBridgeAction(){} +protected: + LLNotecardBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLGestureBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); + preview->setFocus(TRUE); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLGestureBridgeAction(){} +protected: + LLGestureBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLAnimationBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLAnimationBridgeAction(){} +protected: + LLAnimationBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLObjectBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + /* + LLFloaterReg::showInstance("properties", mUUID); + */ + LLInvFVBridgeAction::doIt(); + } + virtual ~LLObjectBridgeAction(){} +protected: + LLObjectBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLLSLTextBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); + } + LLInvFVBridgeAction::doIt(); + } + virtual ~LLLSLTextBridgeAction(){} +protected: + LLLSLTextBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} +}; + +class LLWearableBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() + { // TODO: investigate wearables may not be loaded at this point EXT-8231 LLViewerInventoryItem* item = getItem(); @@ -5540,195 +5562,195 @@ public: if ( get_is_item_worn(mUUID) ) LLAppearanceMgr::instance().removeItemFromAvatar(mUUID); else LLAppearanceMgr::instance().wearItemOnAvatar(mUUID /*item->getUUID()*/, true, true); } - } - virtual ~LLWearableBridgeAction(){} -protected: - LLWearableBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} - BOOL isItemInTrash() const; - // return true if the item is in agent inventory. if false, it - // must be lost or in the inventory library. - BOOL isAgentInventory() const; -}; - -BOOL LLWearableBridgeAction::isItemInTrash() const -{ - if(!mModel) return FALSE; - const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return mModel->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLWearableBridgeAction::isAgentInventory() const -{ - if(!mModel) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, - const LLUUID& uuid, - LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - action = new LLTextureBridgeAction(uuid,model); - break; - case LLAssetType::AT_SOUND: - action = new LLSoundBridgeAction(uuid,model); - break; - case LLAssetType::AT_LANDMARK: - action = new LLLandmarkBridgeAction(uuid,model); - break; - case LLAssetType::AT_CALLINGCARD: - action = new LLCallingCardBridgeAction(uuid,model); - break; - case LLAssetType::AT_OBJECT: - action = new LLObjectBridgeAction(uuid,model); - break; - case LLAssetType::AT_NOTECARD: - action = new LLNotecardBridgeAction(uuid,model); - break; - case LLAssetType::AT_ANIMATION: - action = new LLAnimationBridgeAction(uuid,model); - break; - case LLAssetType::AT_GESTURE: - action = new LLGestureBridgeAction(uuid,model); - break; - case LLAssetType::AT_LSL_TEXT: - action = new LLLSLTextBridgeAction(uuid,model); - break; - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - action = new LLWearableBridgeAction(uuid,model); - break; - default: - break; - } - return action; -} - -/** Bridge Actions - ** - ********************************************************************************/ - -/************************************************************************/ -/* Recent Inventory Panel related classes */ -/************************************************************************/ -void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - LLFolderBridge::buildContextMenu(menu, flags); - - menuentry_vec_t disabled_items, items = getMenuItems(); - - items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); - - hide_context_entries(menu, items, disabled_items); -} - -LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( - LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - U32 flags /*= 0x00*/ ) const -{ - LLInvFVBridge* new_listener = NULL; - switch(asset_type) - { - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // *TODO: Create a link folder handler instead if it is necessary - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - break; - } - new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); - break; - default: - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - } - return new_listener; - -} - -/************************************************************************/ -/* Worn Inventory Panel related classes */ -/************************************************************************/ -void LLWornItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - LLFolderBridge::buildContextMenu(menu, flags); - - menuentry_vec_t disabled_items, items = getMenuItems(); - - items.erase(std::remove(items.begin(), items.end(), std::string("New Body Parts")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Clothes")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Note")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Gesture")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Script")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); - - hide_context_entries(menu, items, disabled_items); -} - -LLInvFVBridge* LLWornInventoryBridgeBuilder::createBridge( - LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - LLFolderView* root, - const LLUUID& uuid, - U32 flags /*= 0x00*/ ) const -{ - LLInvFVBridge* new_listener = NULL; - switch(asset_type) - { - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // *TODO: Create a link folder handler instead if it is necessary - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - break; - } - new_listener = new LLWornItemsFolderBridge(inv_type, inventory, root, uuid); - break; - default: - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - } - return new_listener; - -} - - - -// EOF + } + virtual ~LLWearableBridgeAction(){} +protected: + LLWearableBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {} + BOOL isItemInTrash() const; + // return true if the item is in agent inventory. if false, it + // must be lost or in the inventory library. + BOOL isAgentInventory() const; +}; + +BOOL LLWearableBridgeAction::isItemInTrash() const +{ + if(!mModel) return FALSE; + const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH); + return mModel->isObjectDescendentOf(mUUID, trash_id); +} + +BOOL LLWearableBridgeAction::isAgentInventory() const +{ + if(!mModel) return FALSE; + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); +} + +LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, + const LLUUID& uuid, + LLInventoryModel* model) +{ + LLInvFVBridgeAction* action = NULL; + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + action = new LLTextureBridgeAction(uuid,model); + break; + case LLAssetType::AT_SOUND: + action = new LLSoundBridgeAction(uuid,model); + break; + case LLAssetType::AT_LANDMARK: + action = new LLLandmarkBridgeAction(uuid,model); + break; + case LLAssetType::AT_CALLINGCARD: + action = new LLCallingCardBridgeAction(uuid,model); + break; + case LLAssetType::AT_OBJECT: + action = new LLObjectBridgeAction(uuid,model); + break; + case LLAssetType::AT_NOTECARD: + action = new LLNotecardBridgeAction(uuid,model); + break; + case LLAssetType::AT_ANIMATION: + action = new LLAnimationBridgeAction(uuid,model); + break; + case LLAssetType::AT_GESTURE: + action = new LLGestureBridgeAction(uuid,model); + break; + case LLAssetType::AT_LSL_TEXT: + action = new LLLSLTextBridgeAction(uuid,model); + break; + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + action = new LLWearableBridgeAction(uuid,model); + break; + default: + break; + } + return action; +} + +/** Bridge Actions + ** + ********************************************************************************/ + +/************************************************************************/ +/* Recent Inventory Panel related classes */ +/************************************************************************/ +void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + LLFolderBridge::buildContextMenu(menu, flags); + + menuentry_vec_t disabled_items, items = getMenuItems(); + + items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); + + hide_context_entries(menu, items, disabled_items); +} + +LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( + LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + U32 flags /*= 0x00*/ ) const +{ + LLInvFVBridge* new_listener = NULL; + switch(asset_type) + { + case LLAssetType::AT_CATEGORY: + if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) + { + // *TODO: Create a link folder handler instead if it is necessary + new_listener = LLInventoryFVBridgeBuilder::createBridge( + asset_type, + actual_asset_type, + inv_type, + inventory, + root, + uuid, + flags); + break; + } + new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); + break; + default: + new_listener = LLInventoryFVBridgeBuilder::createBridge( + asset_type, + actual_asset_type, + inv_type, + inventory, + root, + uuid, + flags); + } + return new_listener; + +} + +/************************************************************************/ +/* Worn Inventory Panel related classes */ +/************************************************************************/ +void LLWornItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + LLFolderBridge::buildContextMenu(menu, flags); + + menuentry_vec_t disabled_items, items = getMenuItems(); + + items.erase(std::remove(items.begin(), items.end(), std::string("New Body Parts")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New Clothes")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New Note")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New Gesture")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New Script")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); + + hide_context_entries(menu, items, disabled_items); +} + +LLInvFVBridge* LLWornInventoryBridgeBuilder::createBridge( + LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid, + U32 flags /*= 0x00*/ ) const +{ + LLInvFVBridge* new_listener = NULL; + switch(asset_type) + { + case LLAssetType::AT_CATEGORY: + if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) + { + // *TODO: Create a link folder handler instead if it is necessary + new_listener = LLInventoryFVBridgeBuilder::createBridge( + asset_type, + actual_asset_type, + inv_type, + inventory, + root, + uuid, + flags); + break; + } + new_listener = new LLWornItemsFolderBridge(inv_type, inventory, root, uuid); + break; + default: + new_listener = LLInventoryFVBridgeBuilder::createBridge( + asset_type, + actual_asset_type, + inv_type, + inventory, + root, + uuid, + flags); + } + return new_listener; + +} + + + +// EOF diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 549a07f1c4..6afcc04c12 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -81,8 +81,9 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0b) | Added: RLVa-1.3.0b +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] BOOL LLInventoryState::sWearNewClothing = FALSE; @@ -354,6 +355,14 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id) } } +// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g + if ( (rlv_handler_t::isEnabled()) && + (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(id)) ) + { + return FALSE; + } +// [/RLVa:KB] + const LLInventoryObject *obj = model->getItem(id); if (obj && obj->getIsLinkType()) { @@ -382,8 +391,9 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id) return FALSE; } -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0b) | Added: RLVa-1.3.0b - if ( (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().isLockedFolder(id, RLV_LOCK_ANY)) ) +// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g + if ( ((rlv_handler_t::isEnabled()) && + (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveFolder(id))) ) { return FALSE; } @@ -430,9 +440,8 @@ BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id) return FALSE; } -// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0b) | Added: RLVa-1.3.0b - if ( (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().isLockedFolder(id, RLV_LOCK_ANY)) && - (model->isObjectDescendentOf(id, gInventory.getRootFolderID())) ) +// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g + if ( (rlv_handler_t::isEnabled()) && (model == &gInventory) && (!RlvFolderLocks::instance().canRenameFolder(id)) ) { return FALSE; } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1d01a5ee11..4e1af629e0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -46,8 +46,9 @@ #include "llviewerregion.h" #include "llcallbacklist.h" #include "llvoavatarself.h" -// [RLVa:KB] - Checked: RLVa-1.2.0a (2010-03-05) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] //-TT Patch: ReplaceWornItemsOnly #include "llviewerobjectlist.h" diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index a5d8f34592..6ba304acdd 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -877,8 +877,11 @@ bool LLInventoryPanel::beginIMSession() std::string name; static int session_num = 1; - LLDynamicArray members; - EInstantMessage type = IM_SESSION_CONFERENCE_START; +// LLDynamicArray members; +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + uuid_vec_t members; +// [/RLVa:KB] +// EInstantMessage type = IM_SESSION_CONFERENCE_START; std::set::const_iterator iter; for (iter = selected_items.begin(); iter != selected_items.end(); iter++) @@ -920,7 +923,10 @@ bool LLInventoryPanel::beginIMSession() id = item_array.get(i)->getCreatorUUID(); if(at.isBuddyOnline(id)) { - members.put(id); +// members.put(id); +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + members.push_back(id); +// [/RLVa:KB] } } } @@ -942,7 +948,10 @@ bool LLInventoryPanel::beginIMSession() if(at.isBuddyOnline(id)) { - members.put(id); +// members.put(id); +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + members.push_back(id); +// [/RLVa:KB] } } } //if IT_CALLINGCARD @@ -958,11 +967,14 @@ bool LLInventoryPanel::beginIMSession() name = llformat("Session %d", session_num++); } - LLUUID session_id = gIMMgr->addSession(name, type, members[0], members); - if (session_id != LLUUID::null) - { - LLIMFloater::show(session_id); - } +// LLUUID session_id = gIMMgr->addSession(name, type, members[0], members); +// if (session_id != LLUUID::null) +// { +// LLIMFloater::show(session_id); +// } +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + LLAvatarActions::startConference(members); +// [/RLVa:KB] return true; } diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 004d670137..5fb20fe6f5 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -325,23 +325,32 @@ void LLFloaterMove::setMovementMode(const EMovementMode mode) { case MM_RUN: gAgent.setAlwaysRun(); - gAgent.setRunning(); +// gAgent.setRunning(); break; case MM_WALK: gAgent.clearAlwaysRun(); - gAgent.clearRunning(); +// gAgent.clearRunning(); break; default: //do nothing for other modes (MM_FLY) break; } // tell the simulator. - gAgent.sendWalkRun(gAgent.getAlwaysRun()); - - updateButtonsWithMovementMode(mode); +// gAgent.sendWalkRun(gAgent.getAlwaysRun()); +// +// updateButtonsWithMovementMode(mode); +// +// bool bHideModeButtons = MM_FLY == mode +// || (isAgentAvatarValid() && gAgentAvatarp->isSitting()); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + // Running may have been restricted so update walk-vs-run from the agent's actual running state + if ( (MM_WALK == mode) || (MM_RUN == mode) ) + mCurrentMode = (gAgent.getRunning()) ? MM_RUN : MM_WALK; - bool bHideModeButtons = MM_FLY == mode - || (isAgentAvatarValid() && gAgentAvatarp->isSitting()); + updateButtonsWithMovementMode(mCurrentMode); + + bool bHideModeButtons = (MM_FLY == mCurrentMode) || (isAgentAvatarValid() && gAgentAvatarp->isSitting()); +// [/RLVa:KB] showModeButtons(!bHideModeButtons); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 96e44d2f2a..c42aeb37b9 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -415,6 +415,13 @@ private: */ static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + /** + * Checks whether the user has opted to embed (certain) notifications in IM sessions + */ + static bool canEmbedNotificationInIM(const LLNotificationPtr& notification); +// [/SL:KB] + }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index c3cee66e93..e1578f81e4 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -37,6 +37,9 @@ #include "llfloaterreg.h" #include "llnearbychat.h" #include "llimfloater.h" +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h +#include "rlvhandler.h" +// [/RLVa:KB] using namespace LLNotificationsUI; @@ -166,25 +169,67 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) // static bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) { - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); +// return OFFER_FRIENDSHIP == notification->getName() +// || USER_GIVE_ITEM == notification->getName() +// || TELEPORT_OFFERED == notification->getName(); +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a +// return +// (canEmbedNotificationInIM(notification)) && +// ( (OFFER_FRIENDSHIP == notification->getName()) || (USER_GIVE_ITEM == notification->getName()) || +// (TELEPORT_OFFERED == notification->getName()) ); +// [/SL:KB] +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h + return + (canEmbedNotificationInIM(notification)) && + ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.canStartIM(notification->getPayload()["from_id"].asUUID())) ) && + ( (OFFER_FRIENDSHIP == notification->getName()) || (USER_GIVE_ITEM == notification->getName()) || + (TELEPORT_OFFERED == notification->getName()) ); +// [/RLVa:KB] } +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a +// static +bool LLHandlerUtil::canEmbedNotificationInIM(const LLNotificationPtr& notification) +{ + switch (gSavedSettings.getS32("NotificationCanEmbedInIM")) + { + case 1: // Focused + return isIMFloaterFocused(notification); + case 2: // Never + return false; + case 0: // Always (Viewer 2 default) + default: + return true; + } +} +// [/SL:KB] + // static bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) { - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); +// return OFFER_FRIENDSHIP == notification->getName() +// || USER_GIVE_ITEM == notification->getName() +// || TELEPORT_OFFERED == notification->getName(); +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + return + (canEmbedNotificationInIM(notification)) && + ( (OFFER_FRIENDSHIP == notification->getName()) || (USER_GIVE_ITEM == notification->getName()) || + (TELEPORT_OFFERED == notification->getName()) ); +// [/SL:KB] } // static bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) { - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); +// return OFFER_FRIENDSHIP == notification->getName() +// || USER_GIVE_ITEM == notification->getName() +// || TELEPORT_OFFERED == notification->getName(); +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + return + (canEmbedNotificationInIM(notification)) && + ( (OFFER_FRIENDSHIP == notification->getName()) || (USER_GIVE_ITEM == notification->getName()) || + (TELEPORT_OFFERED == notification->getName()) ); +// [/SL:KB] } // static @@ -214,7 +259,11 @@ bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) || TELEPORT_OFFERED == notification->getName()) { // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 - return ! isIMFloaterOpened(notification); +// return ! isIMFloaterOpened(notification); +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + // Force a toast if the user opted not to embed notifications panels in IMs + return (!canEmbedNotificationInIM(notification)) || (!isIMFloaterOpened(notification)); +// [/SL:KB] } return true; diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 4dfaad9589..59c6abe825 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -101,12 +101,14 @@ bool LLOfferHandler::processNotification(const LLSD& notify) LLUUID session_id; // if (LLHandlerUtil::canSpawnIMSession(notification)) -// [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f +// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Modified: RLVa-1.3.0h // Don't spawn a new IM session for inventory offers if this notification was subject to @shownames=n - // RELEASE-RLVa: [SL-2.3.0] Test on every new release to make sure the notification gets routed the way we want it to be - bool fSpawnIM = (LLHandlerUtil::canSpawnIMSession(notification)) && (!notification->getPayload().has("rlv_shownames")); - if (fSpawnIM) + bool spawn_session = (LLHandlerUtil::canSpawnIMSession(notification)) && (!notification->getPayload().has("rlv_shownames")); // [/RLVa:KB] +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a +// bool spawn_session = LLHandlerUtil::canSpawnIMSession(notification); + if (spawn_session) +// [/SL:KB] { const std::string name = LLHandlerUtil::getSubstitutionName(notification); @@ -117,11 +119,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify) bool show_toast = LLHandlerUtil::canSpawnToast(notification); // bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); -// [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a // NOTE: add_notid_to_im needs to be FALSE if we suppressed spawning an IM because in that case the notification needs to // be routed to the "syswell" or the inventory offer floater will dissapear and the user won't be able to accept it - bool add_notid_to_im = (fSpawnIM) && (LLHandlerUtil::canAddNotifPanelToIM(notification)); -// [/RLVa:KB] + bool add_notid_to_im = (spawn_session) && (LLHandlerUtil::canAddNotifPanelToIM(notification)); +// [/SL:KB] if (add_notid_to_im) { LLHandlerUtil::addNotifPanelToIM(notification); @@ -191,19 +193,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify) { // if (LLHandlerUtil::canAddNotifPanelToIM(notification) // && !LLHandlerUtil::isIMFloaterOpened(notification)) -// [SL:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f - // Repro: - // 1) have someone drop you 2 inventory items (new IM session will be spawned) - // 2) accept/decline the inventory offers as they come in - // -> unread IM counter shows 0 - // 3) toggle "Enable plain text chat history" while the IM session with the inventory offers isn't the active session - // -> unread IM counter shows -2 - // -> LLHandlerUtil::decIMMesageCounter() really should be fixed to check for "0" before decreasing the count but - // there are enough bugfixes in RLVa as it is already :( - // Fix: - // - the one and only time we need to decrease the unread IM count is when we've clicked any of the buttons on the *toast* - // - since LLIMFloater::updateMessages() hides the toast when we open the IM (which resets the unread count to 0) we should - // *only* decrease the unread IM count if there's a visible toast since the unread count will be at 0 otherwise anyway +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a + // LLHandlerUtil::canAddNotifPanelToIM() won't necessarily tell us whether the notification went into an IM or to the syswell + // -> the one and only time we need to decrease the unread IM count is when we've clicked any of the buttons on the *toast* + // -> since LLIMFloater::updateMessages() hides the toast when we open the IM (which resets the unread count to 0) we should + // *only* decrease the unread IM count if there's a visible toast since the unread count will be at 0 otherwise anyway LLScreenChannel* pChannel = dynamic_cast(mChannel); LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification->getID()) : NULL; if ( (pToast) && (!pToast->getCanBeStored()) ) @@ -223,10 +217,9 @@ bool LLOfferHandler::processNotification(const LLSD& notify) void LLOfferHandler::onDeleteToast(LLToast* toast) { // if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) -// [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f - // BUGFIX: LLHandlerUtil::canAddNotifPanelToIM() won't necessarily tell us whether the notification went into an IM or to the syswell +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a if (toast->getCanBeStored()) -// [/RLVa:KB] +// [/SL:KB] { // send a signal to the counter manager mDelNotificationSignal(); @@ -242,12 +235,25 @@ void LLOfferHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this - // don't delete notification since it may be used by IM floater - && !LLHandlerUtil::canAddNotifPanelToIM(notification)) +// if (notification +// && LLNotificationManager::getInstance()->getHandlerForNotification( +// notification->getType()) == this +// // don't delete notification since it may be used by IM floater +// && !LLHandlerUtil::canAddNotifPanelToIM(notification)) +// { +// LLNotifications::instance().cancel(notification); +// } +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a + // NOTE: this will be fired from LLScreenChannel::killToastByNotificationID() which treats visible and stored toasts differently + if ( (notification) && (!notification->isCancelled()) && + (LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) ) { - LLNotifications::instance().cancel(notification); + LLScreenChannel* pChannel = dynamic_cast(mChannel); + LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification->getID()) : NULL; + if ( (!pToast) || (pToast->getCanBeStored()) ) + { + LLNotifications::instance().cancel(notification); + } } +// [/SL:KB] } diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 290d76333a..47425c3f19 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -59,8 +59,9 @@ #include "llviewerregion.h" #include "llviewerwindow.h" #include "llworld.h" -// [RLVa:KB] - Checked: 2010-03-31 (RLVa-1.2.0c) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] // diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index b69fdb6fb9..8b3bf16c5a 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -41,10 +41,6 @@ #include "llsidetray.h" #include "llviewercontrol.h" #include "llviewerdisplayname.h" -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) -#include "rlvhandler.h" -#include "rlvui.h" -// [/RLVa:KB] // Linden libraries #include "llavatarnamecache.h" // IDEVO @@ -199,9 +195,6 @@ LLPanelMyProfileEdit::LLPanelMyProfileEdit() setAvatarId(gAgent.getID()); LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLPanelMyProfileEdit::onAvatarNameChanged, this)); -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Added: RLVa-1.2.1a - RlvUIEnabler::instance().addBehaviourToggleCallback(RLV_BHVR_DISPLAYNAME, boost::bind(&LLPanelMyProfileEdit::onAvatarNameChanged, this)); -// [/RLVa:KB] } void LLPanelMyProfileEdit::onOpen(const LLSD& key) @@ -235,10 +228,7 @@ void LLPanelMyProfileEdit::onOpen(const LLSD& key) getChild("user_slid")->setVisible( true ); getChild("display_name_label")->setVisible( true ); getChild("set_name")->setVisible( true ); -// getChild("set_name")->setEnabled( true ); -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Added: RLVa-1.2.1a - getChild("set_name")->setEnabled( !gRlvHandler.hasBehaviour(RLV_BHVR_DISPLAYNAME) ); -// [/RLVa:KB] + getChild("set_name")->setEnabled( true ); getChild("solo_user_name")->setVisible( false ); getChild("solo_username_label")->setVisible( false ); } @@ -310,10 +300,7 @@ void LLPanelMyProfileEdit::onNameCache(const LLUUID& agent_id, const LLAvatarNam getChild("user_slid")->setVisible( true ); getChild("display_name_label")->setVisible( true ); getChild("set_name")->setVisible( true ); -// getChild("set_name")->setEnabled( true ); -// [RLVa:KB] - Checked: 2010-11-02 (RLVa-1.2.2a) | Added: RLVa-1.2.1a - getChild("set_name")->setEnabled( !gRlvHandler.hasBehaviour(RLV_BHVR_DISPLAYNAME) ); -// [/RLVa:KB] + getChild("set_name")->setEnabled( true ); getChild("solo_user_name")->setVisible( false ); getChild("solo_username_label")->setVisible( false ); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 9e1b78656b..6e19c34241 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -68,8 +68,9 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" //#include "llfirstuse.h" -// [RLVa:KB] - Checked: 2010-03-31 (RLVa-1.2.0c) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "llvoavatarself.h" // [/RLVa:KB] #include "lldrawpool.h" diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1fbfea01c1..8dfa2531b0 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -63,8 +63,9 @@ #include "llviewerregion.h" #include "llviewerobjectlist.h" #include "llviewermessage.h" -// [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.2.0b) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] ///---------------------------------------------------------------------------- diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 4e62ae962b..6f5c964838 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1052,7 +1052,11 @@ void LLPanelPeople::updateButtons() } LLPanel* groups_panel = mTabContainer->getCurrentPanel(); - groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected +// groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected +// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f + groups_panel->getChildView("activate_btn")->setEnabled( + item_selected && !cur_group_active && !gRlvHandler.hasBehaviour(RLV_BHVR_SETGROUP)); // "none" or a non-active group selected +// [/RLVa:KB] groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); } else diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index e892e90842..16f68d4e31 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -85,8 +85,9 @@ #include "lltrans.h" #include "llviewercontrol.h" #include "llappviewer.h" -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] const std::string HELLO_LSL = diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index d3d889e1ef..549330001d 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -860,8 +860,7 @@ LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id) // if (it == mStoredToastList.end()) // return NULL; -// [SL:KB] - Checked: 2010-04-21 (RLVa-1.2.0f) | Added: RLVa-1.2.0f - // BUGFIX-SL: we need to get the visible toast in LLOfferHandler::processNotification() whether it's "stored" or not +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a if (it == mStoredToastList.end()) { // If we can't find it among the stored toasts then widen it to "all visible toasts" diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index be64fde277..a8f5f3475d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -90,7 +90,7 @@ #include "llvoavatarself.h" #include "llvovolume.h" #include "pipeline.h" -// [RLVa:KB] - Checked: 2010-03-23 (RLVa-1.2.0a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" // [/RLVa:KB] diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index fc69157a40..f4dca37826 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -47,7 +47,10 @@ LLToastPanel::~LLToastPanel() std::string LLToastPanel::getTitle() { // *TODO: create Title and localize it. If it will be required. - return mNotification->getMessage(); +// return mNotification->getMessage(); +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + return (mNotification->hasLabel()) ? mNotification->getLabel() : mNotification->getMessage(); +// [/SL:KB] } //virtual diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index fad738760a..70f99a96fe 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -60,8 +60,9 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llworld.h" -// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] // syntactic sugar diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6990f79c41..fc2d0d777e 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -77,8 +77,9 @@ #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llpostprocess.h" -// [RLVa:KB] - Checked: 2010-08-22 (RLVa-1.2.1a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] extern LLPointer gStartTexture; diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index e1dd72dddc..b7dccd08d6 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -329,8 +329,11 @@ void LLViewerJoystick::handleRun(F32 inc) if (1 == mJoystickRun) { ++mJoystickRun; - gAgent.setRunning(); - gAgent.sendWalkRun(gAgent.getRunning()); +// gAgent.setRunning(); +// gAgent.sendWalkRun(gAgent.getRunning()); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + gAgent.setTempRun(); +// [/RLVa:KB] } else if (0 == mJoystickRun) { @@ -345,8 +348,11 @@ void LLViewerJoystick::handleRun(F32 inc) --mJoystickRun; if (0 == mJoystickRun) { - gAgent.clearRunning(); - gAgent.sendWalkRun(gAgent.getRunning()); +// gAgent.clearRunning(); +// gAgent.sendWalkRun(gAgent.getRunning()); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + gAgent.clearTempRun(); +// [/RLVa:KB] } } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 1aa9fd8a45..6f4f449e46 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -41,6 +41,9 @@ #include "llvoavatarself.h" #include "llfloatercamera.h" #include "llinitparam.h" +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i +#include "rlvhandler.h" +// [/RLVa:KB] // // Constants @@ -91,14 +94,18 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m { if (KEYSTATE_UP == s) { - if (gAgent.mDoubleTapRunMode == mode && - gAgent.getRunning() && - !gAgent.getAlwaysRun()) - { - // Turn off temporary running. - gAgent.clearRunning(); - gAgent.sendWalkRun(gAgent.getRunning()); - } +// if (gAgent.mDoubleTapRunMode == mode && +// gAgent.getRunning() && +// !gAgent.getAlwaysRun()) +// { +// // Turn off temporary running. +// gAgent.clearRunning(); +// gAgent.sendWalkRun(gAgent.getRunning()); +// } +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + if ( (gAgent.mDoubleTapRunMode == mode) && (gAgent.getTempRun()) ) + gAgent.clearTempRun(); +// [/RLVa:KB] } else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") && KEYSTATE_DOWN == s && @@ -109,8 +116,11 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m { // Same walk-key was pushed again quickly; this is a // double-tap so engage temporary running. - gAgent.setRunning(); - gAgent.sendWalkRun(gAgent.getRunning()); +// gAgent.setRunning(); +// gAgent.sendWalkRun(gAgent.getRunning()); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + gAgent.setTempRun(); +// [/RLVa:KB] } // Pressing any walk-key resets the double-tap timer diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index cd0ee91c6b..4961b27587 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -105,9 +105,9 @@ #include "lltrans.h" #include "lleconomy.h" #include "boost/unordered_map.hpp" - -// [RLVa:KB] - Checked: 2010-03-09 (RLVa-1.2.0a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] using namespace LLVOAvatarDefines; @@ -5496,16 +5496,16 @@ class LLWorldAlwaysRun : public view_listener_t if (gAgent.getAlwaysRun()) { gAgent.clearAlwaysRun(); - gAgent.clearRunning(); +// gAgent.clearRunning(); } else { gAgent.setAlwaysRun(); - gAgent.setRunning(); +// gAgent.setRunning(); } // tell the simulator. - gAgent.sendWalkRun(gAgent.getAlwaysRun()); +// gAgent.sendWalkRun(gAgent.getAlwaysRun()); // Update Movement Controls according to AlwaysRun mode LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun()); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index b9cc9f614a..427ac56d6c 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1485,7 +1485,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // end has already copied the items into your inventory, // so we can fetch it out of our inventory. // [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e -#ifdef RLV_EXTENSION_GIVETORLV_A2A if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && (LLAssetType::AT_CATEGORY == mType) && (RlvInventory::instance().getSharedRoot()) && (mDesc.find(RLV_PUTINV_PREFIX) == 0) ) { @@ -1496,7 +1495,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& else gInventory.addObserver(pOfferObserver); } -#endif // RLV_EXTENSION_GIVETORLV_A2A // [/RLVa:KB] LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(mObjectID, from_string); @@ -1752,7 +1750,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const { std::string::size_type idxToken = mDesc.find("' ( http://"); if (std::string::npos != idxToken) - RlvBehaviourNotifyHandler::instance().sendNotification("accepted_in_inv inv_offer " + mDesc.substr(1, idxToken - 1)); + RlvBehaviourNotifyHandler::sendNotification("accepted_in_inv inv_offer " + mDesc.substr(1, idxToken - 1)); } // [/RLVa:KB] @@ -1810,7 +1808,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const { std::string::size_type idxToken = mDesc.find("' ( http://"); if (std::string::npos != idxToken) - RlvBehaviourNotifyHandler::instance().sendNotification("declined inv_offer " + mDesc.substr(1, idxToken - 1)); + RlvBehaviourNotifyHandler::sendNotification("declined inv_offer " + mDesc.substr(1, idxToken - 1)); } // [/RLVa:KB] @@ -1951,6 +1949,9 @@ void inventory_offer_handler(LLOfferInfo* info) } else { +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + args["NAME_LABEL"] = LLSLURL("agent", info->mFromID, "completename").getSLURLString(); +// [/SL:KB] args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString(); } std::string verb = "select?name=" + LLURI::escape(msg); @@ -3052,6 +3053,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD args; // *TODO: Translate -> [FIRST] [LAST] (maybe) +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + args["NAME_LABEL"] = LLSLURL("agent", from_id, "completename").getSLURLString(); +// [/SL:KB] args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); args["MESSAGE"] = message; args["MATURITY_STR"] = region_access_str; @@ -3138,6 +3142,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + args["NAME_LABEL"] = LLSLURL("agent", from_id, "completename").getSLURLString(); +// [/SL:KB] args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); if(message.empty()) { @@ -4258,7 +4265,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) } // send walk-vs-run status - gAgent.sendWalkRun(gAgent.getRunning() || gAgent.getAlwaysRun()); +// gAgent.sendWalkRun(gAgent.getRunning() || gAgent.getAlwaysRun()); +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + gAgent.sendWalkRun(); +// [/RLVa:KB] // If the server version has changed, display an info box and offer // to display the release notes, unless this is the initial log in. diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index aa677098d2..7391f5a33e 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -100,8 +100,9 @@ #include "lltrans.h" #include "llsdutil.h" #include "llmediaentry.h" -// [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.2.0b) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] //#define DEBUG_UPDATE_TYPE diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 78ac3c1b79..0da3306020 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -56,8 +56,9 @@ #include "llviewerstats.h" #include "llviewerregion.h" #include "llappearancemgr.h" -// [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] #if LL_MSVC diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a8b9259bcc..ed722c7ec4 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -63,8 +63,9 @@ #include "llmediadataclient.h" #include "llagent.h" #include "llviewermediafocus.h" -// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] const S32 MIN_QUIET_FRAMES_COALESCE = 30; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index f8e80f5a9a..2916d804bb 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -40,8 +40,9 @@ #include "llviewermenu.h" // [/SL:KB] #include "llvoavatarself.h" -// [RLVa:KB] - Checked: 2010-09-04 (RLVa-1.2.1a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] class LLFindOutfitItems : public LLInventoryCollectFunctor diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index a2ba65460a..f619a0d586 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -103,9 +103,9 @@ #if !LL_DARWIN #include "llfloaterhardwaresettings.h" #endif - -// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] #ifdef _DEBUG diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index 01df6d0fa2..4f9678d5de 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2010, Kitty Barnett + * Copyright (c) 2009-2011, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -17,7 +17,6 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" #include "llagentui.h" -#include "llappviewer.h" #include "llavatarnamecache.h" #include "llinstantmessage.h" #include "llnotificationsutil.h" @@ -29,29 +28,16 @@ #include "llworld.h" #include "rlvcommon.h" +#include "rlvhelper.h" #include "rlvhandler.h" #include "rlvlocks.h" +#include + // ============================================================================ // RlvNotifications // -#ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR -// Checked: 2009-12-05 (RLVa-1.1.0h) | Added: RLVa-1.1.0h -/* -void RlvNotifications::notifyBehaviour(ERlvBehaviour eBhvr, ERlvParamType eType) -{ - const std::string& strMsg = RlvStrings::getBehaviourNotificationString(eBhvr, eType); - if (!strMsg.empty()) - { - LLSD argsNotify; - argsNotify["MESSAGE"] = strMsg; - LLNotifications::instance().add("SystemMessageTip", argsNotify); - } -} -*/ -#endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR - // Checked: 2009-11-13 (RLVa-1.1.0b) | Modified: RLVa-1.1.0b /* void RlvNotifications::warnGiveToRLV() @@ -150,10 +136,6 @@ bool RlvSettings::onChangedSettingBOOL(const LLSD& sdValue, bool* pfSetting) std::vector RlvStrings::m_Anonyms; std::map RlvStrings::m_StringMap; -#ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR -std::map RlvStrings::m_BhvrAddMap; -std::map RlvStrings::m_BhvrRemMap; -#endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR // Checked: 2010-03-09 (RLVa-1.2.0a) | Added: RLVa-1.1.0h void RlvStrings::initClass() @@ -189,25 +171,6 @@ void RlvStrings::initClass() m_Anonyms.push_back(pAnonymNode->getTextContents()); } } - #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR - else if (pNode->hasName("behaviour-notifications")) - { - std::string strBhvr, strType; ERlvBehaviour eBhvr; - for (LLXMLNode* pNotifyNode = pNode->getFirstChild(); pNotifyNode != NULL; pNotifyNode = pNotifyNode->getNextSibling()) - { - if ( (!pNotifyNode->hasName("notification")) || (!pNotifyNode->getAttributeString("type", strType)) || - (!pNotifyNode->getAttributeString("behaviour", strBhvr)) || - ((eBhvr = RlvCommand::getBehaviourFromString(strBhvr)) == RLV_BHVR_UNKNOWN) ) - { - continue; - } - if ("add" == strType) - m_BhvrAddMap.insert(std::pair(eBhvr, pNotifyNode->getTextContents())); - else if ("rem" == strType) - m_BhvrRemMap.insert(std::pair(eBhvr, pNotifyNode->getTextContents())); - } - } - #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR } if ( (m_StringMap.empty()) || (m_Anonyms.empty()) ) @@ -232,24 +195,6 @@ const std::string& RlvStrings::getAnonym(const std::string& strName) return m_Anonyms[nHash % m_Anonyms.size()]; } -#ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR -// Checked: 2009-12-05 (RLVa-1.1.0h) | Added: RLVa-1.1.0h -const std::string& RlvStrings::getBehaviourNotificationString(ERlvBehaviour eBhvr, ERlvParamType eType) -{ - if (RLV_TYPE_ADD == eType) - { - std::map::const_iterator itString = m_BhvrAddMap.find(eBhvr); - return (itString != m_BhvrAddMap.end()) ? itString->second : LLStringUtil::null; - } - else if (RLV_TYPE_REMOVE == eType) - { - std::map::const_iterator itString = m_BhvrRemMap.find(eBhvr); - return (itString != m_BhvrRemMap.end()) ? itString->second : LLStringUtil::null; - } - return LLStringUtil::null; -} -#endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR - // Checked: 2009-11-11 (RLVa-1.1.0a) | Added: RLVa-1.1.0a const std::string& RlvStrings::getString(const std::string& strStringName) { @@ -336,27 +281,23 @@ bool RlvUtil::m_fForceTp = false; // Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a void RlvUtil::filterLocation(std::string& strUTF8Text) { - // TODO-RLVa: if either the region or parcel name is a simple word such as "a" or "the" then confusion will ensue? - // -> not sure how you would go about preventing this though :|... - // Filter any mention of the surrounding region names LLWorld::region_list_t regions = LLWorld::getInstance()->getRegionList(); const std::string& strHiddenRegion = RlvStrings::getString(RLV_STRING_HIDDEN_REGION); for (LLWorld::region_list_t::const_iterator itRegion = regions.begin(); itRegion != regions.end(); ++itRegion) - rlvStringReplace(strUTF8Text, (*itRegion)->getName(), strHiddenRegion); + boost::ireplace_all(strUTF8Text, (*itRegion)->getName(), strHiddenRegion); // Filter any mention of the parcel name LLViewerParcelMgr* pParcelMgr = LLViewerParcelMgr::getInstance(); if (pParcelMgr) - rlvStringReplace(strUTF8Text, pParcelMgr->getAgentParcelName(), RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL)); + boost::ireplace_all(strUTF8Text, pParcelMgr->getAgentParcelName(), RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL)); } // Checked: 2010-12-08 (RLVa-1.2.2c) | Modified: RLVa-1.2.2c void RlvUtil::filterNames(std::string& strUTF8Text, bool fFilterLegacy) { - std::vector idAgents; + uuid_vec_t idAgents; LLWorld::getInstance()->getAvatars(&idAgents, NULL); - for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++) { LLAvatarName avName; @@ -370,17 +311,17 @@ void RlvUtil::filterNames(std::string& strUTF8Text, bool fFilterLegacy) strLegacyName = avName.getLegacyName(); // If the display name is a subset of the legacy name we need to filter that first, otherwise it's the other way around - if (std::string::npos != strLegacyName.find(avName.mDisplayName)) + if (boost::icontains(strLegacyName, avName.mDisplayName)) { if (!strLegacyName.empty()) - rlvStringReplace(strUTF8Text, strLegacyName, strAnonym); - rlvStringReplace(strUTF8Text, avName.mDisplayName, strAnonym); + boost::ireplace_all(strUTF8Text, strLegacyName, strAnonym); + boost::ireplace_all(strUTF8Text, avName.mDisplayName, strAnonym); } else { - rlvStringReplace(strUTF8Text, avName.mDisplayName, strAnonym); + boost::ireplace_all(strUTF8Text, avName.mDisplayName, strAnonym); if (!strLegacyName.empty()) - rlvStringReplace(strUTF8Text, strLegacyName, strAnonym); + boost::ireplace_all(strUTF8Text, strLegacyName, strAnonym); } } } @@ -421,27 +362,15 @@ bool RlvUtil::isNearbyRegion(const std::string& strRegion) return false; } -// Checked: 2010-10-07 (RLVa-1.2.1f) | Added: RLVa-1.2.1f -void RlvUtil::notifyBlocked(const std::string& strRlvString) +// Checked: 2011-04-11 (RLVa-1.3.0h) | Modified: RLVa-1.3.0h +void RlvUtil::notifyBlocked(const std::string& strNotifcation, const LLSD& sdArgs) { - LLSD argsNotify; - argsNotify["MESSAGE"] = RlvStrings::getString(strRlvString); - LLNotificationsUtil::add("SystemMessageTip", argsNotify); -} + std::string strMsg = RlvStrings::getString(strNotifcation); + LLStringUtil::format(strMsg, sdArgs); -// Checked: 2010-03-01 (RLVa-1.2.0b) | Added: RLVa-1.2.0a -void RlvUtil::notifyBlockedViewXXX(LLAssetType::EType assetType) -{ - if (!RlvStrings::hasString(RLV_STRING_BLOCKED_VIEWXXX)) - return; - - LLStringUtil::format_map_t argsMsg; std::string strMsg = RlvStrings::getString(RLV_STRING_BLOCKED_VIEWXXX); - argsMsg["[TYPE]"] = LLAssetType::lookup(assetType); - LLStringUtil::format(strMsg, argsMsg); - - LLSD argsNotify; - argsNotify["MESSAGE"] = strMsg; - LLNotificationsUtil::add("SystemMessageTip", argsNotify); + LLSD sdNotify; + sdNotify["MESSAGE"] = strMsg; + LLNotificationsUtil::add("SystemMessageTip", sdNotify); } // Checked: 2010-11-11 (RLVa-1.2.1g) | Added: RLVa-1.2.1g @@ -537,6 +466,32 @@ bool rlvMenuEnableIfNot(const LLSD& sdParam) // Selection functors // +// Checked: 2010-04-11 (RLVa-1.2.0b) | Modified: RLVa-0.2.0g +bool rlvCanDeleteOrReturn() +{ + bool fIsAllowed = true; + + if (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) + { + // We'll allow if none of the prims are owned by the avie or group owned + LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection(); + RlvSelectIsOwnedByOrGroupOwned f(gAgent.getID()); + if ( (handleSel.notNull()) && ((0 == handleSel->getRootObjectCount()) || (NULL != handleSel->getFirstRootNode(&f, FALSE))) ) + fIsAllowed = false; + } + + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (isAgentAvatarValid()) ) + { + // We'll allow if the avie isn't sitting on any of the selected objects + LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection(); + RlvSelectIsSittingOn f(gAgentAvatarp->getRoot()); + if ( (handleSel.notNull()) && (handleSel->getFirstRootNode(&f, TRUE)) ) + fIsAllowed = false; + } + + return fIsAllowed; +} + // Checked: 2010-04-20 (RLVa-1.2.0f) | Modified: RLVa-0.2.0f bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode) { @@ -624,6 +579,18 @@ bool rlvPredCanNotRemoveItem(const LLViewerInventoryItem* pItem) return !rlvPredCanRemoveItem(pItem); } +// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f +RlvPredIsEqualOrLinkedItem::RlvPredIsEqualOrLinkedItem(const LLUUID& idItem) +{ + m_pItem = gInventory.getItem(idItem); +} + +// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f +bool RlvPredIsEqualOrLinkedItem::operator()(const LLViewerInventoryItem* pItem) const +{ + return (m_pItem) && (pItem) && (m_pItem->getLinkedUUID() == pItem->getLinkedUUID()); +} + // ============================================================================ // Various public helper functions // diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h index 3e593082d8..1b762971c4 100644 --- a/indra/newview/rlvcommon.h +++ b/indra/newview/rlvcommon.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2010, Kitty Barnett + * Copyright (c) 2009-2011, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -18,21 +18,45 @@ #define RLV_COMMON_H #include "llavatarname.h" -#include "llinventorymodel.h" #include "llselectmgr.h" #include "llviewercontrol.h" -#include "llviewerinventory.h" #include "rlvdefines.h" +#ifdef LL_WINDOWS + #pragma warning (push) + #pragma warning (disable : 4702) // warning C4702: unreachable code +#endif +#include +#ifdef LL_WINDOWS + #pragma warning (pop) +#endif + // ============================================================================ // Forward declarations // -class RlvCommand; +// +// General viewer source +// +class LLInventoryItem; +class LLViewerInventoryCategory; +class LLViewerInventoryItem; +class LLViewerJointAttachment; +class LLWearable; -typedef std::vector llvo_vec_t; -typedef std::vector c_llvo_vec_t; +// +// RLVa-specific +// +class RlvCommand; +typedef std::list rlv_command_list_t; +class RlvObject; + +struct RlvException; +typedef boost::variant RlvExceptionOption; + +class RlvGCTimer; +class RlvWLSnapshot; // ============================================================================ // RlvSettings @@ -44,7 +68,7 @@ template inline T rlvGetSetting(const std::string& strSetting, const return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.get(strSetting) : defaultValue; } -template inline T rlvGetPerUserSettings(const std::string& strSetting, const T& defaultValue) +template inline T rlvGetPerUserSetting(const std::string& strSetting, const T& defaultValue) { RLV_ASSERT_DBG(gSavedPerAccountSettings.controlExists(strSetting)); return (gSavedPerAccountSettings.controlExists(strSetting)) ? gSavedPerAccountSettings.get(strSetting) : defaultValue; @@ -74,7 +98,7 @@ public: static bool getShowNameTags() { return fShowNameTags; } #ifdef RLV_EXTENSION_STARTLOCATION - static bool getLoginLastLocation() { return rlvGetPerUserSettings(RLV_SETTING_LOGINLASTLOCATION, true); } + static bool getLoginLastLocation() { return rlvGetPerUserSetting(RLV_SETTING_LOGINLASTLOCATION, true); } static void updateLoginLastLocation(); #endif // RLV_EXTENSION_STARTLOCATION @@ -113,10 +137,6 @@ public: protected: static std::vector m_Anonyms; static std::map m_StringMap; - #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR - static std::map m_BhvrAddMap; - static std::map m_BhvrRemMap; - #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR }; // ============================================================================ @@ -136,10 +156,9 @@ public: static bool isForceTp() { return m_fForceTp; } static void forceTp(const LLVector3d& posDest); // Ignores restrictions that might otherwise prevent tp'ing - static void notifyBlocked(const std::string& strRlvString); + static void notifyBlocked(const std::string& strNotifcation, const LLSD& sdArgs = LLSD()); static void notifyBlockedGeneric() { notifyBlocked(RLV_STRING_BLOCKED_GENERIC); } - static void notifyBlockedTeleport() { notifyBlocked(RLV_STRING_BLOCKED_TELEPORT); } - static void notifyBlockedViewXXX(LLAssetType::EType assetType); + static void notifyBlockedViewXXX(LLAssetType::EType assetType) { notifyBlocked(RLV_STRING_BLOCKED_VIEWXXX, LLSD().with("[TYPE]", LLAssetType::lookup(assetType))); } static void notifyFailedAssertion(const std::string& strAssert, const std::string& strFile, int nLine); static void sendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null); @@ -178,6 +197,8 @@ bool rlvMenuEnableIfNot(const LLSD& sdParam); // Selection functors // +bool rlvCanDeleteOrReturn(); + struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor { RlvSelectHasLockedAttach() {} @@ -235,16 +256,18 @@ protected: struct RlvPredIsEqualOrLinkedItem { RlvPredIsEqualOrLinkedItem(const LLViewerInventoryItem* pItem) : m_pItem(pItem) {} - RlvPredIsEqualOrLinkedItem(const LLUUID& idItem) { m_pItem = gInventory.getItem(idItem); } - - bool operator()(const LLViewerInventoryItem* pItem) const - { - return (m_pItem) && (pItem) && (m_pItem->getLinkedUUID() == pItem->getLinkedUUID()); - } + RlvPredIsEqualOrLinkedItem(const LLUUID& idItem); + bool operator()(const LLViewerInventoryItem* pItem) const; protected: const LLViewerInventoryItem* m_pItem; }; +template struct RlvPredValuesEqual +{ + bool operator()(const T* pT2) const { return (pT1) && (pT2) && (*pT1 == *pT2); } + const T* pT1; +}; + // ============================================================================ // Inlined class member functions // diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index d6d1e2b6dc..23d1a814b0 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2009-2010, Kitty Barnett + * Copyright (c) 2009-2011, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; @@ -21,16 +21,10 @@ // Extensions // -// Provides access to "advanced" features through the RLVa debug menu -#define RLV_EXTENSION_FLOATER_RESTRICTIONS // Enables the Advanced / RLVa / Restrictions... floater -#define RLV_EXTENSION_HIDELOCKED // "Hide locked layers", "Hide locked attachments" and "Hide locked inventory" - // Extensions #define RLV_EXTENSION_CMD_GETSETDEBUG_EX // Extends the debug variables accessible through @getdebug_xxx/@setdebug_xxx #define RLV_EXTENSION_CMD_FINDFOLDERS // @findfolders: