Merge branch 'master' of git://github.com/Shyotl/SingularityViewer

This commit is contained in:
Lirusaito
2012-01-13 23:46:32 -05:00
29 changed files with 1641 additions and 1023 deletions

View File

@@ -214,17 +214,16 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_
bool LLAssetType::lookupCanLink(EType asset_type)
{
//Check that enabling all these other types as linkable doesn't break things.
/*const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
const AssetEntry *entry = dict->lookup(asset_type);
if (entry)
{
return entry->mCanLink;
}
return false;
*/
return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY ||
asset_type == AT_BODYPART || asset_type == AT_GESTURE);
/*return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY ||
asset_type == AT_BODYPART || asset_type == AT_GESTURE);*/
}
// static

View File

@@ -266,6 +266,7 @@ set(viewer_SOURCE_FILES
llframestats.cpp
llframestatview.cpp
llgesturemgr.cpp
llgiveinventory.cpp
llgivemoney.cpp
llglsandbox.cpp
llgroupmgr.cpp
@@ -446,6 +447,7 @@ set(viewer_SOURCE_FILES
llviewercamera.cpp
llviewercontrol.cpp
llviewerdisplay.cpp
llviewerfoldertype.cpp
llviewergenericmessage.cpp
llviewergesture.cpp
#llviewerimage.cpp
@@ -735,10 +737,12 @@ set(viewer_HEADER_FILES
llfloaterwindlight.h
llfloaterworldmap.h
llfolderview.h
llfoldervieweventlistener.h
llfollowcam.h
llframestats.h
llframestatview.h
llgesturemgr.h
llgiveinventory.h
llgivemoney.h
llgroupmgr.h
llgroupnotify.h
@@ -923,6 +927,7 @@ set(viewer_HEADER_FILES
llviewercamera.h
llviewercontrol.h
llviewerdisplay.h
llviewerfoldertype.h
llviewergenericmessage.h
llviewergesture.h
#llviewerimage.h

View File

@@ -264,7 +264,7 @@ void LLCOFMgr::addCOFItemLink(const LLInventoryItem* pItem, LLPointer<LLInventor
link_inventory_item(gAgent.getID(), pItem->getLinkedUUID(), getCOF(), pItem->getName(), strDescr, LLAssetType::AT_LINK, cb);
}
bool LLCOFMgr::isLinkInCOF(const LLUUID& idItem)
bool LLCOFMgr::isLinkInCOF(const LLUUID& idItem) const
{
LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items;
LLLinkedItemIDMatches f(gInventory.getLinkedItemID(idItem));
@@ -287,6 +287,34 @@ void LLCOFMgr::removeCOFItemLinks(const LLUUID& idItem)
}
}
BOOL LLCOFMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const
{
if (!isLinkInCOF(obj_id)) return FALSE;
// If a non-link somehow ended up in COF, allow deletion.
const LLInventoryObject *obj = gInventory.getObject(obj_id);
if (obj && !obj->getIsLinkType())
{
return FALSE;
}
// For now, don't allow direct deletion from the COF. Instead, force users
// to choose "Detach" or "Take Off".
return TRUE;
/*
const LLInventoryObject *obj = gInventory.getObject(obj_id);
if (!obj) return FALSE;
// Can't delete bodyparts, since this would be equivalent to removing the item.
if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE;
// Can't delete the folder link, since this is saved for bookkeeping.
if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE;
return FALSE;
*/
}
// ============================================================================
// Attachment functions
//

View File

@@ -31,7 +31,8 @@ public:
static const LLUUID getCOF() { return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); }
static void getDescendentsOfAssetType(const LLUUID& idCat, LLInventoryModel::item_array_t& items,
LLAssetType::EType typeAsset, bool fFollowFolderLinks);
bool isLinkInCOF(const LLUUID& idItem);
bool isLinkInCOF(const LLUUID& idItem) const;
BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const;
protected:
void addCOFItemLink(const LLUUID& idItem, LLPointer<LLInventoryCallback> cb = NULL);
void addCOFItemLink(const LLInventoryItem* pItem, LLPointer<LLInventoryCallback> cb = NULL);

View File

@@ -38,8 +38,10 @@
#include "llagent.h"
#include "llbutton.h"
#include "llfocusmgr.h"
#include "llfoldervieweventlistener.h"
#include "llinventoryview.h"
#include "llinventorymodel.h"
#include "llinventoryfunctions.h"
#include "lllineeditor.h"
#include "llscrolllistctrl.h"
#include "lltextbox.h"

View File

@@ -39,6 +39,7 @@
#include "llcheckboxctrl.h"
#include "llviewerparcelmgr.h"
#include "llfolderview.h"
#include "llfoldervieweventlistener.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
#include "llinventoryview.h"

View File

@@ -45,8 +45,10 @@
#include "llinventory.h"
#include "llcallbacklist.h"
#include "llfoldervieweventlistener.h"
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
#include "llinventoryview.h"// hacked in for the bonus context menu items.
#include "llinventoryfunctions.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"

View File

@@ -70,65 +70,9 @@ class LLMenuGL;
class LLFolderViewItem;
class LLFolderView;
class LLInventoryModel;
class LLFolderViewFunctor;
class LLScrollableContainerView;
class LLFolderViewEventListener
{
public:
virtual ~LLFolderViewEventListener( void ) {}
virtual const std::string& getName() const = 0;
virtual const std::string& getDisplayName() const = 0;
virtual const LLUUID& getUUID() const = 0;
virtual time_t getCreationDate() const = 0; // UTC seconds
virtual PermissionMask getPermissionMask() const = 0;
virtual LLUIImagePtr getIcon() const = 0;
virtual LLFontGL::StyleFlags getLabelStyle() const = 0;
virtual std::string getLabelSuffix() const = 0;
virtual void openItem( void ) = 0;
virtual void previewItem( void ) = 0;
virtual void selectItem(void) = 0;
virtual void showProperties(void) = 0;
virtual BOOL isItemRenameable() const = 0;
virtual BOOL renameItem(const std::string& new_name) = 0;
virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder
virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed
virtual BOOL removeItem() = 0;
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0;
virtual void move( LLFolderViewEventListener* parent_listener ) = 0;
virtual BOOL isItemCopyable() const = 0;
virtual BOOL copyToClipboard() const = 0;
virtual BOOL cutToClipboard() const = 0;
virtual BOOL isClipboardPasteable() const = 0;
virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual BOOL isUpToDate() const = 0;
virtual BOOL hasChildren() const = 0;
virtual LLInventoryType::EType getInventoryType() const = 0;
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) {}
// This method should be called when a drag begins. returns TRUE
// if the drag can begin, otherwise FALSE.
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
// This method will be called to determine if a drop can be
// performed, and will set drop to TRUE if a drop is
// requested. Returns TRUE if a drop is possible/happened,
// otherwise FALSE.
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data) = 0;
// This method is called when the object being referenced by the
// bridge is actually dropped. This allows for cleanup of the old
// view, reference counting, etc.
// virtual void dropped() = 0;
// this method accesses the parent and arranges and sets it as
// specified.
void arrangeAndSet(LLFolderViewItem* focus, BOOL set_selection,
BOOL take_keyboard_focus = TRUE);
};
class LLFolderViewEventListener;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -157,13 +101,6 @@ public:
class LLFolderViewItem;
class LLFolderViewFolder;
class LLFolderViewFunctor
{
public:
virtual ~LLFolderViewFunctor() {}
virtual void doFolder(LLFolderViewFolder* folder) = 0;
virtual void doItem(LLFolderViewItem* item) = 0;
};
class LLInventoryFilter
{

View File

@@ -0,0 +1,108 @@
/**
* @file llfoldervieweventlistener.h
*
* $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$
*/
#ifndef LLFOLDERVIEWEVENTLISTENER_H
#define LLFOLDERVIEWEVENTLISTENER_H
#include "lldarray.h" // *TODO: convert to std::vector
#include "llfoldertype.h"
#include "llfontgl.h" // just for StyleFlags enum
#include "llinventorytype.h"
#include "llpermissionsflags.h"
#include "llpointer.h"
#include "llwearabletype.h"
class LLFolderViewItem;
class LLFolderView;
class LLFontGL;
class LLInventoryModel;
class LLMenuGL;
class LLScrollContainer;
class LLUIImage;
class LLUUID;
// This is an abstract base class that users of the folderview classes
// would use to catch the useful events emitted from the folder
// views.
class LLFolderViewEventListener
{
public:
virtual ~LLFolderViewEventListener( void ) {}
virtual const std::string& getName() const = 0;
virtual const std::string& getDisplayName() const = 0;
virtual const LLUUID& getUUID() const = 0;
virtual time_t getCreationDate() const = 0; // UTC seconds
virtual PermissionMask getPermissionMask() const = 0;
virtual LLPointer<LLUIImage> getIcon() const = 0;
virtual LLFontGL::StyleFlags getLabelStyle() const = 0;
virtual std::string getLabelSuffix() const = 0;
virtual void openItem( void ) = 0;
virtual void previewItem( void ) = 0;
virtual void selectItem(void) = 0;
virtual void showProperties(void) = 0;
virtual BOOL isItemRenameable() const = 0;
virtual BOOL renameItem(const std::string& new_name) = 0;
virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder
virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed
virtual BOOL removeItem() = 0;
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0;
virtual void move( LLFolderViewEventListener* parent_listener ) = 0;
virtual BOOL isItemCopyable() const = 0;
virtual BOOL copyToClipboard() const = 0;
virtual BOOL cutToClipboard() const = 0;
virtual BOOL isClipboardPasteable() const = 0;
virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual BOOL isUpToDate() const = 0;
virtual BOOL hasChildren() const = 0;
virtual LLInventoryType::EType getInventoryType() const = 0;
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) {}
// This method should be called when a drag begins. returns TRUE
// if the drag can begin, otherwise FALSE.
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
// This method will be called to determine if a drop can be
// performed, and will set drop to TRUE if a drop is
// requested. Returns TRUE if a drop is possible/happened,
// otherwise FALSE.
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data) = 0;
// This method is called when the object being referenced by the
// bridge is actually dropped. This allows for cleanup of the old
// view, reference counting, etc.
// virtual void dropped() = 0;
// this method accesses the parent and arranges and sets it as
// specified.
void arrangeAndSet(LLFolderViewItem* focus, BOOL set_selection,
BOOL take_keyboard_focus = TRUE);
};
#endif

View File

@@ -0,0 +1,541 @@
/**
* @file llgiveinventory.cpp
* @brief LLGiveInventory class implementation
*
* $LicenseInfo:firstyear=2010&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 "llgiveinventory.h"
// library includes
#include "llnotificationsutil.h"
#include "lltrans.h"
// newview includes
#include "llagent.h"
#include "llagentdata.h"
#include "llagentui.h"
#include "llagentwearables.h"
#include "llfloatertools.h" // for gFloaterTool
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llimview.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
#include "llmutelist.h"
#include "llviewerobjectlist.h"
#include "llvoavatarself.h"
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
// bit from there to give some pad.
const S32 MAX_ITEMS = 42;
class LLGiveable : public LLInventoryCollectFunctor
{
public:
LLGiveable() : mCountLosing(0) {}
virtual ~LLGiveable() {}
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
S32 countNoCopy() const { return mCountLosing; }
protected:
S32 mCountLosing;
};
bool LLGiveable::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
// All categories can be given.
if (cat)
return true;
bool allowed = false;
if(item)
{
allowed = itemTransferCommonlyAllowed(item);
if(allowed &&
!item->getPermissions().allowOperationBy(PERM_TRANSFER,
gAgent.getID()))
{
allowed = FALSE;
}
if(allowed &&
!item->getPermissions().allowCopyBy(gAgent.getID()))
{
++mCountLosing;
}
}
return allowed;
}
class LLUncopyableItems : public LLInventoryCollectFunctor
{
public:
LLUncopyableItems() {}
virtual ~LLUncopyableItems() {}
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
};
bool LLUncopyableItems::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
bool uncopyable = false;
if(item)
{
if (itemTransferCommonlyAllowed(item) &&
!item->getPermissions().allowCopyBy(gAgent.getID()))
{
uncopyable = true;
}
}
return uncopyable;
}
// static
bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item)
{
if (!item) return false;
if (!isAgentAvatarValid()) return false;
if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID))
{
return false;
}
bool acceptable = true;
switch(item->getType())
{
case LLAssetType::AT_CALLINGCARD:
acceptable = false;
break;
case LLAssetType::AT_OBJECT:
// <edit>
/*if(my_avatar->isWearingAttachment(item->getUUID()))
{
acceptable = false;
}*/
// </edit>
break;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
{
// <edit>
/*bool copyable = false;
if(item->getPermissions().allowCopyBy(gAgent.getID())) copyable = true;
if(!copyable && gAgentWearables.isWearingItem(item->getUUID()))
{
acceptable = false;
}*/
// </edit>
}
break;
default:
break;
}
return acceptable;
}
// Static
bool LLGiveInventory::isInventoryGroupGiveAcceptable(const LLInventoryItem* item)
{
if(!item) return false;
if (!isAgentAvatarValid()) return false;
// These permissions are double checked in the simulator in
// LLGroupNoticeInventoryItemFetch::result().
if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID))
{
return false;
}
if (!item->getPermissions().allowCopyBy(gAgent.getID()))
{
return false;
}
bool acceptable = true;
switch(item->getType())
{
case LLAssetType::AT_CALLINGCARD:
acceptable = false;
break;
// <edit>
/*case LLAssetType::AT_OBJECT:
if(gAgentAvatarp->isWearingAttachment(item->getUUID()))
{
acceptable = false;
}*
break;*/
// </edit>
default:
break;
}
return acceptable;
}
// static
bool LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID& im_session_id/* = LLUUID::null*/)
{
bool res = true;
llinfos << "LLGiveInventory::giveInventory()" << llendl;
if(!isInventoryGiveAcceptable(item))
{
return false;
}
if (item->getPermissions().allowCopyBy(gAgentID))
{
// just give it away.
LLGiveInventory::commitGiveInventoryItem(to_agent, item, im_session_id);
}
else
{
// ask if the agent is sure.
LLSD payload;
payload["agent_id"] = to_agent;
payload["item_id"] = item->getUUID();
LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload,
&LLGiveInventory::handleCopyProtectedItem);
res = false;
}
return res;
}
void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat,
const LLUUID& im_session_id)
{
if (!cat) return;
llinfos << "LLGiveInventory::giveInventoryCategory() - "
<< cat->getUUID() << llendl;
if (!isAgentAvatarValid()) return;
// Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLGiveable giveable;
gInventory.collectDescendentsIf(cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
giveable);
S32 count = cats.count();
bool complete = true;
for(S32 i = 0; i < count; ++i)
{
if(!gInventory.isCategoryComplete(cats.get(i)->getUUID()))
{
complete = false;
break;
}
}
if(!complete)
{
LLNotificationsUtil::add("IncompleteInventory");
return;
}
count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
return;
}
else if(count == 0)
{
LLNotificationsUtil::add("NoItems");
return;
}
else
{
if(0 == giveable.countNoCopy())
{
LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id);
}
else
{
LLSD args;
args["COUNT"] = llformat("%d",giveable.countNoCopy());
LLSD payload;
payload["agent_id"] = to_agent;
payload["folder_id"] = cat->getUUID();
LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory);
}
}
}
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//static
void LLGiveInventory::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im_session_id)
{
// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat.
if (im_session_id.notNull())
{
LLSD args;
gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
}
}
// static
bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
LLInventoryItem* item = NULL;
switch(option)
{
case 0: // "Yes"
item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
if(item)
{
LLGiveInventory::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(),
item);
// delete it for now - it will be deleted on the server
// quickly enough.
gInventory.deleteObject(notification["payload"]["item_id"].asUUID());
gInventory.notifyObservers();
}
else
{
LLNotificationsUtil::add("CannotGiveItem");
}
break;
default: // no, cancel, whatever, who cares, not yes.
LLNotificationsUtil::add("TransactionCancelled");
break;
}
return false;
}
// static
void LLGiveInventory::commitGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID& im_session_id)
{
if (!item) return;
std::string name;
LLAgentUI::buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES;
U8 bucket[BUCKET_SIZE];
bucket[0] = (U8)item->getType();
memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES); /* Flawfinder: ignore */
pack_instant_message(
gMessageSystem,
gAgentID,
FALSE,
gAgentSessionID,
to_agent,
name,
item->getName(),
IM_ONLINE,
IM_INVENTORY_OFFERED,
transaction_id,
0,
LLUUID::null,
gAgent.getPositionAgent(),
NO_TIMESTAMP,
bucket,
BUCKET_SIZE);
gAgent.sendReliableMessage();
// <edit>
if (gSavedSettings.getBOOL("BroadcastViewerEffects"))
{
// </edit>
// VEFFECT: giveInventory
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
effectp->setSourceObject(gAgentAvatarp);
effectp->setTargetObject(gObjectList.findObject(to_agent));
effectp->setDuration(LL_HUD_DUR_SHORT);
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
// <edit>
}
// </edit>
gFloaterTools->dirty();
LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);
logInventoryOffer(to_agent, im_session_id);
}
// static
bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryCategory* cat = NULL;
switch(option)
{
case 0: // "Yes"
cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID());
if(cat)
{
LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
cat);
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLUncopyableItems remove;
gInventory.collectDescendentsIf(cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
remove);
S32 count = items.count();
for(S32 i = 0; i < count; ++i)
{
gInventory.deleteObject(items.get(i)->getUUID());
}
gInventory.notifyObservers();
}
else
{
LLNotificationsUtil::add("CannotGiveCategory");
}
break;
default: // no, cancel, whatever, who cares, not yes.
LLNotificationsUtil::add("TransactionCancelled");
break;
}
return false;
}
// static
void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat,
const LLUUID& im_session_id)
{
if(!cat) return;
llinfos << "LLGiveInventory::commitGiveInventoryCategory() - "
<< cat->getUUID() << llendl;
// Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLGiveable giveable;
gInventory.collectDescendentsIf(cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
giveable);
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
// MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
// 66. I've cut it down a bit from there to give some pad.
S32 count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
return;
}
else if(count == 0)
{
LLNotificationsUtil::add("NoItems");
return;
}
else
{
std::string name;
LLAgentUI::buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
U8* bucket = new U8[bucket_size];
U8* pos = bucket;
U8 type = (U8)cat->getType();
memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
pos += sizeof(U8);
memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
S32 i;
count = cats.count();
for(i = 0; i < count; ++i)
{
memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
pos += sizeof(U8);
memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
}
count = items.count();
for(i = 0; i < count; ++i)
{
type = (U8)items.get(i)->getType();
memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
pos += sizeof(U8);
memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
}
pack_instant_message(
gMessageSystem,
gAgent.getID(),
FALSE,
gAgent.getSessionID(),
to_agent,
name,
cat->getName(),
IM_ONLINE,
IM_INVENTORY_OFFERED,
transaction_id,
0,
LLUUID::null,
gAgent.getPositionAgent(),
NO_TIMESTAMP,
bucket,
bucket_size);
gAgent.sendReliableMessage();
delete[] bucket;
// <edit>
if (gSavedSettings.getBOOL("BroadcastViewerEffects"))
{
// </edit>
// VEFFECT: giveInventoryCategory
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
effectp->setSourceObject(gAgentAvatarp);
effectp->setTargetObject(gObjectList.findObject(to_agent));
effectp->setDuration(LL_HUD_DUR_SHORT);
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
// <edit>
}
// </edit>
gFloaterTools->dirty();
LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);
logInventoryOffer(to_agent, im_session_id);
}
}
// EOF

View File

@@ -0,0 +1,93 @@
/**
* @file llgiveinventory.cpp
* @brief LLGiveInventory class declaration
*
* $LicenseInfo:firstyear=2010&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$
*/
#ifndef LL_LLGIVEINVENTORY_H
#define LL_LLGIVEINVENTORY_H
class LLInventoryItem;
class LLInventoryCategory;
/**
* Class represented give inventory related actions.
*
* It has only static methods and is not intended to be instantiated for now.
*/
class LLGiveInventory
{
public:
/**
* Checks if inventory item you are attempting to transfer to a resident can be given.
*
* @return true if you can give, otherwise false.
*/
static bool isInventoryGiveAcceptable(const LLInventoryItem* item);
/**
* Checks if inventory item you are attempting to transfer to a group can be given.
*
* @return true if you can give, otherwise false.
*/
static bool isInventoryGroupGiveAcceptable(const LLInventoryItem* item);
/**
* Gives passed inventory item to specified avatar in specified session.
*/
static bool doGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID& im_session_id = LLUUID::null);
/**
* Gives passed inventory category to specified avatar in specified session.
*/
static void doGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* item,
const LLUUID &session_id = LLUUID::null);
// give inventory item functionality
static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
private:
// this class is not intended to be instantiated.
LLGiveInventory();
/**
* logs "Inventory item offered" to IM
*/
static void logInventoryOffer(const LLUUID& to_agent,
const LLUUID &im_session_id = LLUUID::null);
static void commitGiveInventoryItem(const LLUUID& to_agent,
const LLInventoryItem* item,
const LLUUID &im_session_id = LLUUID::null);
// give inventory category functionality
static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat,
const LLUUID &im_session_id = LLUUID::null);
};
#endif // LL_LLGIVEINVENTORY_H

View File

@@ -43,6 +43,7 @@
#include "llagent.h"
#include "llcallingcard.h"
#include "llcheckboxctrl.h" // for radio buttons
#include "llfoldervieweventlistener.h"
#include "llnotificationsutil.h"
#include "llradiogroup.h"
#include "llspinctrl.h"
@@ -410,7 +411,7 @@ class LLDoCreate : public inventory_panel_listener_t
LLInventoryModel* model = mPtr->getModel();
if(!model) return false;
std::string type = userdata.asString();
do_create(model, mPtr, type, LLFolderBridge::sSelf);
do_create(model, mPtr, type, LLFolderBridge::sSelf.get());
return true;
}
};

View File

@@ -52,6 +52,7 @@
#include "llspinctrl.h"
#include "lltextbox.h"
#include "llui.h"
#include "llviewerfoldertype.h"
#include "llviewercontrol.h"
#include "llfirstuse.h"
@@ -64,6 +65,7 @@
#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
#include "llgiveinventory.h"
#include "lliconctrl.h"
#include "llinventorymodel.h"
#include "llinventoryclipboard.h"
@@ -251,21 +253,7 @@ time_t LLInvFVBridge::getCreationDate() const
// Can be destroyed (or moved to trash)
BOOL LLInvFVBridge::isItemRemovable()
{
LLInventoryModel* model = getInventoryModel();
if (!model)
{
return FALSE;
}
const LLInventoryObject *obj = model->getItem(mUUID);
if (obj && obj->getIsLinkType())
{
return TRUE;
}
if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
{
return TRUE;
}
return FALSE;
return get_is_item_removable(getInventoryModel(), mUUID);
}
// Can be moved to another folder
@@ -645,6 +633,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
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)
{
@@ -654,13 +646,21 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (show_asset_id)
{
items.push_back(std::string("Copy Asset UUID"));
if ((!( isItemPermissive() || gAgent.isGodlike()))
|| (flags & FIRST_SELECTED_ITEM) == 0)
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"));
@@ -898,27 +898,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp)
{
// <edit>
bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID());
// </edit>
if(item->getParentUUID() != new_parent_id)
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
update.push_back(old_folder);
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
gInventory.accountForUpdate(update);
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setParent(new_parent_id);
// <edit>
if(send_parent_update)
// </edit>
new_item->updateParentOnServer(restamp);
model->updateItem(new_item);
model->notifyObservers();
}
change_item_parent(model, item, new_parent_id, restamp);
}
// static
@@ -927,21 +907,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp)
{
if(cat->getParentUUID() != new_parent_id)
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
update.push_back(old_folder);
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
gInventory.accountForUpdate(update);
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->setParent(new_parent_id);
new_cat->updateParentOnServer(restamp);
model->updateCategory(new_cat);
model->notifyObservers();
}
change_category_parent(model, cat, new_parent_id, restamp);
}
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
@@ -1540,11 +1506,7 @@ BOOL LLItemBridge::isItemPermissive() const
LLViewerInventoryItem* item = getItem();
if(item)
{
U32 mask = item->getPermissions().getMaskBase();
if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
{
return TRUE;
}
return item->getIsFullPerm();
}
return FALSE;
}
@@ -1553,7 +1515,7 @@ BOOL LLItemBridge::isItemPermissive() const
// | LLFolderBridge |
// +=================================================+
LLFolderBridge* LLFolderBridge::sSelf=NULL;
LLHandle<LLFolderBridge> LLFolderBridge::sSelf;
// Can be moved to another folder
BOOL LLFolderBridge::isItemMovable()
@@ -1922,29 +1884,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
return accept;
}
class LLFindWearables : public LLInventoryCollectFunctor
{
public:
LLFindWearables() {}
virtual ~LLFindWearables() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
bool LLFindWearables::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((item->getType() == LLAssetType::AT_CLOTHING)
|| (item->getType() == LLAssetType::AT_BODYPART))
{
return TRUE;
}
}
return FALSE;
}
//Used by LLFolderBridge as callback for directory recursion.
class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
{
@@ -2210,13 +2149,7 @@ void LLFolderBridge::openItem()
BOOL LLFolderBridge::isItemRenameable() const
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
if(cat && ((cat->getPreferredType() == LLFolderType::FT_NONE) || (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
&& (cat->getOwnerID() == gAgent.getID()))
{
return TRUE;
}
return FALSE;
return get_is_category_renameable(getInventoryModel(), mUUID);
}
void LLFolderBridge::restoreItem()
@@ -2247,82 +2180,34 @@ LLFolderType::EType LLFolderBridge::getPreferredType() const
// Icons for folders are based on the preferred type
LLUIImagePtr LLFolderBridge::getIcon() const
{
const char* control = NULL;
LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
preferred_type = cat->getPreferredType();
}
switch(preferred_type)
{
case LLFolderType::FT_TEXTURE:
control = "inv_folder_texture.tga";
break;
case LLFolderType::FT_SOUND:
control = "inv_folder_sound.tga";
break;
case LLFolderType::FT_CALLINGCARD:
control = "inv_folder_callingcard.tga";
break;
case LLFolderType::FT_LANDMARK:
control = "inv_folder_landmark.tga";
break;
//case LLFolderType::FT_SCRIPT:
case LLFolderType::FT_LSL_TEXT:
control = "inv_folder_script.tga";
break;
case LLFolderType::FT_OBJECT:
control = "inv_folder_object.tga";
break;
case LLFolderType::FT_NOTECARD:
control = "inv_folder_notecard.tga";
break;
//case LLFolderType::FT_CATEGORY:
// control = "inv_folder_plain_closed.tga";
// break;
case LLFolderType::FT_CLOTHING:
control = "inv_folder_clothing.tga";
break;
case LLFolderType::FT_BODYPART:
control = "inv_folder_bodypart.tga";
break;
case LLFolderType::FT_TRASH:
control = "inv_folder_trash.tga";
break;
case LLFolderType::FT_SNAPSHOT_CATEGORY:
control = "inv_folder_snapshot.tga";
break;
case LLFolderType::FT_LOST_AND_FOUND:
control = "inv_folder_lostandfound.tga";
break;
case LLFolderType::FT_ANIMATION:
control = "inv_folder_animation.tga";
break;
case LLFolderType::FT_GESTURE:
control = "inv_folder_gesture.tga";
break;
default:
control = "inv_folder_plain_closed.tga";
break;
}
return LLUI::getUIImage(control);
return getIcon(preferred_type);
}
// static
LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
{
return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE));
/*case LLAssetType::AT_MESH:
control = "inv_folder_mesh.tga";
break;*/
}
LLUIImagePtr LLFolderBridge::getOpenIcon() const
{
return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));
}
BOOL LLFolderBridge::renameItem(const std::string& new_name)
{
if(!isItemRenameable()) return FALSE;
LLInventoryModel* model = mInventoryPanel->getModel();
if(!model) return FALSE;
LLViewerInventoryCategory* cat = getCategory();
if(cat && (cat->getName() != new_name))
{
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
model->notifyObservers();
}
rename_category(getInventoryModel(), mUUID, new_name);
// return FALSE because we either notified observers (& therefore
// rebuilt) or we didn't update.
return FALSE;
@@ -2475,14 +2360,15 @@ void LLFolderBridge::pasteLinkFromClipboard()
void LLFolderBridge::staticFolderOptionsMenu()
{
if (!sSelf) return;
sSelf->folderOptionsMenu();
LLFolderBridge* selfp = sSelf.get();
if (selfp)
{
selfp->folderOptionsMenu();
}
}
void LLFolderBridge::folderOptionsMenu()
{
menuentry_vec_t disabled_items;
// *TODO: Translate
LLInventoryModel* model = getInventoryModel();
@@ -2511,7 +2397,12 @@ void LLFolderBridge::folderOptionsMenu()
mItems.push_back(std::string("IM All Contacts In Folder"));
}
}
if (!isItemRemovable())
{
mDisabledItems.push_back(std::string("Delete"));
}
// wearables related functionality for folders.
//is_wearable
LLFindWearables is_wearable;
@@ -2539,7 +2430,11 @@ void LLFolderBridge::folderOptionsMenu()
}
mItems.push_back(std::string("Take Off Items"));
}
hide_context_entries(*mMenu, mItems, disabled_items);
LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
if (menup)
{
hide_context_entries(*menup, mItems, mDisabledItems);
}
}
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@@ -2576,11 +2471,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// [/RLVa:KB]
if (lost_and_found_id == mUUID)
{
{
// This is the lost+found folder.
mItems.push_back(std::string("Empty Lost And Found"));
}
}
// clear out old menu and folder pointers
mMenu.markDead();
sSelf.markDead();
if (cof_id == mUUID)
{
mItems.push_back(std::string("Take Off Items"));
@@ -2649,16 +2547,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mWearables=TRUE;
}
mMenu = &menu;
sSelf = this;
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
uuid_vec_t folders;
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
if (category)
{
folders.push_back(category->getUUID());
folders.push_back(category->getUUID());
}
mMenu = menu.getHandle();
sSelf = getHandle();
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
fetch->fetchDescendents(folders);
inc_busy_count();
if(fetch->isEverythingComplete())
@@ -3570,7 +3469,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
rv = TRUE;
if(drop)
{
LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
LLGiveInventory::doGiveInventoryItem(item->getCreatorUUID(),
(LLInventoryItem*)cargo_data);
}
}
@@ -3591,7 +3490,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
rv = TRUE;
if(drop)
{
LLToolDragAndDrop::giveInventoryCategory(
LLGiveInventory::doGiveInventoryCategory(
item->getCreatorUUID(),
inv_cat);
}
@@ -4342,11 +4241,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
model->updateItem(new_item);
model->notifyObservers();
LLVOAvatar* avatar = gAgentAvatarp;
if( avatar )
if (isAgentAvatarValid())
{
LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
if( obj )
LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() );
if(obj)
{
LLSelectMgr::getInstance()->deselectAll();
LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );

View File

@@ -35,7 +35,7 @@
#include "llcallingcard.h"
#include "llfloaterproperties.h"
#include "llfolderview.h"
#include "llfoldervieweventlistener.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
//#include "llinventoryview.h"
@@ -302,7 +302,11 @@ public:
virtual LLFolderType::EType getPreferredType() const;
virtual LLUIImagePtr getIcon() const;
virtual LLUIImagePtr getOpenIcon() const;
static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem();
virtual void pasteFromClipboard();
virtual void pasteLinkFromClipboard();
@@ -322,6 +326,7 @@ public:
static void createWearable(LLUUID parent_folder_id, LLWearableType::EType type);
LLViewerInventoryCategory* getCategory() const;
LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
protected:
// menu callbacks
@@ -350,15 +355,17 @@ protected:
void modifyOutfit(BOOL append, BOOL replace = FALSE);
menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items
public:
static LLFolderBridge* sSelf;
static LLHandle<LLFolderBridge> sSelf;
static void staticFolderOptionsMenu();
void folderOptionsMenu();
private:
BOOL mCallingCards;
BOOL mWearables;
LLMenuGL* mMenu;
LLHandle<LLView> mMenu;
menuentry_vec_t mItems;
menuentry_vec_t mDisabledItems;
LLRootHandle<LLFolderBridge> mHandle;
};

View File

@@ -106,7 +106,10 @@ void change_item_parent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp)
{
if (item->getParentUUID() != new_parent_id)
// <edit>
bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID());
// </edit>
if(item->getParentUUID() != new_parent_id)
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
@@ -117,6 +120,9 @@ void change_item_parent(LLInventoryModel* model,
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setParent(new_parent_id);
// <edit>
if(send_parent_update)
// </edit>
new_item->updateParentOnServer(restamp);
model->updateItem(new_item);
model->notifyObservers();
@@ -153,6 +159,59 @@ void change_category_parent(LLInventoryModel* model,
model->notifyObservers();
}
/*void remove_category(LLInventoryModel* model, const LLUUID& cat_id)
{
if (!model || !get_is_category_removable(model, cat_id))
{
return;
}
// Look for any gestures and deactivate them
LLInventoryModel::cat_array_t descendent_categories;
LLInventoryModel::item_array_t descendent_items;
gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
iter != descendent_items.end();
++iter)
{
const LLViewerInventoryItem* item = (*iter);
const LLUUID& item_id = item->getUUID();
if (item->getType() == LLAssetType::AT_GESTURE
&& LLGestureMgr::instance().isGestureActive(item_id))
{
LLGestureMgr::instance().deactivateGesture(item_id);
}
}
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (cat)
{
const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
change_category_parent(model, cat, trash_id, TRUE);
}
}*/
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
{
LLViewerInventoryCategory* cat;
if (!model ||
!get_is_category_renameable(model, cat_id) ||
(cat = model->getCategory(cat_id)) == NULL ||
cat->getName() == new_name)
{
return;
}
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
model->notifyObservers();
}
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
{
public:
@@ -308,6 +367,101 @@ BOOL get_can_item_be_worn(const LLUUID& id)
return FALSE;
}
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
{
if (!model)
{
return FALSE;
}
// Can't delete an item that's in the library.
if(!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
return FALSE;
}
// Disable delete from COF folder; have users explicitly choose "detach/take off",
// unless the item is not worn but in the COF (i.e. is bugged).
if (LLCOFMgr::instance().getIsProtectedCOFItem(id))
{
if (get_is_item_worn(id))
{
return FALSE;
}
}
const LLInventoryObject *obj = model->getItem(id);
if (obj && obj->getIsLinkType())
{
return TRUE;
}
if (get_is_item_worn(id))
{
return FALSE;
}
return TRUE;
}
/*BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
{
// NOTE: This function doesn't check the folder's children.
// See LLFolderBridge::isItemRemovable for a function that does
// consider the children.
if (!model)
{
return FALSE;
}
if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
return FALSE;
}
if (!isAgentAvatarValid()) return FALSE;
const LLInventoryCategory* category = model->getCategory(id);
if (!category)
{
return FALSE;
}
const LLFolderType::EType folder_type = category->getPreferredType();
if (LLFolderType::lookupIsProtectedType(folder_type))
{
return FALSE;
}
// Can't delete the outfit that is currently being worn.
if (folder_type == LLFolderType::FT_OUTFIT)
{
const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
if (base_outfit_link && (category == base_outfit_link->getLinkedCategory()))
{
return FALSE;
}
}
return TRUE;
}*/
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
{
if (!model)
{
return FALSE;
}
LLViewerInventoryCategory* cat = model->getCategory(id);
if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
cat->getOwnerID() == gAgent.getID())
{
return TRUE;
}
return FALSE;
}
///----------------------------------------------------------------------------
@@ -458,6 +612,21 @@ bool LLNameCategoryCollector::operator()(
}
return false;
}
bool LLFindWearables::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((item->getType() == LLAssetType::AT_CLOTHING)
|| (item->getType() == LLAssetType::AT_BODYPART))
{
return TRUE;
}
}
return FALSE;
}
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------
@@ -474,4 +643,112 @@ bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem
return (item &&
(item->getIsLinkType()) &&
(item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
}
}
void LLSaveFolderState::setApply(BOOL apply)
{
mApply = apply;
// before generating new list of open folders, clear the old one
if(!apply)
{
clearOpenFolders();
}
}
void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
{
if(mApply)
{
// we're applying the open state
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
if(!bridge) return;
LLUUID id(bridge->getUUID());
if(mOpenFolders.find(id) != mOpenFolders.end())
{
folder->setOpen(TRUE);
}
else
{
// keep selected filter in its current state, this is less jarring to user
if (!folder->isSelected())
{
folder->setOpen(FALSE);
}
}
}
else
{
// we're recording state at this point
if(folder->isOpen())
{
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
if(!bridge) return;
mOpenFolders.insert(bridge->getUUID());
}
}
}
void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
{
if (item->getFiltered())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
{
if (folder->getFiltered() && folder->getParentFolder())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
// if this folder didn't pass the filter, and none of its descendants did
else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
{
folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
}
}
void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
{
if (item->getFiltered() && !mItemSelected)
{
item->getRoot()->setSelection(item, FALSE, FALSE);
if (item->getParentFolder())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
item->getRoot()->scrollToShowSelection();
mItemSelected = TRUE;
}
}
void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
{
if (folder->getFiltered() && !mItemSelected)
{
folder->getRoot()->setSelection(folder, FALSE, FALSE);
if (folder->getParentFolder())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
folder->getRoot()->scrollToShowSelection();
mItemSelected = TRUE;
}
}
void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
{
if (item->getParentFolder() && item->isSelected())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
{
if (folder->getParentFolder() && folder->isSelected())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}

View File

@@ -47,6 +47,11 @@ BOOL get_is_item_worn(const LLUUID& id);
// Could this item be worn (correct type + not already being worn)
BOOL get_can_item_be_worn(const LLUUID& id);
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id);
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id);
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id);
void change_item_parent(LLInventoryModel* model,
LLViewerInventoryItem* item,
@@ -57,6 +62,10 @@ void change_category_parent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
const LLUUID& new_parent_id,
BOOL restamp);
void remove_category(LLInventoryModel* model, const LLUUID& cat_id);
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
// Generates a string containing the path to the item specified by item_id.
void append_path(const LLUUID& id, std::string& path);
@@ -252,6 +261,42 @@ public:
protected:
std::string mName;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFindWearables
//
// Collects wearables based on item type.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFindWearables : public LLInventoryCollectFunctor
{
public:
LLFindWearables() {}
virtual ~LLFindWearables() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
/** Inventory Collector Functions
** **
*******************************************************************************/
class LLFolderViewItem;
class LLFolderViewFolder;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewFunctor
//
// Simple abstract base class for applying a functor to folders and
// items in a folder view hierarchy. This is suboptimal for algorithms
// that only work folders or only work on items, but I'll worry about
// that later when it's determined to be too slow.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFolderViewFunctor
{
public:
virtual ~LLFolderViewFunctor() {}
virtual void doFolder(LLFolderViewFolder* folder) = 0;
virtual void doItem(LLFolderViewItem* item) = 0;
};
class LLInventoryState
{
public:
@@ -260,6 +305,49 @@ public:
static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction
};
class LLSelectFirstFilteredItem : public LLFolderViewFunctor
{
public:
LLSelectFirstFilteredItem() : mItemSelected(FALSE) {}
virtual ~LLSelectFirstFilteredItem() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
BOOL wasItemSelected() { return mItemSelected; }
protected:
BOOL mItemSelected;
};
class LLOpenFilteredFolders : public LLFolderViewFunctor
{
public:
LLOpenFilteredFolders() {}
virtual ~LLOpenFilteredFolders() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
};
class LLSaveFolderState : public LLFolderViewFunctor
{
public:
LLSaveFolderState() : mApply(FALSE) {}
virtual ~LLSaveFolderState() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item) {}
void setApply(BOOL apply);
void clearOpenFolders() { mOpenFolders.clear(); }
protected:
std::set<LLUUID> mOpenFolders;
BOOL mApply;
};
class LLOpenFoldersWithSelection : public LLFolderViewFunctor
{
public:
LLOpenFoldersWithSelection() {}
virtual ~LLOpenFoldersWithSelection() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
};
#endif // LL_LLINVENTORYFUNCTIONS_H

View File

@@ -50,6 +50,7 @@
#include "llviewerinventory.h"
#include "llviewermessage.h"
#include "llfoldertype.h"
#include "llviewerfoldertype.h"
#include "llviewerwindow.h"
#include "llviewerregion.h"
#include "llappviewer.h"
@@ -77,6 +78,8 @@
#include "process.h"
#endif
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
const S32 MAX_FETCH_RETRIES = 10;
BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
BOOL LLInventoryModel::sFullFetchStarted = FALSE;
@@ -90,6 +93,7 @@ S16 LLInventoryModel::sBulkFetchCount = 0;
// RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue
static std::deque<LLUUID> sFetchQueue;
// Increment this if the inventory contents change in a non-backwards-compatible way.
// For viewers with link items support, former caches are incorrect.
const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
@@ -99,67 +103,8 @@ const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
///----------------------------------------------------------------------------
//BOOL decompress_file(const char* src_filename, const char* dst_filename);
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
const S32 MAX_FETCH_RETRIES = 10;
const char CACHE_FORMAT_STRING[] = "%s.inv";
const char* NEW_CATEGORY_NAME = "New Folder";
const char* NEW_CATEGORY_NAMES[LLFolderType::FT_COUNT] =
{
"Textures", // FT_TEXTURE = 0,
"Sounds", // FT_SOUND = 1,
"Calling Cards", // FT_CALLINGCARD = 2,
"Landmarks", // FT_LANDMARK = 3,
"Scripts", // AT_SCRIPT (deprecated?)
"Clothing", // FT_CLOTHING = 5,
"Objects", // FT_OBJECT = 6,
"Notecards", // FT_NOTECARD = 7,
"New Folder", // FT_ROOT_INVENTORY = 8,
"Inventory", // AT_ROOT_CATEGORY
"Scripts", // FT_LSL_TEXT = 10,
"Scripts", // AT_LSL_BYTECODE
"Uncompressed Images", // AT_TEXTURE_TGA
"Body Parts", // FT_BODYPART = 13,
"Trash", // FT_TRASH = 14,
"Photo Album", // FT_SNAPSHOT_CATEGORY = 15,
"Lost And Found", // FT_LOST_AND_FOUND = 16,
"Uncompressed Sounds", // AT_SOUND_WAV
"Uncompressed Images", // AT_IMAGE_TGA
"Uncompressed Images", // AT_IMAGE_JPEG
"Animations", // FT_ANIMATION = 20,
"Gestures", // FT_GESTURE = 21,
"New Folder", // AT_SIMSTATE
"Favorites", // FT_FAVORITE = 23,
"New Folder",
"New Folder",
"New Ensemble", // FT_ENSEMBLE_START = 26,
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble",
"New Ensemble", // FT_ENSEMBLE_END = 45,
"Current Outfit", // FT_CURRENT_OUTFIT = 46,
"New Outfit", // FT_OUTFIT = 47,
"My Outfits", // FT_MY_OUTFITS = 48,
"Mesh", // FT_MESH = 49,
"Inbox", // FT_INBOX = 50,
"Outbox", // FT_OUTBOX = 51,
"Basic Root" // FT_BASIC_ROOT = 52
};
const char CACHE_FORMAT_STRING[] = "%s.inv";
struct InventoryIDPtrLess
{
@@ -600,10 +545,10 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
{
name.assign(pname);
}
else if(preferred_type < (LLFolderType::EType)0 || preferred_type >= LLFolderType::FT_COUNT)
name.assign(NEW_CATEGORY_NAME);
else
name.assign(NEW_CATEGORY_NAMES[preferred_type]);
{
name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
}
if ( callback && user_data ) //callback required for acked message.
{
@@ -996,10 +941,10 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
}
}
/*else if (new_item->getType() == LLAssetType::AT_GESTURE)
else if (new_item->getType() == LLAssetType::AT_GESTURE)
{
mask |= LLInventoryObserver::GESTURE;
}*/
}
addChangedMask(mask, new_item->getUUID());
return mask;
}

View File

@@ -55,6 +55,7 @@ public:
REMOVE = 8, // something deleted
STRUCTURE = 16, // structural change, eg, item or folder moved
CALLING_CARD = 32, // online, grant status, cancel, etc change
GESTURE = 64,
ALL = 0xffffffff
};
virtual ~LLInventoryObserver() {};

View File

@@ -413,49 +413,6 @@ void LLInventoryViewFinder::selectNoTypes(void* user_data)
///----------------------------------------------------------------------------
/// LLInventoryView
///----------------------------------------------------------------------------
void LLSaveFolderState::setApply(BOOL apply)
{
mApply = apply;
// before generating new list of open folders, clear the old one
if(!apply)
{
clearOpenFolders();
}
}
void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
{
if(mApply)
{
// we're applying the open state
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
if(!bridge) return;
LLUUID id(bridge->getUUID());
if(mOpenFolders.find(id) != mOpenFolders.end())
{
folder->setOpen(TRUE);
}
else
{
// keep selected filter in its current state, this is less jarring to user
if (!folder->isSelected())
{
folder->setOpen(FALSE);
}
}
}
else
{
// we're recording state at this point
if(folder->isOpen())
{
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
if(!bridge) return;
mOpenFolders.insert(bridge->getUUID());
}
}
}
// Default constructor
LLInventoryView::LLInventoryView(const std::string& name,
const std::string& rect,
@@ -667,71 +624,6 @@ void LLInventoryView::draw()
LLFloater::draw();
}
void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
{
if (item->getFiltered())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
{
if (folder->getFiltered() && folder->getParentFolder())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
// if this folder didn't pass the filter, and none of its descendants did
else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
{
folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
}
}
void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
{
if (item->getFiltered() && !mItemSelected)
{
item->getRoot()->setSelection(item, FALSE, FALSE);
if (item->getParentFolder())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
item->getRoot()->scrollToShowSelection();
mItemSelected = TRUE;
}
}
void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
{
if (folder->getFiltered() && !mItemSelected)
{
folder->getRoot()->setSelection(folder, FALSE, FALSE);
if (folder->getParentFolder())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
folder->getRoot()->scrollToShowSelection();
mItemSelected = TRUE;
}
}
void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
{
if (item->getParentFolder() && item->isSelected())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
{
if (folder->getParentFolder() && folder->isSelected())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLInventoryView::startSearch()
{
// this forces focus to line editor portion of search editor

View File

@@ -318,50 +318,6 @@ protected:
static LLDynamicArray<LLInventoryView*> sActiveViews;
};
class LLSelectFirstFilteredItem : public LLFolderViewFunctor
{
public:
LLSelectFirstFilteredItem() : mItemSelected(FALSE) {}
virtual ~LLSelectFirstFilteredItem() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
BOOL wasItemSelected() { return mItemSelected; }
protected:
BOOL mItemSelected;
};
class LLOpenFilteredFolders : public LLFolderViewFunctor
{
public:
LLOpenFilteredFolders() {}
virtual ~LLOpenFilteredFolders() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
};
class LLSaveFolderState : public LLFolderViewFunctor
{
public:
LLSaveFolderState() : mApply(FALSE) {}
virtual ~LLSaveFolderState() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item) {}
void setApply(BOOL apply);
void clearOpenFolders() { mOpenFolders.clear(); }
protected:
std::set<LLUUID> mOpenFolders;
BOOL mApply;
};
class LLOpenFoldersWithSelection : public LLFolderViewFunctor
{
public:
LLOpenFoldersWithSelection() {}
virtual ~LLOpenFoldersWithSelection() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
};
///----------------------------------------------------------------------------
/// Function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------

View File

@@ -36,10 +36,12 @@
#include "llview.h"
#include "llavatarnamecache.h"
#include "llinventory.h"
#include "llviewerinventory.h"
#include "llinventorymodel.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llinventoryicon.h"
#include "llagent.h"
#include "lltooldraganddrop.h"
@@ -49,7 +51,6 @@
#include "llbutton.h"
#include "lliconctrl.h"
#include "llcheckboxctrl.h"
#include "llnotificationsutil.h"
#include "llscrolllistctrl.h"
#include "lltextbox.h"
@@ -57,6 +58,8 @@
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "llviewermessage.h"
#include "llnotificationsutil.h"
#include "llgiveinventory.h"
const S32 NOTICE_DATE_STRING_SIZE = 30;
@@ -140,7 +143,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
&& LLToolDragAndDrop::isInventoryGroupGiveAcceptable(inv_item))
&& LLGiveInventory::isInventoryGroupGiveAcceptable(inv_item))
{
// *TODO: get multiple object transfers working
*accept = ACCEPT_YES_COPY_SINGLE;

View File

@@ -49,6 +49,7 @@
#include "lldarray.h"
#include "llfontgl.h"
#include "llassetstorage.h"
#include "llfoldervieweventlistener.h"
#include "llinventory.h"
#include "llinventorybridge.h"
#include "llinventorydefines.h"

View File

@@ -44,6 +44,7 @@
#include "lldraghandle.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llfoldervieweventlistener.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
#include "llinventoryview.h"

View File

@@ -48,8 +48,10 @@
#include "llfloatertools.h"
#include "llfocusmgr.h"
#include "llgesturemgr.h"
#include "llhudeffecttrail.h"
#include "llgiveinventory.h"
#include "llhudmanager.h"
#include "llhudeffecttrail.h"
#include "llimview.h"
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
@@ -68,18 +70,15 @@
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
#include "llvolume.h"
#include "llworld.h"
#include "object_flags.h"
#include "llimview.h"
// <edit>
#include "llappviewer.h" // System Folders
#include "llparcel.h" // always rez
#include "llviewerparcelmgr.h" // always rez
// </edit>
#include "object_flags.h"
#include "llimview.h"
// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a)
#include "rlvhandler.h"
@@ -145,18 +144,18 @@ bool LLDroppableItem::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
bool allowed = false;
if(item)
if (item)
{
allowed = itemTransferCommonlyAllowed(item);
if(allowed
if (allowed
&& mIsTransfer
&& !item->getPermissions().allowOperationBy(PERM_TRANSFER,
gAgent.getID()))
{
allowed = false;
}
if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
if (allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
{
++mCountLosing;
}
@@ -164,29 +163,6 @@ bool LLDroppableItem::operator()(LLInventoryCategory* cat,
return allowed;
}
class LLUncopyableItems : public LLInventoryCollectFunctor
{
public:
LLUncopyableItems() {}
virtual ~LLUncopyableItems() {}
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
};
bool LLUncopyableItems::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
bool uncopyable = false;
if(item)
{
if (itemTransferCommonlyAllowed(item) &&
!item->getPermissions().allowCopyBy(gAgent.getID()))
{
uncopyable = true;
}
}
return uncopyable;
}
class LLDropCopyableItems : public LLInventoryCollectFunctor
{
public:
@@ -214,43 +190,6 @@ bool LLDropCopyableItems::operator()(
return allowed;
}
class LLGiveable : public LLInventoryCollectFunctor
{
public:
LLGiveable() : mCountLosing(0) {}
virtual ~LLGiveable() {}
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
S32 countNoCopy() const { return mCountLosing; }
protected:
S32 mCountLosing;
};
bool LLGiveable::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
// All categories can be given.
if (cat)
return true;
bool allowed = false;
if(item)
{
allowed = itemTransferCommonlyAllowed(item);
if(allowed &&
!item->getPermissions().allowOperationBy(PERM_TRANSFER,
gAgent.getID()))
{
allowed = FALSE;
}
if(allowed &&
!item->getPermissions().allowCopyBy(gAgent.getID()))
{
++mCountLosing;
}
}
return allowed;
}
class LLCategoryFireAndForget : public LLInventoryFetchComboObserver
{
public:
@@ -558,8 +497,8 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLNoPreferredTypeOrItem is_not_preferred;
LLInventoryFetchComboObserver::folder_ref_t folder_ids;
LLInventoryFetchComboObserver::item_ref_t item_ids;
uuid_vec_t folder_ids;
uuid_vec_t item_ids;
if(is_not_preferred(cat, NULL))
{
folder_ids.push_back(cargo_id);
@@ -649,9 +588,9 @@ void LLToolDragAndDrop::beginMultiDrag(
}
if(!cat_ids.empty())
{
LLInventoryFetchComboObserver::folder_ref_t folder_ids;
LLInventoryFetchComboObserver::item_ref_t item_ids;
std::back_insert_iterator<LLInventoryFetchDescendentsObserver::folder_ref_t> copier(folder_ids);
uuid_vec_t folder_ids;
uuid_vec_t item_ids;
std::back_insert_iterator<uuid_vec_t> copier(folder_ids);
std::copy(cat_ids.begin(), cat_ids.end(), copier);
LLCategoryFireAndForget fetcher;
fetcher.fetch(folder_ids, item_ids);
@@ -1561,447 +1500,6 @@ struct LLGiveInventoryInfo
{}
};
void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent,
LLInventoryItem* item,
const LLUUID& im_session_id)
{
llinfos << "LLToolDragAndDrop::giveInventory()" << llendl;
if(!isInventoryGiveAcceptable(item))
{
return;
}
if(item->getPermissions().allowCopyBy(gAgent.getID()))
{
// just give it away.
LLToolDragAndDrop::commitGiveInventoryItem(to_agent, item, im_session_id);
}
else
{
// ask if the agent is sure.
LLSD payload;
payload["agent_id"] = to_agent;
payload["item_id"] = item->getUUID();
LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload,
&LLToolDragAndDrop::handleCopyProtectedItem);
}
}
// static
bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
LLInventoryItem* item = NULL;
switch(option)
{
case 0: // "Yes"
item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
if(item)
{
LLToolDragAndDrop::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(),
item);
// delete it for now - it will be deleted on the server
// quickly enough.
gInventory.deleteObject(notification["payload"]["item_id"].asUUID());
gInventory.notifyObservers();
}
else
{
LLNotificationsUtil::add("CannotGiveItem");
}
break;
default: // no, cancel, whatever, who cares, not yes.
LLNotificationsUtil::add("TransactionCancelled");
break;
}
return false;
}
// static
void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,
LLInventoryItem* item,
const LLUUID& im_session_id)
{
if(!item) return;
std::string name;
gAgent.buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES;
U8 bucket[BUCKET_SIZE];
bucket[0] = (U8)item->getType();
memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES); /* Flawfinder: ignore */
pack_instant_message(
gMessageSystem,
gAgent.getID(),
FALSE,
gAgent.getSessionID(),
to_agent,
name,
item->getName(),
IM_ONLINE,
IM_INVENTORY_OFFERED,
transaction_id,
0,
LLUUID::null,
gAgent.getPositionAgent(),
NO_TIMESTAMP,
bucket,
BUCKET_SIZE);
gAgent.sendReliableMessage();
// <edit>
if (gSavedSettings.getBOOL("BroadcastViewerEffects"))
{
// </edit>
// VEFFECT: giveInventory
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
effectp->setSourceObject(gAgentAvatarp);
effectp->setTargetObject(gObjectList.findObject(to_agent));
effectp->setDuration(LL_HUD_DUR_SHORT);
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
// <edit>
}
// </edit>
gFloaterTools->dirty();
LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);
// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat.
if (im_session_id != LLUUID::null)
{
LLSD args;
gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
}
}
void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
LLInventoryCategory* cat,
const LLUUID& im_session_id)
{
if(!cat) return;
llinfos << "LLToolDragAndDrop::giveInventoryCategory() - "
<< cat->getUUID() << llendl;
LLVOAvatar* my_avatar = gAgentAvatarp;
if( !my_avatar )
{
return;
}
// Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLGiveable giveable;
gInventory.collectDescendentsIf(cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
giveable);
S32 count = cats.count();
bool complete = true;
for(S32 i = 0; i < count; ++i)
{
if(!gInventory.isCategoryComplete(cats.get(i)->getUUID()))
{
complete = false;
break;
}
}
if(!complete)
{
LLNotificationsUtil::add("IncompleteInventory");
return;
}
count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
return;
}
else if(count == 0)
{
LLNotificationsUtil::add("NoItems");
return;
}
else
{
if(0 == giveable.countNoCopy())
{
LLToolDragAndDrop::commitGiveInventoryCategory(to_agent, cat, im_session_id);
}
else
{
LLGiveInventoryInfo* info = NULL;
info = new LLGiveInventoryInfo(to_agent, cat->getUUID(), im_session_id);
LLSD args;
args["COUNT"] = llformat("%d",giveable.countNoCopy());
LLSD payload;
payload["agent_id"] = to_agent;
payload["folder_id"] = cat->getUUID();
LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory);
}
}
}
// static
bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
LLInventoryCategory* cat = NULL;
switch(option)
{
case 0: // "Yes"
cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID());
if(cat)
{
LLToolDragAndDrop::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
cat);
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLUncopyableItems remove;
gInventory.collectDescendentsIf(cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
remove);
S32 count = items.count();
for(S32 i = 0; i < count; ++i)
{
gInventory.deleteObject(items.get(i)->getUUID());
}
gInventory.notifyObservers();
}
else
{
LLNotificationsUtil::add("CannotGiveCategory");
}
break;
default: // no, cancel, whatever, who cares, not yes.
LLNotificationsUtil::add("TransactionCancelled");
break;
}
return false;
}
// static
void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,
LLInventoryCategory* cat,
const LLUUID& im_session_id)
{
if(!cat) return;
llinfos << "LLToolDragAndDrop::commitGiveInventoryCategory() - "
<< cat->getUUID() << llendl;
// Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
LLGiveable giveable;
gInventory.collectDescendentsIf(cat->getUUID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
giveable);
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
// MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
// 66. I've cut it down a bit from there to give some pad.
S32 count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
return;
}
else if(count == 0)
{
LLNotificationsUtil::add("NoItems");
return;
}
else
{
std::string name;
gAgent.buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
U8* bucket = new U8[bucket_size];
U8* pos = bucket;
U8 type = (U8)cat->getType();
memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
pos += sizeof(U8);
memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
S32 i;
count = cats.count();
for(i = 0; i < count; ++i)
{
memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
pos += sizeof(U8);
memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
}
count = items.count();
for(i = 0; i < count; ++i)
{
type = (U8)items.get(i)->getType();
memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
pos += sizeof(U8);
memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
}
pack_instant_message(
gMessageSystem,
gAgent.getID(),
FALSE,
gAgent.getSessionID(),
to_agent,
name,
cat->getName(),
IM_ONLINE,
IM_INVENTORY_OFFERED,
transaction_id,
0,
LLUUID::null,
gAgent.getPositionAgent(),
NO_TIMESTAMP,
bucket,
bucket_size);
gAgent.sendReliableMessage();
delete[] bucket;
// <edit>
if (gSavedSettings.getBOOL("BroadcastViewerEffects"))
{
// </edit>
// VEFFECT: giveInventoryCategory
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
effectp->setSourceObject(gAgentAvatarp);
effectp->setTargetObject(gObjectList.findObject(to_agent));
effectp->setDuration(LL_HUD_DUR_SHORT);
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
// <edit>
}
// </edit>
gFloaterTools->dirty();
LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);
// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat.
if (im_session_id != LLUUID::null)
{
LLSD args;
gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
}
}
}
// static
BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item)
{
if(!item)
{
return FALSE;
}
if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
{
return FALSE;
}
BOOL copyable = FALSE;
if(item->getPermissions().allowCopyBy(gAgent.getID())) copyable = TRUE;
// <edit>
/*LLVOAvatar* my_avatar = gAgentAvatarp;
if(!my_avatar)
{
return FALSE;
}*/
// </edit>
// <edit>
//BOOL acceptable = FALSE;
BOOL acceptable = TRUE;
// Might also look at what's down below
// </edit>
switch(item->getType())
{
case LLAssetType::AT_CALLINGCARD:
acceptable = FALSE;
break;
case LLAssetType::AT_OBJECT:
// <edit>
/*if(my_avatar->isWearingAttachment(item->getUUID()))
{
acceptable = FALSE;
}*/
// </edit>
break;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
// <edit>
/*if(!copyable && gAgentWearables.isWearingItem(item->getUUID()))
{
acceptable = FALSE;
}*/
// </edit>
break;
default:
break;
}
return acceptable;
}
// Static
BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
{
if(!item)
{
return FALSE;
}
// These permissions are double checked in the simulator in
// LLGroupNoticeInventoryItemFetch::result().
if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
{
return FALSE;
}
if(!item->getPermissions().allowCopyBy(gAgent.getID()))
{
return FALSE;
}
LLVOAvatar* my_avatar = gAgentAvatarp;
if(!my_avatar)
{
return FALSE;
}
BOOL acceptable = TRUE;
// <edit>
/*
// </edit>
switch(item->getType())
{
case LLAssetType::AT_CALLINGCARD:
acceptable = FALSE;
break;
case LLAssetType::AT_OBJECT:
if(my_avatar->isWearingAttachment(item->getUUID()))
{
acceptable = FALSE;
}
break;
default:
break;
}
// <edit>
*/
// </edit>
return acceptable;
}
// accessor that looks at permissions, copyability, and names of
// inventory items to determine if a drop would be ok.
EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
@@ -2117,13 +1615,13 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
&& LLToolDragAndDrop::isInventoryGiveAcceptable(inv_item))
&& LLGiveInventory::isInventoryGiveAcceptable(inv_item))
{
// *TODO: get multiple object transfers working
*accept = ACCEPT_YES_COPY_SINGLE;
if(drop)
{
LLToolDragAndDrop::giveInventory(dest_agent, inv_item, session_id);
LLGiveInventory::doGiveInventoryItem(dest_agent, inv_item, session_id);
}
}
else
@@ -2145,7 +1643,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
*accept = ACCEPT_YES_COPY_SINGLE;
if(drop)
{
LLToolDragAndDrop::giveInventoryCategory(dest_agent, inv_cat, session_id);
LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id);
}
}
else
@@ -2868,7 +2366,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject(
{
if(drop)
{
giveInventory(obj->getID(), item );
LLGiveInventory::doGiveInventoryItem(obj->getID(), item );
}
// *TODO: deal with all the issues surrounding multi-object
// inventory transfers.
@@ -2888,13 +2386,13 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventory(
LLViewerInventoryCategory* cat;
locateInventory(item, cat);
if(!item || !item->isComplete()) return ACCEPT_NO;
if(!isInventoryGiveAcceptable(item))
if(!LLGiveInventory::isInventoryGiveAcceptable(item))
{
return ACCEPT_NO;
}
if(drop && obj)
{
giveInventory(obj->getID(), item);
LLGiveInventory::doGiveInventoryItem(obj->getID(), item);
}
// *TODO: deal with all the issues surrounding multi-object
// inventory transfers.
@@ -2911,7 +2409,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory(
LLViewerInventoryCategory* cat;
locateInventory(item, cat);
if(!cat) return ACCEPT_NO;
giveInventoryCategory(obj->getID(), cat);
LLGiveInventory::doGiveInventoryCategory(obj->getID(), cat);
}
// *TODO: deal with all the issues surrounding multi-object
// inventory transfers.

View File

@@ -208,27 +208,10 @@ protected:
LLToolDragAndDrop::ESource source,
const LLUUID& src_id);
// give inventory item functionality
static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryItem(const LLUUID& to_agent,
LLInventoryItem* item,
const LLUUID &im_session_id = LLUUID::null);
// give inventory category functionality
static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryCategory(const LLUUID& to_agent,
LLInventoryCategory* cat,
const LLUUID &im_session_id = LLUUID::null);
public:
// helper functions
static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); }
// This simple helper function assumes you are attempting to
// transfer item. returns true if you can give, otherwise false.
static BOOL isInventoryGiveAcceptable(LLInventoryItem* item);
static BOOL isInventoryGroupGiveAcceptable(LLInventoryItem* item);
BOOL dadUpdateInventory(LLViewerObject* obj, BOOL drop);
BOOL dadUpdateInventoryCategory(LLViewerObject* obj, BOOL drop);
@@ -255,13 +238,6 @@ public:
ESource source,
const LLUUID& src_id);
static void giveInventory(const LLUUID& to_agent,
LLInventoryItem* item,
const LLUUID &session_id = LLUUID::null);
static void giveInventoryCategory(const LLUUID& to_agent,
LLInventoryCategory* item,
const LLUUID &session_id = LLUUID::null);
static bool handleGiveDragAndDrop(LLUUID agent, LLUUID session, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,

View File

@@ -0,0 +1,303 @@
/**
* @file llfoldertype.cpp
* @brief Implementation of LLViewerFolderType functionality.
*
* $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 "llviewerfoldertype.h"
#include "lldictionary.h"
#include "llmemory.h"
#include "llvisualparam.h"
static const std::string empty_string;
struct ViewerFolderEntry : public LLDictionaryEntry
{
// Constructor for non-ensembles
ViewerFolderEntry(const std::string &new_category_name, // default name when creating a new category of this type
const std::string &icon_name_open, // name of the folder icon
const std::string &icon_name_closed,
BOOL is_quiet, // folder doesn't need a UI update when changed
const std::string &dictionary_name = empty_string // no reverse lookup needed on non-ensembles, so in most cases just leave this blank
)
:
LLDictionaryEntry(dictionary_name),
mNewCategoryName(new_category_name),
mIconNameOpen(icon_name_open),
mIconNameClosed(icon_name_closed),
mIsQuiet(is_quiet)
{
mAllowedNames.clear();
}
// Constructor for ensembles
ViewerFolderEntry(const std::string &xui_name, // name of the xui menu item
const std::string &new_category_name, // default name when creating a new category of this type
const std::string &icon_name, // name of the folder icon
const std::string allowed_names // allowed item typenames for this folder type
)
:
LLDictionaryEntry(xui_name),
/* Just use default icons until we actually support ensembles
mIconNameOpen(icon_name),
mIconNameClosed(icon_name),
*/
mIconNameOpen("Inv_FolderOpen"), mIconNameClosed("Inv_FolderClosed"),
mNewCategoryName(new_category_name),
mIsQuiet(FALSE)
{
const std::string delims (",");
LLStringUtilBase<char>::getTokens(allowed_names, mAllowedNames, delims);
}
bool getIsAllowedName(const std::string &name) const
{
if (mAllowedNames.empty())
return false;
for (name_vec_t::const_iterator iter = mAllowedNames.begin();
iter != mAllowedNames.end();
iter++)
{
if (name == (*iter))
return true;
}
return false;
}
const std::string mIconNameOpen;
const std::string mIconNameClosed;
const std::string mNewCategoryName;
typedef std::vector<std::string> name_vec_t;
name_vec_t mAllowedNames;
BOOL mIsQuiet;
};
class LLViewerFolderDictionary : public LLSingleton<LLViewerFolderDictionary>,
public LLDictionary<LLFolderType::EType, ViewerFolderEntry>
{
public:
LLViewerFolderDictionary();
protected:
bool initEnsemblesFromFile(); // Reads in ensemble information from foldertypes.xml
};
LLViewerFolderDictionary::LLViewerFolderDictionary()
{
// NEW CATEGORY NAME FOLDER OPEN FOLDER CLOSED QUIET?
// |-------------------------|-----------------------|----------------------|-----------|
addEntry(LLFolderType::FT_TEXTURE, new ViewerFolderEntry("Textures", "inv_folder_texture.tga", "inv_folder_texture.tga", FALSE));
addEntry(LLFolderType::FT_SOUND, new ViewerFolderEntry("Sounds", "inv_folder_sound.tga", "inv_folder_sound.tga", FALSE));
addEntry(LLFolderType::FT_CALLINGCARD, new ViewerFolderEntry("Calling Cards", "inv_folder_callingcard.tga", "inv_folder_callingcard.tga", FALSE));
addEntry(LLFolderType::FT_LANDMARK, new ViewerFolderEntry("Landmarks", "inv_folder_landmark.tga", "inv_folder_landmark.tga", FALSE));
addEntry(LLFolderType::FT_CLOTHING, new ViewerFolderEntry("Clothing", "inv_folder_clothing.tga", "inv_folder_clothing.tga", FALSE));
addEntry(LLFolderType::FT_OBJECT, new ViewerFolderEntry("Objects", "inv_folder_object.tga", "inv_folder_object.tga", FALSE));
addEntry(LLFolderType::FT_NOTECARD, new ViewerFolderEntry("Notecards", "inv_folder_notecard.tga", "inv_folder_notecard.tga", FALSE));
addEntry(LLFolderType::FT_ROOT_INVENTORY, new ViewerFolderEntry("My Inventory", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
addEntry(LLFolderType::FT_LSL_TEXT, new ViewerFolderEntry("Scripts", "inv_folder_script.tga", "inv_folder_script.tga", FALSE));
addEntry(LLFolderType::FT_BODYPART, new ViewerFolderEntry("Body Parts", "inv_folder_bodypart.tga", "inv_folder_bodypart.tga", FALSE));
addEntry(LLFolderType::FT_TRASH, new ViewerFolderEntry("Trash", "inv_folder_trash.tga", "inv_folder_trash.tga", TRUE));
addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new ViewerFolderEntry("Photo Album", "inv_folder_snapshot.tga", "inv_folder_snapshot.tga", FALSE));
addEntry(LLFolderType::FT_LOST_AND_FOUND, new ViewerFolderEntry("Lost And Found", "inv_folder_lostandfound.tga", "inv_folder_lostandfound.tga", TRUE));
addEntry(LLFolderType::FT_ANIMATION, new ViewerFolderEntry("Animations", "inv_folder_animation.tga", "inv_folder_animation.tga", FALSE));
addEntry(LLFolderType::FT_GESTURE, new ViewerFolderEntry("Gestures", "inv_folder_gesture.tga", "inv_folder_gesture.tga", FALSE));
addEntry(LLFolderType::FT_FAVORITE, new ViewerFolderEntry("Favorites", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", TRUE));
addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", TRUE));
addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", TRUE));
addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Outbox", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE, "default"));
#if SUPPORT_ENSEMBLES
initEnsemblesFromFile();
#else
for (U32 type = (U32)LLFolderType::FT_ENSEMBLE_START; type <= (U32)LLFolderType::FT_ENSEMBLE_END; ++type)
{
addEntry((LLFolderType::EType)type, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga", "inv_folder_plain_closed.tga", FALSE));
}
#endif
}
bool LLViewerFolderDictionary::initEnsemblesFromFile()
{
std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"foldertypes.xml");
LLXmlTree folder_def;
if (!folder_def.parseFile(xml_filename))
{
llerrs << "Failed to parse folders file " << xml_filename << llendl;
return false;
}
LLXmlTreeNode* rootp = folder_def.getRoot();
for (LLXmlTreeNode* ensemble = rootp->getFirstChild();
ensemble;
ensemble = rootp->getNextChild())
{
if (!ensemble->hasName("ensemble"))
{
llwarns << "Invalid ensemble definition node " << ensemble->getName() << llendl;
continue;
}
S32 ensemble_type;
static LLStdStringHandle ensemble_num_string = LLXmlTree::addAttributeString("foldertype_num");
if (!ensemble->getFastAttributeS32(ensemble_num_string, ensemble_type))
{
llwarns << "No ensemble type defined" << llendl;
continue;
}
if (ensemble_type < S32(LLFolderType::FT_ENSEMBLE_START) || ensemble_type > S32(LLFolderType::FT_ENSEMBLE_END))
{
llwarns << "Exceeded maximum ensemble index" << LLFolderType::FT_ENSEMBLE_END << llendl;
break;
}
std::string xui_name;
static LLStdStringHandle xui_name_string = LLXmlTree::addAttributeString("xui_name");
if (!ensemble->getFastAttributeString(xui_name_string, xui_name))
{
llwarns << "No xui name defined" << llendl;
continue;
}
std::string icon_name;
static LLStdStringHandle icon_name_string = LLXmlTree::addAttributeString("icon_name");
if (!ensemble->getFastAttributeString(icon_name_string, icon_name))
{
llwarns << "No ensemble icon name defined" << llendl;
continue;
}
std::string allowed_names;
static LLStdStringHandle allowed_names_string = LLXmlTree::addAttributeString("allowed");
if (!ensemble->getFastAttributeString(allowed_names_string, allowed_names))
{
}
// Add the entry and increment the asset number.
const static std::string new_ensemble_name = "New Ensemble";
addEntry(LLFolderType::EType(ensemble_type), new ViewerFolderEntry(xui_name, new_ensemble_name, icon_name, allowed_names));
}
return true;
}
const std::string &LLViewerFolderType::lookupXUIName(LLFolderType::EType folder_type)
{
const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
if (entry)
{
return entry->mName;
}
return badLookup();
}
LLFolderType::EType LLViewerFolderType::lookupTypeFromXUIName(const std::string &name)
{
return LLViewerFolderDictionary::getInstance()->lookup(name);
}
const std::string &LLViewerFolderType::lookupIconName(LLFolderType::EType folder_type, BOOL is_open)
{
const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
if (entry)
{
if (is_open)
return entry->mIconNameOpen;
else
return entry->mIconNameClosed;
}
// Error condition. Return something so that we don't show a grey box in inventory view.
const ViewerFolderEntry *default_entry = LLViewerFolderDictionary::getInstance()->lookup(LLFolderType::FT_NONE);
if (default_entry)
{
return default_entry->mIconNameClosed;
}
// Should not get here unless there's something corrupted with the FT_NONE entry.
return badLookup();
}
BOOL LLViewerFolderType::lookupIsQuietType(LLFolderType::EType folder_type)
{
const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
if (entry)
{
return entry->mIsQuiet;
}
return FALSE;
}
const std::string &LLViewerFolderType::lookupNewCategoryName(LLFolderType::EType folder_type)
{
const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
if (entry)
{
return entry->mNewCategoryName;
}
return badLookup();
}
LLFolderType::EType LLViewerFolderType::lookupTypeFromNewCategoryName(const std::string& name)
{
for (LLViewerFolderDictionary::const_iterator iter = LLViewerFolderDictionary::getInstance()->begin();
iter != LLViewerFolderDictionary::getInstance()->end();
iter++)
{
const ViewerFolderEntry *entry = iter->second;
if (entry->mNewCategoryName == name)
{
return iter->first;
}
}
return FT_NONE;
}
U64 LLViewerFolderType::lookupValidFolderTypes(const std::string& item_name)
{
U64 matching_folders = 0;
for (LLViewerFolderDictionary::const_iterator iter = LLViewerFolderDictionary::getInstance()->begin();
iter != LLViewerFolderDictionary::getInstance()->end();
iter++)
{
const ViewerFolderEntry *entry = iter->second;
if (entry->getIsAllowedName(item_name))
{
matching_folders |= 1LL << iter->first;
}
}
return matching_folders;
}

View File

@@ -0,0 +1,53 @@
/**
* @file llviewerfoldertype.h
* @brief Declaration of LLAssetType.
*
* $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$
*/
#ifndef LL_LLVIEWERFOLDERTYPE_H
#define LL_LLVIEWERFOLDERTYPE_H
#include <string>
#include "llfoldertype.h"
// This class is similar to llfoldertype, but contains methods
// only used by the viewer. This also handles ensembles.
class LLViewerFolderType : public LLFolderType
{
public:
static const std::string& lookupXUIName(EType folder_type); // name used by the UI
static LLFolderType::EType lookupTypeFromXUIName(const std::string& name);
static const std::string& lookupIconName(EType folder_type, BOOL is_open = FALSE); // folder icon name
static BOOL lookupIsQuietType(EType folder_type); // folder doesn't require UI update when changes have occured
static const std::string& lookupNewCategoryName(EType folder_type); // default name when creating new category
static LLFolderType::EType lookupTypeFromNewCategoryName(const std::string& name); // default name when creating new category
static U64 lookupValidFolderTypes(const std::string& item_name); // which folders allow an item of this type?
protected:
LLViewerFolderType() {}
~LLViewerFolderType() {}
};
#endif // LL_LLVIEWERFOLDERTYPE_H

View File

@@ -167,6 +167,8 @@
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
#include "llgiveinventory.h"
#include <boost/tokenizer.hpp>
#if LL_WINDOWS // For Windows specific error handler
@@ -1972,7 +1974,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
position,
false);
}
LLToolDragAndDrop::giveInventory(from_id, item);
LLGiveInventory::doGiveInventoryItem(from_id, item);
}
}
}

View File

@@ -18,6 +18,7 @@
#include "llagent.h"
#include "llcallbacklist.h"
#include "llstartup.h"
#include "llviewerfoldertype.h"
#include "llviewerobject.h"
#include "llvoavatar.h"
@@ -29,9 +30,6 @@
#include "boost/algorithm/string.hpp"
// Only defined in llinventorymodel.cpp
extern const char* NEW_CATEGORY_NAME;
// ============================================================================
// Static variable initialization
//
@@ -394,6 +392,7 @@ void RlvRenameOnWearObserver::doneIdle()
continue;
}
static const std::string &new_category_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_NONE);
for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
{
LLViewerInventoryItem* pItem = items.get(idxItem);
@@ -428,7 +427,7 @@ void RlvRenameOnWearObserver::doneIdle()
std::string strFolderName = ".(" + strAttachPt + ")";
// Rename the item's parent folder if it's called "New Folder", isn't directly under #RLV and contains exactly 1 object
if ( (NEW_CATEGORY_NAME == pFolder->getName()) &&
if ( (new_category_name == pFolder->getName()) &&
(pFolder->getParentUUID() != pRlvRoot->getUUID()) &&
(1 == RlvInventory::getDirectDescendentsCount(pFolder, LLAssetType::AT_OBJECT)) )
{