Merge branch 'master' of git://github.com/Shyotl/SingularityViewer
This commit is contained in:
@@ -214,17 +214,16 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_
|
|||||||
bool LLAssetType::lookupCanLink(EType asset_type)
|
bool LLAssetType::lookupCanLink(EType asset_type)
|
||||||
{
|
{
|
||||||
//Check that enabling all these other types as linkable doesn't break things.
|
//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);
|
const AssetEntry *entry = dict->lookup(asset_type);
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
return entry->mCanLink;
|
return entry->mCanLink;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
*/
|
|
||||||
|
|
||||||
return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY ||
|
/*return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY ||
|
||||||
asset_type == AT_BODYPART || asset_type == AT_GESTURE);
|
asset_type == AT_BODYPART || asset_type == AT_GESTURE);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ set(viewer_SOURCE_FILES
|
|||||||
llframestats.cpp
|
llframestats.cpp
|
||||||
llframestatview.cpp
|
llframestatview.cpp
|
||||||
llgesturemgr.cpp
|
llgesturemgr.cpp
|
||||||
|
llgiveinventory.cpp
|
||||||
llgivemoney.cpp
|
llgivemoney.cpp
|
||||||
llglsandbox.cpp
|
llglsandbox.cpp
|
||||||
llgroupmgr.cpp
|
llgroupmgr.cpp
|
||||||
@@ -446,6 +447,7 @@ set(viewer_SOURCE_FILES
|
|||||||
llviewercamera.cpp
|
llviewercamera.cpp
|
||||||
llviewercontrol.cpp
|
llviewercontrol.cpp
|
||||||
llviewerdisplay.cpp
|
llviewerdisplay.cpp
|
||||||
|
llviewerfoldertype.cpp
|
||||||
llviewergenericmessage.cpp
|
llviewergenericmessage.cpp
|
||||||
llviewergesture.cpp
|
llviewergesture.cpp
|
||||||
#llviewerimage.cpp
|
#llviewerimage.cpp
|
||||||
@@ -735,10 +737,12 @@ set(viewer_HEADER_FILES
|
|||||||
llfloaterwindlight.h
|
llfloaterwindlight.h
|
||||||
llfloaterworldmap.h
|
llfloaterworldmap.h
|
||||||
llfolderview.h
|
llfolderview.h
|
||||||
|
llfoldervieweventlistener.h
|
||||||
llfollowcam.h
|
llfollowcam.h
|
||||||
llframestats.h
|
llframestats.h
|
||||||
llframestatview.h
|
llframestatview.h
|
||||||
llgesturemgr.h
|
llgesturemgr.h
|
||||||
|
llgiveinventory.h
|
||||||
llgivemoney.h
|
llgivemoney.h
|
||||||
llgroupmgr.h
|
llgroupmgr.h
|
||||||
llgroupnotify.h
|
llgroupnotify.h
|
||||||
@@ -923,6 +927,7 @@ set(viewer_HEADER_FILES
|
|||||||
llviewercamera.h
|
llviewercamera.h
|
||||||
llviewercontrol.h
|
llviewercontrol.h
|
||||||
llviewerdisplay.h
|
llviewerdisplay.h
|
||||||
|
llviewerfoldertype.h
|
||||||
llviewergenericmessage.h
|
llviewergenericmessage.h
|
||||||
llviewergesture.h
|
llviewergesture.h
|
||||||
#llviewerimage.h
|
#llviewerimage.h
|
||||||
|
|||||||
@@ -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);
|
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;
|
LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items;
|
||||||
LLLinkedItemIDMatches f(gInventory.getLinkedItemID(idItem));
|
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
|
// Attachment functions
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ public:
|
|||||||
static const LLUUID getCOF() { return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); }
|
static const LLUUID getCOF() { return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); }
|
||||||
static void getDescendentsOfAssetType(const LLUUID& idCat, LLInventoryModel::item_array_t& items,
|
static void getDescendentsOfAssetType(const LLUUID& idCat, LLInventoryModel::item_array_t& items,
|
||||||
LLAssetType::EType typeAsset, bool fFollowFolderLinks);
|
LLAssetType::EType typeAsset, bool fFollowFolderLinks);
|
||||||
bool isLinkInCOF(const LLUUID& idItem);
|
bool isLinkInCOF(const LLUUID& idItem) const;
|
||||||
|
BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const;
|
||||||
protected:
|
protected:
|
||||||
void addCOFItemLink(const LLUUID& idItem, LLPointer<LLInventoryCallback> cb = NULL);
|
void addCOFItemLink(const LLUUID& idItem, LLPointer<LLInventoryCallback> cb = NULL);
|
||||||
void addCOFItemLink(const LLInventoryItem* pItem, LLPointer<LLInventoryCallback> cb = NULL);
|
void addCOFItemLink(const LLInventoryItem* pItem, LLPointer<LLInventoryCallback> cb = NULL);
|
||||||
|
|||||||
@@ -38,8 +38,10 @@
|
|||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llbutton.h"
|
#include "llbutton.h"
|
||||||
#include "llfocusmgr.h"
|
#include "llfocusmgr.h"
|
||||||
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llinventoryview.h"
|
#include "llinventoryview.h"
|
||||||
#include "llinventorymodel.h"
|
#include "llinventorymodel.h"
|
||||||
|
#include "llinventoryfunctions.h"
|
||||||
#include "lllineeditor.h"
|
#include "lllineeditor.h"
|
||||||
#include "llscrolllistctrl.h"
|
#include "llscrolllistctrl.h"
|
||||||
#include "lltextbox.h"
|
#include "lltextbox.h"
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "llcheckboxctrl.h"
|
#include "llcheckboxctrl.h"
|
||||||
#include "llviewerparcelmgr.h"
|
#include "llviewerparcelmgr.h"
|
||||||
#include "llfolderview.h"
|
#include "llfolderview.h"
|
||||||
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llinventory.h"
|
#include "llinventory.h"
|
||||||
#include "llinventoryfunctions.h"
|
#include "llinventoryfunctions.h"
|
||||||
#include "llinventoryview.h"
|
#include "llinventoryview.h"
|
||||||
|
|||||||
@@ -45,8 +45,10 @@
|
|||||||
#include "llinventory.h"
|
#include "llinventory.h"
|
||||||
|
|
||||||
#include "llcallbacklist.h"
|
#include "llcallbacklist.h"
|
||||||
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
|
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
|
||||||
#include "llinventoryview.h"// hacked in for the bonus context menu items.
|
#include "llinventoryview.h"// hacked in for the bonus context menu items.
|
||||||
|
#include "llinventoryfunctions.h"
|
||||||
#include "llkeyboard.h"
|
#include "llkeyboard.h"
|
||||||
#include "lllineeditor.h"
|
#include "lllineeditor.h"
|
||||||
#include "llmenugl.h"
|
#include "llmenugl.h"
|
||||||
|
|||||||
@@ -70,65 +70,9 @@ class LLMenuGL;
|
|||||||
class LLFolderViewItem;
|
class LLFolderViewItem;
|
||||||
class LLFolderView;
|
class LLFolderView;
|
||||||
class LLInventoryModel;
|
class LLInventoryModel;
|
||||||
|
class LLFolderViewFunctor;
|
||||||
class LLScrollableContainerView;
|
class LLScrollableContainerView;
|
||||||
|
class LLFolderViewEventListener;
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -157,13 +101,6 @@ public:
|
|||||||
class LLFolderViewItem;
|
class LLFolderViewItem;
|
||||||
class LLFolderViewFolder;
|
class LLFolderViewFolder;
|
||||||
|
|
||||||
class LLFolderViewFunctor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~LLFolderViewFunctor() {}
|
|
||||||
virtual void doFolder(LLFolderViewFolder* folder) = 0;
|
|
||||||
virtual void doItem(LLFolderViewItem* item) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LLInventoryFilter
|
class LLInventoryFilter
|
||||||
{
|
{
|
||||||
|
|||||||
108
indra/newview/llfoldervieweventlistener.h
Normal file
108
indra/newview/llfoldervieweventlistener.h
Normal 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
|
||||||
541
indra/newview/llgiveinventory.cpp
Normal file
541
indra/newview/llgiveinventory.cpp
Normal 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
|
||||||
93
indra/newview/llgiveinventory.h
Normal file
93
indra/newview/llgiveinventory.h
Normal 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
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llcallingcard.h"
|
#include "llcallingcard.h"
|
||||||
#include "llcheckboxctrl.h" // for radio buttons
|
#include "llcheckboxctrl.h" // for radio buttons
|
||||||
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llnotificationsutil.h"
|
#include "llnotificationsutil.h"
|
||||||
#include "llradiogroup.h"
|
#include "llradiogroup.h"
|
||||||
#include "llspinctrl.h"
|
#include "llspinctrl.h"
|
||||||
@@ -410,7 +411,7 @@ class LLDoCreate : public inventory_panel_listener_t
|
|||||||
LLInventoryModel* model = mPtr->getModel();
|
LLInventoryModel* model = mPtr->getModel();
|
||||||
if(!model) return false;
|
if(!model) return false;
|
||||||
std::string type = userdata.asString();
|
std::string type = userdata.asString();
|
||||||
do_create(model, mPtr, type, LLFolderBridge::sSelf);
|
do_create(model, mPtr, type, LLFolderBridge::sSelf.get());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
#include "llspinctrl.h"
|
#include "llspinctrl.h"
|
||||||
#include "lltextbox.h"
|
#include "lltextbox.h"
|
||||||
#include "llui.h"
|
#include "llui.h"
|
||||||
|
#include "llviewerfoldertype.h"
|
||||||
|
|
||||||
#include "llviewercontrol.h"
|
#include "llviewercontrol.h"
|
||||||
#include "llfirstuse.h"
|
#include "llfirstuse.h"
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
#include "llfocusmgr.h"
|
#include "llfocusmgr.h"
|
||||||
#include "llfolderview.h"
|
#include "llfolderview.h"
|
||||||
#include "llgesturemgr.h"
|
#include "llgesturemgr.h"
|
||||||
|
#include "llgiveinventory.h"
|
||||||
#include "lliconctrl.h"
|
#include "lliconctrl.h"
|
||||||
#include "llinventorymodel.h"
|
#include "llinventorymodel.h"
|
||||||
#include "llinventoryclipboard.h"
|
#include "llinventoryclipboard.h"
|
||||||
@@ -251,21 +253,7 @@ time_t LLInvFVBridge::getCreationDate() const
|
|||||||
// Can be destroyed (or moved to trash)
|
// Can be destroyed (or moved to trash)
|
||||||
BOOL LLInvFVBridge::isItemRemovable()
|
BOOL LLInvFVBridge::isItemRemovable()
|
||||||
{
|
{
|
||||||
LLInventoryModel* model = getInventoryModel();
|
return get_is_item_removable(getInventoryModel(), mUUID);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be moved to another folder
|
// Can be moved to another folder
|
||||||
@@ -645,6 +633,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (LLAssetType::lookupCanLink(obj->getType()))
|
||||||
|
{
|
||||||
|
items.push_back(std::string("Find Links"));
|
||||||
|
}
|
||||||
items.push_back(std::string("Rename"));
|
items.push_back(std::string("Rename"));
|
||||||
if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
|
if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
|
||||||
{
|
{
|
||||||
@@ -654,13 +646,21 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||||||
if (show_asset_id)
|
if (show_asset_id)
|
||||||
{
|
{
|
||||||
items.push_back(std::string("Copy Asset UUID"));
|
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"));
|
disabled_items.push_back(std::string("Copy Asset UUID"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items.push_back(std::string("Copy Separator"));
|
items.push_back(std::string("Copy Separator"));
|
||||||
|
|
||||||
items.push_back(std::string("Copy"));
|
items.push_back(std::string("Copy"));
|
||||||
@@ -898,27 +898,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
|
|||||||
const LLUUID& new_parent_id,
|
const LLUUID& new_parent_id,
|
||||||
BOOL restamp)
|
BOOL restamp)
|
||||||
{
|
{
|
||||||
// <edit>
|
change_item_parent(model, item, new_parent_id, restamp);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@@ -927,21 +907,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
|
|||||||
const LLUUID& new_parent_id,
|
const LLUUID& new_parent_id,
|
||||||
BOOL restamp)
|
BOOL restamp)
|
||||||
{
|
{
|
||||||
if(cat->getParentUUID() != new_parent_id)
|
change_category_parent(model, cat, new_parent_id, restamp);
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
|
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
|
||||||
@@ -1540,11 +1506,7 @@ BOOL LLItemBridge::isItemPermissive() const
|
|||||||
LLViewerInventoryItem* item = getItem();
|
LLViewerInventoryItem* item = getItem();
|
||||||
if(item)
|
if(item)
|
||||||
{
|
{
|
||||||
U32 mask = item->getPermissions().getMaskBase();
|
return item->getIsFullPerm();
|
||||||
if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -1553,7 +1515,7 @@ BOOL LLItemBridge::isItemPermissive() const
|
|||||||
// | LLFolderBridge |
|
// | LLFolderBridge |
|
||||||
// +=================================================+
|
// +=================================================+
|
||||||
|
|
||||||
LLFolderBridge* LLFolderBridge::sSelf=NULL;
|
LLHandle<LLFolderBridge> LLFolderBridge::sSelf;
|
||||||
|
|
||||||
// Can be moved to another folder
|
// Can be moved to another folder
|
||||||
BOOL LLFolderBridge::isItemMovable()
|
BOOL LLFolderBridge::isItemMovable()
|
||||||
@@ -1922,29 +1884,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
|
|||||||
return accept;
|
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.
|
//Used by LLFolderBridge as callback for directory recursion.
|
||||||
class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
|
class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
|
||||||
{
|
{
|
||||||
@@ -2210,13 +2149,7 @@ void LLFolderBridge::openItem()
|
|||||||
|
|
||||||
BOOL LLFolderBridge::isItemRenameable() const
|
BOOL LLFolderBridge::isItemRenameable() const
|
||||||
{
|
{
|
||||||
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
|
return get_is_category_renameable(getInventoryModel(), mUUID);
|
||||||
if(cat && ((cat->getPreferredType() == LLFolderType::FT_NONE) || (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
|
|
||||||
&& (cat->getOwnerID() == gAgent.getID()))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLFolderBridge::restoreItem()
|
void LLFolderBridge::restoreItem()
|
||||||
@@ -2247,82 +2180,34 @@ LLFolderType::EType LLFolderBridge::getPreferredType() const
|
|||||||
// Icons for folders are based on the preferred type
|
// Icons for folders are based on the preferred type
|
||||||
LLUIImagePtr LLFolderBridge::getIcon() const
|
LLUIImagePtr LLFolderBridge::getIcon() const
|
||||||
{
|
{
|
||||||
const char* control = NULL;
|
|
||||||
LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
|
LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
|
||||||
LLViewerInventoryCategory* cat = getCategory();
|
LLViewerInventoryCategory* cat = getCategory();
|
||||||
if(cat)
|
if(cat)
|
||||||
{
|
{
|
||||||
preferred_type = cat->getPreferredType();
|
preferred_type = cat->getPreferredType();
|
||||||
}
|
}
|
||||||
switch(preferred_type)
|
return getIcon(preferred_type);
|
||||||
{
|
}
|
||||||
case LLFolderType::FT_TEXTURE:
|
|
||||||
control = "inv_folder_texture.tga";
|
// static
|
||||||
break;
|
LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
|
||||||
case LLFolderType::FT_SOUND:
|
{
|
||||||
control = "inv_folder_sound.tga";
|
return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE));
|
||||||
break;
|
/*case LLAssetType::AT_MESH:
|
||||||
case LLFolderType::FT_CALLINGCARD:
|
control = "inv_folder_mesh.tga";
|
||||||
control = "inv_folder_callingcard.tga";
|
break;*/
|
||||||
break;
|
}
|
||||||
case LLFolderType::FT_LANDMARK:
|
|
||||||
control = "inv_folder_landmark.tga";
|
LLUIImagePtr LLFolderBridge::getOpenIcon() const
|
||||||
break;
|
{
|
||||||
//case LLFolderType::FT_SCRIPT:
|
return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL LLFolderBridge::renameItem(const std::string& new_name)
|
BOOL LLFolderBridge::renameItem(const std::string& new_name)
|
||||||
{
|
{
|
||||||
if(!isItemRenameable()) return FALSE;
|
rename_category(getInventoryModel(), mUUID, new_name);
|
||||||
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();
|
|
||||||
}
|
|
||||||
// return FALSE because we either notified observers (& therefore
|
// return FALSE because we either notified observers (& therefore
|
||||||
// rebuilt) or we didn't update.
|
// rebuilt) or we didn't update.
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -2475,14 +2360,15 @@ void LLFolderBridge::pasteLinkFromClipboard()
|
|||||||
|
|
||||||
void LLFolderBridge::staticFolderOptionsMenu()
|
void LLFolderBridge::staticFolderOptionsMenu()
|
||||||
{
|
{
|
||||||
if (!sSelf) return;
|
LLFolderBridge* selfp = sSelf.get();
|
||||||
sSelf->folderOptionsMenu();
|
if (selfp)
|
||||||
|
{
|
||||||
|
selfp->folderOptionsMenu();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLFolderBridge::folderOptionsMenu()
|
void LLFolderBridge::folderOptionsMenu()
|
||||||
{
|
{
|
||||||
menuentry_vec_t disabled_items;
|
|
||||||
|
|
||||||
// *TODO: Translate
|
// *TODO: Translate
|
||||||
|
|
||||||
LLInventoryModel* model = getInventoryModel();
|
LLInventoryModel* model = getInventoryModel();
|
||||||
@@ -2512,6 +2398,11 @@ void LLFolderBridge::folderOptionsMenu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isItemRemovable())
|
||||||
|
{
|
||||||
|
mDisabledItems.push_back(std::string("Delete"));
|
||||||
|
}
|
||||||
|
|
||||||
// wearables related functionality for folders.
|
// wearables related functionality for folders.
|
||||||
//is_wearable
|
//is_wearable
|
||||||
LLFindWearables is_wearable;
|
LLFindWearables is_wearable;
|
||||||
@@ -2539,7 +2430,11 @@ void LLFolderBridge::folderOptionsMenu()
|
|||||||
}
|
}
|
||||||
mItems.push_back(std::string("Take Off Items"));
|
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)
|
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
|
||||||
@@ -2576,11 +2471,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||||||
// [/RLVa:KB]
|
// [/RLVa:KB]
|
||||||
|
|
||||||
if (lost_and_found_id == mUUID)
|
if (lost_and_found_id == mUUID)
|
||||||
{
|
{
|
||||||
// This is the lost+found folder.
|
// This is the lost+found folder.
|
||||||
mItems.push_back(std::string("Empty Lost And Found"));
|
mItems.push_back(std::string("Empty Lost And Found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear out old menu and folder pointers
|
||||||
|
mMenu.markDead();
|
||||||
|
sSelf.markDead();
|
||||||
if (cof_id == mUUID)
|
if (cof_id == mUUID)
|
||||||
{
|
{
|
||||||
mItems.push_back(std::string("Take Off Items"));
|
mItems.push_back(std::string("Take Off Items"));
|
||||||
@@ -2649,16 +2547,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||||||
mWearables=TRUE;
|
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);
|
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
|
||||||
if (category)
|
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);
|
fetch->fetchDescendents(folders);
|
||||||
inc_busy_count();
|
inc_busy_count();
|
||||||
if(fetch->isEverythingComplete())
|
if(fetch->isEverythingComplete())
|
||||||
@@ -3570,7 +3469,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
|
|||||||
rv = TRUE;
|
rv = TRUE;
|
||||||
if(drop)
|
if(drop)
|
||||||
{
|
{
|
||||||
LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
|
LLGiveInventory::doGiveInventoryItem(item->getCreatorUUID(),
|
||||||
(LLInventoryItem*)cargo_data);
|
(LLInventoryItem*)cargo_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3591,7 +3490,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
|
|||||||
rv = TRUE;
|
rv = TRUE;
|
||||||
if(drop)
|
if(drop)
|
||||||
{
|
{
|
||||||
LLToolDragAndDrop::giveInventoryCategory(
|
LLGiveInventory::doGiveInventoryCategory(
|
||||||
item->getCreatorUUID(),
|
item->getCreatorUUID(),
|
||||||
inv_cat);
|
inv_cat);
|
||||||
}
|
}
|
||||||
@@ -4342,11 +4241,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
|
|||||||
model->updateItem(new_item);
|
model->updateItem(new_item);
|
||||||
model->notifyObservers();
|
model->notifyObservers();
|
||||||
|
|
||||||
LLVOAvatar* avatar = gAgentAvatarp;
|
if (isAgentAvatarValid())
|
||||||
if( avatar )
|
|
||||||
{
|
{
|
||||||
LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
|
LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() );
|
||||||
if( obj )
|
if(obj)
|
||||||
{
|
{
|
||||||
LLSelectMgr::getInstance()->deselectAll();
|
LLSelectMgr::getInstance()->deselectAll();
|
||||||
LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
|
LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#include "llcallingcard.h"
|
#include "llcallingcard.h"
|
||||||
#include "llfloaterproperties.h"
|
#include "llfloaterproperties.h"
|
||||||
#include "llfolderview.h"
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llinventorymodel.h"
|
#include "llinventorymodel.h"
|
||||||
#include "llinventoryobserver.h"
|
#include "llinventoryobserver.h"
|
||||||
//#include "llinventoryview.h"
|
//#include "llinventoryview.h"
|
||||||
@@ -302,7 +302,11 @@ public:
|
|||||||
|
|
||||||
virtual LLFolderType::EType getPreferredType() const;
|
virtual LLFolderType::EType getPreferredType() const;
|
||||||
virtual LLUIImagePtr getIcon() 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 renameItem(const std::string& new_name);
|
||||||
|
|
||||||
virtual BOOL removeItem();
|
virtual BOOL removeItem();
|
||||||
virtual void pasteFromClipboard();
|
virtual void pasteFromClipboard();
|
||||||
virtual void pasteLinkFromClipboard();
|
virtual void pasteLinkFromClipboard();
|
||||||
@@ -322,6 +326,7 @@ public:
|
|||||||
static void createWearable(LLUUID parent_folder_id, LLWearableType::EType type);
|
static void createWearable(LLUUID parent_folder_id, LLWearableType::EType type);
|
||||||
|
|
||||||
LLViewerInventoryCategory* getCategory() const;
|
LLViewerInventoryCategory* getCategory() const;
|
||||||
|
LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// menu callbacks
|
// menu callbacks
|
||||||
@@ -350,15 +355,17 @@ protected:
|
|||||||
void modifyOutfit(BOOL append, BOOL replace = FALSE);
|
void modifyOutfit(BOOL append, BOOL replace = FALSE);
|
||||||
menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items
|
menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items
|
||||||
public:
|
public:
|
||||||
static LLFolderBridge* sSelf;
|
static LLHandle<LLFolderBridge> sSelf;
|
||||||
static void staticFolderOptionsMenu();
|
static void staticFolderOptionsMenu();
|
||||||
void folderOptionsMenu();
|
void folderOptionsMenu();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOOL mCallingCards;
|
BOOL mCallingCards;
|
||||||
BOOL mWearables;
|
BOOL mWearables;
|
||||||
LLMenuGL* mMenu;
|
LLHandle<LLView> mMenu;
|
||||||
menuentry_vec_t mItems;
|
menuentry_vec_t mItems;
|
||||||
menuentry_vec_t mDisabledItems;
|
menuentry_vec_t mDisabledItems;
|
||||||
|
LLRootHandle<LLFolderBridge> mHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,10 @@ void change_item_parent(LLInventoryModel* model,
|
|||||||
const LLUUID& new_parent_id,
|
const LLUUID& new_parent_id,
|
||||||
BOOL restamp)
|
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::update_list_t update;
|
||||||
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
|
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
|
||||||
@@ -117,6 +120,9 @@ void change_item_parent(LLInventoryModel* model,
|
|||||||
|
|
||||||
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
|
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
|
||||||
new_item->setParent(new_parent_id);
|
new_item->setParent(new_parent_id);
|
||||||
|
// <edit>
|
||||||
|
if(send_parent_update)
|
||||||
|
// </edit>
|
||||||
new_item->updateParentOnServer(restamp);
|
new_item->updateParentOnServer(restamp);
|
||||||
model->updateItem(new_item);
|
model->updateItem(new_item);
|
||||||
model->notifyObservers();
|
model->notifyObservers();
|
||||||
@@ -153,6 +159,59 @@ void change_category_parent(LLInventoryModel* model,
|
|||||||
model->notifyObservers();
|
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
|
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -308,6 +367,101 @@ BOOL get_can_item_be_worn(const LLUUID& id)
|
|||||||
return FALSE;
|
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;
|
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
|
/// LLAssetIDMatches
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
@@ -475,3 +644,111 @@ bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem
|
|||||||
(item->getIsLinkType()) &&
|
(item->getIsLinkType()) &&
|
||||||
(item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
|
(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ BOOL get_is_item_worn(const LLUUID& id);
|
|||||||
// Could this item be worn (correct type + not already being worn)
|
// Could this item be worn (correct type + not already being worn)
|
||||||
BOOL get_can_item_be_worn(const LLUUID& id);
|
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,
|
void change_item_parent(LLInventoryModel* model,
|
||||||
LLViewerInventoryItem* item,
|
LLViewerInventoryItem* item,
|
||||||
@@ -57,6 +62,10 @@ void change_category_parent(LLInventoryModel* model,
|
|||||||
LLViewerInventoryCategory* cat,
|
LLViewerInventoryCategory* cat,
|
||||||
const LLUUID& new_parent_id,
|
const LLUUID& new_parent_id,
|
||||||
BOOL restamp);
|
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.
|
// Generates a string containing the path to the item specified by item_id.
|
||||||
void append_path(const LLUUID& id, std::string& path);
|
void append_path(const LLUUID& id, std::string& path);
|
||||||
|
|
||||||
@@ -252,6 +261,42 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
std::string mName;
|
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
|
class LLInventoryState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -260,6 +305,49 @@ public:
|
|||||||
static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction
|
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
|
#endif // LL_LLINVENTORYFUNCTIONS_H
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#include "llviewerinventory.h"
|
#include "llviewerinventory.h"
|
||||||
#include "llviewermessage.h"
|
#include "llviewermessage.h"
|
||||||
#include "llfoldertype.h"
|
#include "llfoldertype.h"
|
||||||
|
#include "llviewerfoldertype.h"
|
||||||
#include "llviewerwindow.h"
|
#include "llviewerwindow.h"
|
||||||
#include "llviewerregion.h"
|
#include "llviewerregion.h"
|
||||||
#include "llappviewer.h"
|
#include "llappviewer.h"
|
||||||
@@ -77,6 +78,8 @@
|
|||||||
#include "process.h"
|
#include "process.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
|
||||||
|
const S32 MAX_FETCH_RETRIES = 10;
|
||||||
BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
|
BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
|
||||||
BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
|
BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
|
||||||
BOOL LLInventoryModel::sFullFetchStarted = 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
|
// 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;
|
static std::deque<LLUUID> sFetchQueue;
|
||||||
|
|
||||||
|
|
||||||
// Increment this if the inventory contents change in a non-backwards-compatible way.
|
// Increment this if the inventory contents change in a non-backwards-compatible way.
|
||||||
// For viewers with link items support, former caches are incorrect.
|
// For viewers with link items support, former caches are incorrect.
|
||||||
const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
|
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);
|
//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] =
|
const char CACHE_FORMAT_STRING[] = "%s.inv";
|
||||||
{
|
|
||||||
"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
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InventoryIDPtrLess
|
struct InventoryIDPtrLess
|
||||||
{
|
{
|
||||||
@@ -600,10 +545,10 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
|||||||
{
|
{
|
||||||
name.assign(pname);
|
name.assign(pname);
|
||||||
}
|
}
|
||||||
else if(preferred_type < (LLFolderType::EType)0 || preferred_type >= LLFolderType::FT_COUNT)
|
|
||||||
name.assign(NEW_CATEGORY_NAME);
|
|
||||||
else
|
else
|
||||||
name.assign(NEW_CATEGORY_NAMES[preferred_type]);
|
{
|
||||||
|
name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
|
||||||
|
}
|
||||||
|
|
||||||
if ( callback && user_data ) //callback required for acked message.
|
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;
|
mask |= LLInventoryObserver::GESTURE;
|
||||||
}*/
|
}
|
||||||
addChangedMask(mask, new_item->getUUID());
|
addChangedMask(mask, new_item->getUUID());
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
REMOVE = 8, // something deleted
|
REMOVE = 8, // something deleted
|
||||||
STRUCTURE = 16, // structural change, eg, item or folder moved
|
STRUCTURE = 16, // structural change, eg, item or folder moved
|
||||||
CALLING_CARD = 32, // online, grant status, cancel, etc change
|
CALLING_CARD = 32, // online, grant status, cancel, etc change
|
||||||
|
GESTURE = 64,
|
||||||
ALL = 0xffffffff
|
ALL = 0xffffffff
|
||||||
};
|
};
|
||||||
virtual ~LLInventoryObserver() {};
|
virtual ~LLInventoryObserver() {};
|
||||||
|
|||||||
@@ -413,49 +413,6 @@ void LLInventoryViewFinder::selectNoTypes(void* user_data)
|
|||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
/// LLInventoryView
|
/// 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
|
// Default constructor
|
||||||
LLInventoryView::LLInventoryView(const std::string& name,
|
LLInventoryView::LLInventoryView(const std::string& name,
|
||||||
const std::string& rect,
|
const std::string& rect,
|
||||||
@@ -667,71 +624,6 @@ void LLInventoryView::draw()
|
|||||||
LLFloater::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()
|
void LLInventoryView::startSearch()
|
||||||
{
|
{
|
||||||
// this forces focus to line editor portion of search editor
|
// this forces focus to line editor portion of search editor
|
||||||
|
|||||||
@@ -318,50 +318,6 @@ protected:
|
|||||||
static LLDynamicArray<LLInventoryView*> sActiveViews;
|
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
|
/// Function declarations, constants, enums, and typedefs
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -36,10 +36,12 @@
|
|||||||
|
|
||||||
#include "llview.h"
|
#include "llview.h"
|
||||||
|
|
||||||
|
#include "llavatarnamecache.h"
|
||||||
#include "llinventory.h"
|
#include "llinventory.h"
|
||||||
#include "llviewerinventory.h"
|
#include "llviewerinventory.h"
|
||||||
#include "llinventorymodel.h"
|
|
||||||
#include "llinventorydefines.h"
|
#include "llinventorydefines.h"
|
||||||
|
#include "llinventoryfunctions.h"
|
||||||
|
#include "llinventorymodel.h"
|
||||||
#include "llinventoryicon.h"
|
#include "llinventoryicon.h"
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "lltooldraganddrop.h"
|
#include "lltooldraganddrop.h"
|
||||||
@@ -49,7 +51,6 @@
|
|||||||
#include "llbutton.h"
|
#include "llbutton.h"
|
||||||
#include "lliconctrl.h"
|
#include "lliconctrl.h"
|
||||||
#include "llcheckboxctrl.h"
|
#include "llcheckboxctrl.h"
|
||||||
#include "llnotificationsutil.h"
|
|
||||||
#include "llscrolllistctrl.h"
|
#include "llscrolllistctrl.h"
|
||||||
#include "lltextbox.h"
|
#include "lltextbox.h"
|
||||||
|
|
||||||
@@ -57,6 +58,8 @@
|
|||||||
#include "llviewerwindow.h"
|
#include "llviewerwindow.h"
|
||||||
#include "llviewercontrol.h"
|
#include "llviewercontrol.h"
|
||||||
#include "llviewermessage.h"
|
#include "llviewermessage.h"
|
||||||
|
#include "llnotificationsutil.h"
|
||||||
|
#include "llgiveinventory.h"
|
||||||
|
|
||||||
const S32 NOTICE_DATE_STRING_SIZE = 30;
|
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;
|
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
|
||||||
if(gInventory.getItem(inv_item->getUUID())
|
if(gInventory.getItem(inv_item->getUUID())
|
||||||
&& LLToolDragAndDrop::isInventoryGroupGiveAcceptable(inv_item))
|
&& LLGiveInventory::isInventoryGroupGiveAcceptable(inv_item))
|
||||||
{
|
{
|
||||||
// *TODO: get multiple object transfers working
|
// *TODO: get multiple object transfers working
|
||||||
*accept = ACCEPT_YES_COPY_SINGLE;
|
*accept = ACCEPT_YES_COPY_SINGLE;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "lldarray.h"
|
#include "lldarray.h"
|
||||||
#include "llfontgl.h"
|
#include "llfontgl.h"
|
||||||
#include "llassetstorage.h"
|
#include "llassetstorage.h"
|
||||||
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llinventory.h"
|
#include "llinventory.h"
|
||||||
#include "llinventorybridge.h"
|
#include "llinventorybridge.h"
|
||||||
#include "llinventorydefines.h"
|
#include "llinventorydefines.h"
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "lldraghandle.h"
|
#include "lldraghandle.h"
|
||||||
#include "llfocusmgr.h"
|
#include "llfocusmgr.h"
|
||||||
#include "llfolderview.h"
|
#include "llfolderview.h"
|
||||||
|
#include "llfoldervieweventlistener.h"
|
||||||
#include "llinventory.h"
|
#include "llinventory.h"
|
||||||
#include "llinventoryfunctions.h"
|
#include "llinventoryfunctions.h"
|
||||||
#include "llinventoryview.h"
|
#include "llinventoryview.h"
|
||||||
|
|||||||
@@ -48,8 +48,10 @@
|
|||||||
#include "llfloatertools.h"
|
#include "llfloatertools.h"
|
||||||
#include "llfocusmgr.h"
|
#include "llfocusmgr.h"
|
||||||
#include "llgesturemgr.h"
|
#include "llgesturemgr.h"
|
||||||
#include "llhudeffecttrail.h"
|
#include "llgiveinventory.h"
|
||||||
#include "llhudmanager.h"
|
#include "llhudmanager.h"
|
||||||
|
#include "llhudeffecttrail.h"
|
||||||
|
#include "llimview.h"
|
||||||
#include "llinventorybridge.h"
|
#include "llinventorybridge.h"
|
||||||
#include "llinventorydefines.h"
|
#include "llinventorydefines.h"
|
||||||
#include "llinventoryfunctions.h"
|
#include "llinventoryfunctions.h"
|
||||||
@@ -68,18 +70,15 @@
|
|||||||
#include "llviewerregion.h"
|
#include "llviewerregion.h"
|
||||||
#include "llviewerstats.h"
|
#include "llviewerstats.h"
|
||||||
#include "llviewerwindow.h"
|
#include "llviewerwindow.h"
|
||||||
#include "llvoavatar.h"
|
#include "llvoavatarself.h"
|
||||||
#include "llvolume.h"
|
#include "llvolume.h"
|
||||||
#include "llworld.h"
|
#include "llworld.h"
|
||||||
#include "object_flags.h"
|
#include "object_flags.h"
|
||||||
#include "llimview.h"
|
|
||||||
// <edit>
|
// <edit>
|
||||||
#include "llappviewer.h" // System Folders
|
#include "llappviewer.h" // System Folders
|
||||||
#include "llparcel.h" // always rez
|
#include "llparcel.h" // always rez
|
||||||
#include "llviewerparcelmgr.h" // always rez
|
#include "llviewerparcelmgr.h" // always rez
|
||||||
// </edit>
|
// </edit>
|
||||||
#include "object_flags.h"
|
|
||||||
#include "llimview.h"
|
|
||||||
|
|
||||||
// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a)
|
// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a)
|
||||||
#include "rlvhandler.h"
|
#include "rlvhandler.h"
|
||||||
@@ -145,18 +144,18 @@ bool LLDroppableItem::operator()(LLInventoryCategory* cat,
|
|||||||
LLInventoryItem* item)
|
LLInventoryItem* item)
|
||||||
{
|
{
|
||||||
bool allowed = false;
|
bool allowed = false;
|
||||||
if(item)
|
if (item)
|
||||||
{
|
{
|
||||||
allowed = itemTransferCommonlyAllowed(item);
|
allowed = itemTransferCommonlyAllowed(item);
|
||||||
|
|
||||||
if(allowed
|
if (allowed
|
||||||
&& mIsTransfer
|
&& mIsTransfer
|
||||||
&& !item->getPermissions().allowOperationBy(PERM_TRANSFER,
|
&& !item->getPermissions().allowOperationBy(PERM_TRANSFER,
|
||||||
gAgent.getID()))
|
gAgent.getID()))
|
||||||
{
|
{
|
||||||
allowed = false;
|
allowed = false;
|
||||||
}
|
}
|
||||||
if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
|
if (allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
|
||||||
{
|
{
|
||||||
++mCountLosing;
|
++mCountLosing;
|
||||||
}
|
}
|
||||||
@@ -164,29 +163,6 @@ bool LLDroppableItem::operator()(LLInventoryCategory* cat,
|
|||||||
return allowed;
|
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
|
class LLDropCopyableItems : public LLInventoryCollectFunctor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -214,43 +190,6 @@ bool LLDropCopyableItems::operator()(
|
|||||||
return allowed;
|
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
|
class LLCategoryFireAndForget : public LLInventoryFetchComboObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -558,8 +497,8 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
|
|||||||
LLViewerInventoryCategory::cat_array_t cats;
|
LLViewerInventoryCategory::cat_array_t cats;
|
||||||
LLViewerInventoryItem::item_array_t items;
|
LLViewerInventoryItem::item_array_t items;
|
||||||
LLNoPreferredTypeOrItem is_not_preferred;
|
LLNoPreferredTypeOrItem is_not_preferred;
|
||||||
LLInventoryFetchComboObserver::folder_ref_t folder_ids;
|
uuid_vec_t folder_ids;
|
||||||
LLInventoryFetchComboObserver::item_ref_t item_ids;
|
uuid_vec_t item_ids;
|
||||||
if(is_not_preferred(cat, NULL))
|
if(is_not_preferred(cat, NULL))
|
||||||
{
|
{
|
||||||
folder_ids.push_back(cargo_id);
|
folder_ids.push_back(cargo_id);
|
||||||
@@ -649,9 +588,9 @@ void LLToolDragAndDrop::beginMultiDrag(
|
|||||||
}
|
}
|
||||||
if(!cat_ids.empty())
|
if(!cat_ids.empty())
|
||||||
{
|
{
|
||||||
LLInventoryFetchComboObserver::folder_ref_t folder_ids;
|
uuid_vec_t folder_ids;
|
||||||
LLInventoryFetchComboObserver::item_ref_t item_ids;
|
uuid_vec_t item_ids;
|
||||||
std::back_insert_iterator<LLInventoryFetchDescendentsObserver::folder_ref_t> copier(folder_ids);
|
std::back_insert_iterator<uuid_vec_t> copier(folder_ids);
|
||||||
std::copy(cat_ids.begin(), cat_ids.end(), copier);
|
std::copy(cat_ids.begin(), cat_ids.end(), copier);
|
||||||
LLCategoryFireAndForget fetcher;
|
LLCategoryFireAndForget fetcher;
|
||||||
fetcher.fetch(folder_ids, item_ids);
|
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
|
// accessor that looks at permissions, copyability, and names of
|
||||||
// inventory items to determine if a drop would be ok.
|
// inventory items to determine if a drop would be ok.
|
||||||
EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
|
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;
|
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
|
||||||
if(gInventory.getItem(inv_item->getUUID())
|
if(gInventory.getItem(inv_item->getUUID())
|
||||||
&& LLToolDragAndDrop::isInventoryGiveAcceptable(inv_item))
|
&& LLGiveInventory::isInventoryGiveAcceptable(inv_item))
|
||||||
{
|
{
|
||||||
// *TODO: get multiple object transfers working
|
// *TODO: get multiple object transfers working
|
||||||
*accept = ACCEPT_YES_COPY_SINGLE;
|
*accept = ACCEPT_YES_COPY_SINGLE;
|
||||||
if(drop)
|
if(drop)
|
||||||
{
|
{
|
||||||
LLToolDragAndDrop::giveInventory(dest_agent, inv_item, session_id);
|
LLGiveInventory::doGiveInventoryItem(dest_agent, inv_item, session_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2145,7 +1643,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
|
|||||||
*accept = ACCEPT_YES_COPY_SINGLE;
|
*accept = ACCEPT_YES_COPY_SINGLE;
|
||||||
if(drop)
|
if(drop)
|
||||||
{
|
{
|
||||||
LLToolDragAndDrop::giveInventoryCategory(dest_agent, inv_cat, session_id);
|
LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2868,7 +2366,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject(
|
|||||||
{
|
{
|
||||||
if(drop)
|
if(drop)
|
||||||
{
|
{
|
||||||
giveInventory(obj->getID(), item );
|
LLGiveInventory::doGiveInventoryItem(obj->getID(), item );
|
||||||
}
|
}
|
||||||
// *TODO: deal with all the issues surrounding multi-object
|
// *TODO: deal with all the issues surrounding multi-object
|
||||||
// inventory transfers.
|
// inventory transfers.
|
||||||
@@ -2888,13 +2386,13 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventory(
|
|||||||
LLViewerInventoryCategory* cat;
|
LLViewerInventoryCategory* cat;
|
||||||
locateInventory(item, cat);
|
locateInventory(item, cat);
|
||||||
if(!item || !item->isComplete()) return ACCEPT_NO;
|
if(!item || !item->isComplete()) return ACCEPT_NO;
|
||||||
if(!isInventoryGiveAcceptable(item))
|
if(!LLGiveInventory::isInventoryGiveAcceptable(item))
|
||||||
{
|
{
|
||||||
return ACCEPT_NO;
|
return ACCEPT_NO;
|
||||||
}
|
}
|
||||||
if(drop && obj)
|
if(drop && obj)
|
||||||
{
|
{
|
||||||
giveInventory(obj->getID(), item);
|
LLGiveInventory::doGiveInventoryItem(obj->getID(), item);
|
||||||
}
|
}
|
||||||
// *TODO: deal with all the issues surrounding multi-object
|
// *TODO: deal with all the issues surrounding multi-object
|
||||||
// inventory transfers.
|
// inventory transfers.
|
||||||
@@ -2911,7 +2409,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory(
|
|||||||
LLViewerInventoryCategory* cat;
|
LLViewerInventoryCategory* cat;
|
||||||
locateInventory(item, cat);
|
locateInventory(item, cat);
|
||||||
if(!cat) return ACCEPT_NO;
|
if(!cat) return ACCEPT_NO;
|
||||||
giveInventoryCategory(obj->getID(), cat);
|
LLGiveInventory::doGiveInventoryCategory(obj->getID(), cat);
|
||||||
}
|
}
|
||||||
// *TODO: deal with all the issues surrounding multi-object
|
// *TODO: deal with all the issues surrounding multi-object
|
||||||
// inventory transfers.
|
// inventory transfers.
|
||||||
|
|||||||
@@ -208,27 +208,10 @@ protected:
|
|||||||
LLToolDragAndDrop::ESource source,
|
LLToolDragAndDrop::ESource source,
|
||||||
const LLUUID& src_id);
|
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:
|
public:
|
||||||
// helper functions
|
// helper functions
|
||||||
static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); }
|
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 dadUpdateInventory(LLViewerObject* obj, BOOL drop);
|
||||||
BOOL dadUpdateInventoryCategory(LLViewerObject* obj, BOOL drop);
|
BOOL dadUpdateInventoryCategory(LLViewerObject* obj, BOOL drop);
|
||||||
@@ -255,13 +238,6 @@ public:
|
|||||||
ESource source,
|
ESource source,
|
||||||
const LLUUID& src_id);
|
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,
|
static bool handleGiveDragAndDrop(LLUUID agent, LLUUID session, BOOL drop,
|
||||||
EDragAndDropType cargo_type,
|
EDragAndDropType cargo_type,
|
||||||
void* cargo_data,
|
void* cargo_data,
|
||||||
|
|||||||
303
indra/newview/llviewerfoldertype.cpp
Normal file
303
indra/newview/llviewerfoldertype.cpp
Normal 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;
|
||||||
|
}
|
||||||
53
indra/newview/llviewerfoldertype.h
Normal file
53
indra/newview/llviewerfoldertype.h
Normal 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
|
||||||
@@ -167,6 +167,8 @@
|
|||||||
#include "llwlparammanager.h"
|
#include "llwlparammanager.h"
|
||||||
#include "llwaterparammanager.h"
|
#include "llwaterparammanager.h"
|
||||||
|
|
||||||
|
#include "llgiveinventory.h"
|
||||||
|
|
||||||
#include <boost/tokenizer.hpp>
|
#include <boost/tokenizer.hpp>
|
||||||
|
|
||||||
#if LL_WINDOWS // For Windows specific error handler
|
#if LL_WINDOWS // For Windows specific error handler
|
||||||
@@ -1972,7 +1974,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
|
|||||||
position,
|
position,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
LLToolDragAndDrop::giveInventory(from_id, item);
|
LLGiveInventory::doGiveInventoryItem(from_id, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
#include "llcallbacklist.h"
|
#include "llcallbacklist.h"
|
||||||
#include "llstartup.h"
|
#include "llstartup.h"
|
||||||
|
#include "llviewerfoldertype.h"
|
||||||
#include "llviewerobject.h"
|
#include "llviewerobject.h"
|
||||||
#include "llvoavatar.h"
|
#include "llvoavatar.h"
|
||||||
|
|
||||||
@@ -29,9 +30,6 @@
|
|||||||
|
|
||||||
#include "boost/algorithm/string.hpp"
|
#include "boost/algorithm/string.hpp"
|
||||||
|
|
||||||
// Only defined in llinventorymodel.cpp
|
|
||||||
extern const char* NEW_CATEGORY_NAME;
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Static variable initialization
|
// Static variable initialization
|
||||||
//
|
//
|
||||||
@@ -394,6 +392,7 @@ void RlvRenameOnWearObserver::doneIdle()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const std::string &new_category_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_NONE);
|
||||||
for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
|
for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
|
||||||
{
|
{
|
||||||
LLViewerInventoryItem* pItem = items.get(idxItem);
|
LLViewerInventoryItem* pItem = items.get(idxItem);
|
||||||
@@ -428,7 +427,7 @@ void RlvRenameOnWearObserver::doneIdle()
|
|||||||
std::string strFolderName = ".(" + strAttachPt + ")";
|
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
|
// 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()) &&
|
(pFolder->getParentUUID() != pRlvRoot->getUUID()) &&
|
||||||
(1 == RlvInventory::getDirectDescendentsCount(pFolder, LLAssetType::AT_OBJECT)) )
|
(1 == RlvInventory::getDirectDescendentsCount(pFolder, LLAssetType::AT_OBJECT)) )
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user