svn merge -r 127683:128178 svn+ssh://svn.lindenlab.com/svn/linden/branches/avatar-pipeline/folder-links__merge__viewer-2.0.0.3-r127634 into svn+ssh://svn.lindenlab.com/svn/linden/branches/viewer/viewer-2.0.0-3

For DEV-36425 : Viewer merge for Folder Links and Types [VIEWER]

Test plans - EXTERNAL
* [ Test against a 1.30 server ]
* Test various inventory operations -- move, copy, paste-as-link, etc. on both folders and inventory items.
* Test ability to change user-created folder types.  Test inventory operations on these folder types.

Test plans - INTERNAL
* Test against any inventory smoke tests.
* See test plan in QAR-1643 for full FolderLinks&Types test plan.
meow-7.2.2
Loren Shih 2009-07-23 23:41:12 +00:00
parent 80deb2a535
commit 363de6c3bc
25 changed files with 701 additions and 171 deletions

View File

@ -44,19 +44,29 @@ struct AssetEntry : public LLDictionaryEntry
{
AssetEntry(const char *desc_name,
const char *type_name, // 8 character limit!
const char *human_name,
const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one
const char *category_name, // used by llinventorymodel when creating new categories
EDragAndDropType dad_type,
bool can_link);
bool can_link, // can you create a link to this type?
bool is_protected) // can the viewer change categories of this type?
:
LLDictionaryEntry(desc_name),
mTypeName(type_name),
mHumanName(human_name),
mCategoryName(category_name),
mDadType(dad_type),
mCanLink(can_link),
mIsProtected(is_protected)
{
llassert(strlen(mTypeName) <= 8);
}
// limited to 8 characters
const char *mTypeName;
// human readable form. Put as many printable characters you want in each one.
// (c.f. llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES).
const char *mHumanName;
const char *mCategoryName;
EDragAndDropType mDadType;
bool mCanLink;
bool mIsProtected;
};
class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
@ -68,53 +78,50 @@ public:
LLAssetDictionary::LLAssetDictionary()
{
addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE));
addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE));
addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE));
addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE));
addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE));
addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE));
addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE));
addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE));
addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE));
addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE));
addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE));
addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE));
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, FALSE));
addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE));
// DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED?
// |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------|
addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE, TRUE));
addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE, TRUE));
addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE, TRUE));
addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE, TRUE));
addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE));
addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE));
addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE, TRUE));
addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE));
addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE));
addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE, TRUE));
addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE));
addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE, TRUE));
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, FALSE, TRUE));
addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE));
addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "New Folder", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_NONE, FALSE));
addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "Link", DAD_LINK, FALSE, TRUE));
addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_LINK, FALSE, TRUE));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE));
for (S32 ensemble_num = S32(LLAssetType::AT_FOLDER_ENSEMBLE_START);
ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END);
ensemble_num++)
{
addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, TRUE, FALSE));
}
addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Outfit", DAD_CATEGORY, FALSE, TRUE));
addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "Outfit", DAD_CATEGORY, TRUE, FALSE));
addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Outfits", DAD_CATEGORY, FALSE, TRUE));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE));
};
AssetEntry::AssetEntry(const char *desc_name,
const char *type_name,
const char *human_name,
const char *category_name,
EDragAndDropType dad_type,
bool can_link) :
LLDictionaryEntry(desc_name),
mTypeName(type_name),
mHumanName(human_name),
mCategoryName(category_name),
mDadType(dad_type),
mCanLink(can_link)
{
llassert(strlen(mTypeName) <= 8);
}
// static
LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
{
@ -128,11 +135,11 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
{
const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type);
if (entry)
{
{
return entry->mName;
}
else
{
{
static const std::string error_string = "BAD TYPE";
return error_string;
}
@ -154,7 +161,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)
}
// static
LLAssetType::EType LLAssetType::lookup( const char* name )
LLAssetType::EType LLAssetType::lookup(const char* name)
{
return lookup(ll_safe_string(name));
}
@ -191,7 +198,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
}
// static
LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name )
LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name)
{
return lookupHumanReadable(ll_safe_string(name));
}
@ -261,6 +268,21 @@ bool LLAssetType::lookupIsLinkType(EType asset_type)
return false;
}
// static
// Only ensembles and plain folders aren't protected. "Protected" means
// you can't change certain properties such as their type.
bool LLAssetType::lookupIsProtectedCategoryType(EType asset_type)
{
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
const AssetEntry *entry = dict->lookup(asset_type);
if (entry)
{
return entry->mIsProtected;
}
return true;
}
// static. Generate a good default description
void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
std::string& description)

View File

@ -125,7 +125,7 @@ public:
AT_SIMSTATE = 22,
// Simstate file.
AT_FAVORITE = 23,
// favorite items
@ -135,21 +135,35 @@ public:
AT_LINK_FOLDER = 25,
// Inventory folder link
AT_COUNT = 26,
AT_FOLDER_ENSEMBLE_START = 26,
AT_FOLDER_ENSEMBLE_END = 45,
// This range is reserved for special clothing folder types.
// +************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
// +************************************************+
// | 1. INSERT BEFORE AT_COUNT |
// | 2. INCREMENT AT_COUNT BY 1 |
// | 3. ADD TO LLAssetDictionary in llassettype.cpp |
// +************************************************+
AT_CURRENT_OUTFIT = 46,
// Current outfit
AT_OUTFIT = 47,
// Predefined outfit ("look")
AT_MY_OUTFITS = 48,
// Folder that holds your outfits.
AT_COUNT = 49,
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
// +*********************************************************+
// | 1. INSERT BEFORE AT_COUNT |
// | 2. INCREMENT AT_COUNT BY 1 |
// | 3. ADD TO LLAssetDictionary in LLAssetType.cpp |
// | 3. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
// +*********************************************************+
AT_NONE = -1
};
// machine transation between type and strings
static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
static EType lookup(const std::string& type_name);
static const char* lookup(EType asset_type);
@ -158,8 +172,6 @@ public:
static EType lookupHumanReadable(const std::string& readable_name);
static const char* lookupHumanReadable(EType asset_type);
static const char* lookupCategoryName(EType asset_type);
// Generate a good default description. You may want to add a verb
// or agent name after this depending on your application.
static void generateDescriptionFor(LLAssetType::EType asset_type,
@ -168,9 +180,13 @@ public:
static EType getType(const std::string& desc_name);
static const std::string& getDesc(EType asset_type);
static EDragAndDropType lookupDragAndDropType(EType asset_type);
static bool lookupCanLink(EType asset_type);
static bool lookupIsLinkType(EType asset_type);
static const char* lookupCategoryName(EType asset_type);
static bool lookupIsProtectedCategoryType(EType asset_type);
/* TODO: Change return types from "const char *" to "const std::string &".
This is fairly straightforward, but requires changing some calls to use .c_str().
e.g.:
@ -180,8 +196,8 @@ public:
private:
// don't instantiate or derive one of these objects
LLAssetType() {}
~LLAssetType() {}
LLAssetType( void ) {}
~LLAssetType( void ) {}
};
#endif // LL_LLASSETTYPE_H

View File

@ -95,6 +95,10 @@ public:
protected:
void addEntry(Index index, Entry *entry)
{
if (lookup(index))
{
llerrs << "Dictionary entry already added (attempted to add duplicate entry)" << llendl;
}
(*this)[index] = entry;
}
};

View File

@ -54,7 +54,8 @@ enum EDragAndDropType
DAD_BODYPART = 11,
DAD_ANIMATION = 12,
DAD_GESTURE = 13,
DAD_COUNT = 14, // number of types in this enum
DAD_LINK = 14,
DAD_COUNT = 15, // number of types in this enum
};
// Reasons for drags to be denied.

View File

@ -1624,7 +1624,7 @@ LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
rv[INV_PARENT_ID_LABEL] = cat->getParentUUID();
rv[INV_NAME_LABEL] = cat->getName();
rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType());
if(LLAssetType::AT_NONE != cat->getPreferredType())
if(LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
{
rv[INV_PREFERRED_TYPE_LABEL] =
LLAssetType::lookup(cat->getPreferredType());

View File

@ -44,9 +44,23 @@ static const std::string empty_string;
///----------------------------------------------------------------------------
struct InventoryEntry : public LLDictionaryEntry
{
InventoryEntry(const std::string &name,
const std::string &human_name,
int num_asset_types = 0, ...);
InventoryEntry(const std::string &name, // unlike asset type names, not limited to 8 characters; need not match asset type names
const std::string &human_name, // for decoding to human readable form; put any and as many printable characters you want in each one.
int num_asset_types = 0, ...)
:
LLDictionaryEntry(name),
mHumanName(human_name)
{
va_list argp;
va_start(argp, num_asset_types);
// Read in local textures
for (U8 i=0; i < num_asset_types; i++)
{
LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int);
mAssetTypes.push_back(t);
}
}
const std::string mHumanName;
typedef std::vector<LLAssetType::EType> asset_vec_t;
asset_vec_t mAssetTypes;
@ -115,25 +129,35 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_GESTURE, // AT_GESTURE
LLInventoryType::IT_NONE, // AT_SIMSTATE
LLInventoryType::IT_FAVORITE, // AT_FAVORITE
LLInventoryType::IT_NONE, // AT_LINK
LLInventoryType::IT_NONE, // AT_LINK_FOLDER
};
InventoryEntry::InventoryEntry(const std::string &name,
const std::string &human_name,
int num_asset_types, ...) :
LLDictionaryEntry(name),
mHumanName(human_name)
{
va_list argp;
va_start(argp, num_asset_types);
// Read in local textures
for (U8 i=0; i < num_asset_types; i++)
{
LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int);
mAssetTypes.push_back(t);
}
}
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
LLInventoryType::IT_CATEGORY, // AT_CURRENT_OUTFIT
LLInventoryType::IT_CATEGORY, // AT_OUTFIT
LLInventoryType::IT_CATEGORY, // AT_MY_OUTFITS
};
// static
const std::string &LLInventoryType::lookup(EType type)
@ -173,6 +197,21 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a
}
}
// add any types that we don't want the user to be able to change permissions on.
// static
bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type)
{
switch(type)
{
case IT_CALLINGCARD:
case IT_LANDMARK:
return true;
default:
return false;
}
}
bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
LLAssetType::EType asset_type)
{

View File

@ -83,10 +83,13 @@ public:
// return the default inventory for the given asset type.
static EType defaultForAssetType(LLAssetType::EType asset_type);
// true if this type cannot have restricted permissions.
static bool cannotRestrictPermissions(EType type);
private:
// don't instantiate or derive one of these objects
LLInventoryType() {}
~LLInventoryType() {}
LLInventoryType( void );
~LLInventoryType( void );
};
// helper function that returns true if inventory type and asset type

View File

@ -296,10 +296,10 @@ bool is_asset_id_knowable(LLAssetType::EType type)
case LLAssetType::AT_FAVORITE:
case LLAssetType::AT_LINK:
case LLAssetType::AT_LINK_FOLDER:
rv = true;
break;
default:
break;
rv = true;
break;
default:
break;
}
return rv;
}

View File

@ -211,6 +211,7 @@ set(viewer_SOURCE_FILES
llfloaterwater.cpp
llfloaterwindlight.cpp
llfloaterworldmap.cpp
llfoldertype.cpp
llfolderview.cpp
llfolderviewitem.cpp
llfollowcam.cpp
@ -646,6 +647,7 @@ set(viewer_HEADER_FILES
llfloaterwater.h
llfloaterwindlight.h
llfloaterworldmap.h
llfoldertype.h
llfolderview.h
llfoldervieweventlistener.h
llfolderviewitem.h

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ensemble_defs>
<ensemble
asset_num="-1"
xui_name="default"
icon_name="inv_plain_closed.tga"
/>
<ensemble
asset_num="27"
xui_name="head"
icon_name="inv_folder_outfit_head.tga"
/>
<ensemble
asset_num="28"
xui_name="gloves"
icon_name="inv_folder_outfit_gloves.tga"
/>
<ensemble
asset_num="29"
xui_name="jacket"
icon_name="inv_folder_outfit_jacket.tga"
/>
<ensemble
asset_num="30"
xui_name="pants"
icon_name="inv_folder_outfit_pants.tga"
/>
<ensemble
asset_num="31"
xui_name="shape"
icon_name="inv_folder_outfit_shape.tga"
/>
<ensemble
asset_num="32"
xui_name="shoes"
icon_name="inv_folder_outfit_shoes.tga"
/>
<ensemble
asset_num="33"
xui_name="shirt"
icon_name="inv_folder_outfit_shirt.tga"
/>
<ensemble
asset_num="34"
xui_name="skirt"
icon_name="inv_folder_outfit_skirt.tga"
/>
<ensemble
asset_num="35"
xui_name="underpants"
icon_name="inv_folder_outfit_underpants.tga"
/>
<ensemble
asset_num="36"
xui_name="undershirt"
icon_name="inv_folder_outfit_undershirt.tga"
/>
</ensemble_defs>

View File

@ -1533,12 +1533,14 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
<< ((S32) objectp->getType())
<< " (shouldn't happen)" << llendl;
}
else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category
else if (objectp->getType() == LLAssetType::AT_CATEGORY &&
objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)
{
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
LLInventoryType::IT_CATEGORY,
this,
objectp->getUUID());
objectp->getType(),
LLInventoryType::IT_CATEGORY,
this,
objectp->getUUID());
if (new_listener)
{
@ -1553,15 +1555,17 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
itemp = folderp;
}
}
else // build new view for item
else
{
// Build new view for item
LLInventoryItem* item = (LLInventoryItem*)objectp;
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
item->getType(),
item->getInventoryType(),
this,
item->getUUID(),
item->getFlags());
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(item->getType(),
item->getActualType(),
item->getInventoryType(),
this,
item->getUUID(),
item->getFlags());
if (new_listener)
{
LLFolderViewItem::Params params;
@ -1591,7 +1595,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
}
if ((id.isNull() ||
(objectp && objectp->getType() == LLAssetType::AT_CATEGORY)))
(objectp && objectp->getType() == LLAssetType::AT_CATEGORY)))
{
LLViewerInventoryCategory::cat_array_t* categories;
LLViewerInventoryItem::item_array_t* items;

View File

@ -658,6 +658,7 @@ void LLFloaterProperties::onCommitName(LLUICtrl* ctrl, void* data)
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.updateLinkedObjects(new_item->getUUID());
gInventory.notifyObservers();
}
else

View File

@ -34,10 +34,12 @@
#include "llfolderview.h"
#include "llagent.h"
#include "llcallbacklist.h"
#include "llinventorybridge.h"
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
#include "llinventoryfilter.h"
#include "llfoldertype.h"
#include "llfloaterinventory.h"// hacked in for the bonus context menu items.
#include "llkeyboard.h"
#include "lllineeditor.h"
@ -1094,6 +1096,35 @@ void LLFolderView::propertiesSelectedItems( void )
}
}
void LLFolderView::changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type)
{
LLFolderBridge *folder_bridge = LLFolderBridge::sSelf;
if (!folder_bridge) return;
LLViewerInventoryCategory *cat = folder_bridge->getCategory();
if (!cat) return;
const LLUUID &folder_id = cat->getUUID();
const LLUUID &parent_id = cat->getParentUUID();
const std::string &name = cat->getName();
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_FolderData);
msg->addUUIDFast(_PREHASH_FolderID, folder_id);
msg->addUUIDFast(_PREHASH_ParentID, parent_id);
msg->addS8Fast(_PREHASH_Type, new_folder_type);
msg->addStringFast(_PREHASH_Name, name);
gAgent.sendReliableMessage();
cat->setPreferredType(new_folder_type);
gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
gInventory.updateLinkedObjects(folder_id);
}
void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
{
if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH)
@ -1904,6 +1935,16 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)
LLInventoryClipboard::instance().reset();
}
static const std::string change_folder_string = "change_folder_type_";
if (action.length() > change_folder_string.length() &&
(action.compare(0,change_folder_string.length(),"change_folder_type_") == 0))
{
LLAssetType::EType new_folder_type = LLFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
changeType(model, new_folder_type);
return true;
}
std::set<LLUUID> selected_items;
getSelectionList(selected_items);

View File

@ -190,6 +190,9 @@ public:
void openSelectedItems( void );
void propertiesSelectedItems( void );
// change the folder type
void changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type);
void autoOpenItem(LLFolderViewFolder* item);
void closeAutoOpenedFolders();
BOOL autoOpenTest(LLFolderViewFolder* item);

View File

@ -230,7 +230,7 @@ void LLFolderViewItem::refreshFromListener()
// *TODO: to be removed when database supports multi language. This is a
// temporary attempt to display the inventory folder in the user locale.
if (preferred_type != LLAssetType::AT_NONE)
if (LLAssetType::lookupIsProtectedCategoryType(preferred_type))
{
mLabel = LLTrans::getString("InvFolder " + mLabel);
};

View File

@ -157,13 +157,6 @@ protected:
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
// This function clears the currently selected item, and records
// the specified selected item appropriately for display and use
// in the UI. If open is TRUE, then folders are opened up along
// the way to the selection.
void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
BOOL take_keyboard_focus = TRUE);
// helper function to change the selection from the root.
void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
@ -176,6 +169,13 @@ protected:
virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
public:
// This function clears the currently selected item, and records
// the specified selected item appropriately for display and use
// in the UI. If open is TRUE, then folders are opened up along
// the way to the selection.
void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
BOOL take_keyboard_focus = TRUE);
// This function is called when the folder view is dirty. It's
// implemented here but called by derived classes when folding the
// views.

View File

@ -51,6 +51,7 @@
#include "llviewercontrol.h"
#include "llfirstuse.h"
#include "llfoldertype.h"
#include "llfloaterchat.h"
#include "llfloatercustomize.h"
#include "llfloaterproperties.h"
@ -604,7 +605,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
if(obj)
{
*type = LLAssetType::lookupDragAndDropType(obj->getType());
*type = LLAssetType::lookupDragAndDropType(obj->getActualType());
if(*type == DAD_NONE)
{
return FALSE;
@ -653,11 +654,11 @@ BOOL LLInvFVBridge::isLinkedObjectInTrash() const
{
if (isInTrash()) return TRUE;
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
LLInventoryObject *obj = model->getObject(mUUID);
LLInventoryObject *obj = getInventoryObject();
if (obj && LLAssetType::lookupIsLinkType(obj->getActualType()))
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
const LLUUID& trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
}
@ -735,6 +736,7 @@ const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
}
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
const LLUUID& uuid,
@ -833,12 +835,22 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
break;
case LLAssetType::AT_CATEGORY:
case LLAssetType::AT_ROOT_CATEGORY:
if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
{
// Create a link folder handler instead.
new_listener = new LLLinkFolderBridge(inventory, uuid);
break;
}
new_listener = new LLFolderBridge(inventory, uuid);
break;
case LLAssetType::AT_LINK:
// Only should happen for broken links.
new_listener = new LLLinkItemBridge(inventory, uuid);
break;
case LLAssetType::AT_LINK_FOLDER:
// Only should happen for broken links.
new_listener = new LLLinkItemBridge(inventory, uuid);
break;
default:
llinfos << "Unhandled asset type (llassetstorage.h): "
<< (S32)asset_type << llendl;
@ -875,6 +887,10 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
if ("goto" == action)
{
gotoItem(folder);
}
if ("open" == action)
{
openItem();
@ -1005,6 +1021,19 @@ void LLItemBridge::restoreToWorld()
}
}
void LLItemBridge::gotoItem(LLFolderView *folder)
{
LLInventoryObject *obj = getInventoryObject();
if (obj && LLAssetType::lookupIsLinkType(obj->getActualType()))
{
LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
if (active_panel)
{
active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
}
}
}
LLUIImagePtr LLItemBridge::getIcon() const
{
return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
@ -1075,7 +1104,8 @@ std::string LLItemBridge::getLabelSuffix() const
static std::string NO_COPY =LLTrans::getString("no_copy");
static std::string NO_MOD = LLTrans::getString("no_modify");
static std::string NO_XFER = LLTrans::getString("no_transfer");
static std::string LINK = LLTrans::getString("link");
static std::string BROKEN_LINK = LLTrans::getString("broken_link");
std::string suffix;
LLInventoryItem* item = getItem();
if(item)
@ -1084,8 +1114,10 @@ std::string LLItemBridge::getLabelSuffix() const
if(LLAssetType::AT_CALLINGCARD != item->getType()
&& item->getPermissions().getOwner() == gAgent.getID())
{
BOOL link = (item->getActualType() == LLAssetType::AT_LINK);
const char* LINK = " (link)"; // *TODO: Seraph translate
BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
if (broken_link) return BROKEN_LINK;
BOOL link = LLAssetType::lookupIsLinkType(item->getActualType());
if (link) return LINK;
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
@ -1146,7 +1178,7 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
renameLinkedItems(item->getUUID(),new_name);
model->updateLinkedObjects(item->getUUID());
model->notifyObservers();
}
@ -1204,7 +1236,7 @@ BOOL LLItemBridge::isItemCopyable() const
// All items can be copied, not all can be pasted.
// The only time an item can't be copied is if it's a link
// return (item->getPermissions().allowCopyBy(gAgent.getID()));
if (item->getActualType() == LLAssetType::AT_LINK)
if (LLAssetType::lookupIsLinkType(item->getActualType()))
{
return FALSE;
}
@ -1259,7 +1291,7 @@ BOOL LLFolderBridge::isItemMovable()
LLInventoryObject* obj = getInventoryObject();
if(obj)
{
return (LLAssetType::AT_NONE == ((LLInventoryCategory*)obj)->getPreferredType());
return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType()));
}
return FALSE;
}
@ -1295,7 +1327,7 @@ BOOL LLFolderBridge::isItemRemovable()
return FALSE;
}
if( LLAssetType::AT_NONE != category->getPreferredType() )
if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
{
return FALSE;
}
@ -1308,7 +1340,7 @@ BOOL LLFolderBridge::isItemRemovable()
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
if( LLAssetType::AT_NONE != category->getPreferredType() )
if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
{
return FALSE;
}
@ -1403,7 +1435,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
BOOL move_is_into_trash = (mUUID == trash_id)
|| model->isObjectDescendentOf(mUUID, trash_id);
BOOL is_movable = (LLAssetType::AT_NONE == inv_cat->getPreferredType());
BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType()));
if( is_movable )
{
gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
@ -1411,7 +1443,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
if( LLAssetType::AT_NONE != category->getPreferredType() )
if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
{
// ...can't move "special folders" like Textures
is_movable = FALSE;
@ -1868,7 +1900,7 @@ void LLFolderBridge::openItem()
BOOL LLFolderBridge::isItemRenameable() const
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)
if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())
&& (cat->getOwnerID() == gAgent.getID()))
{
return TRUE;
@ -1904,13 +1936,26 @@ LLAssetType::EType LLFolderBridge::getPreferredType() const
// Icons for folders are based on the preferred type
LLUIImagePtr LLFolderBridge::getIcon() const
{
const char* control = NULL;
LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
preferred_type = cat->getPreferredType();
}
return getIcon(preferred_type);
}
LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type)
{
if (preferred_type >= LLAssetType::AT_FOLDER_ENSEMBLE_START &&
preferred_type <= LLAssetType::AT_FOLDER_ENSEMBLE_END)
{
LLUIImage* icon = LLUI::getUIImage(LLFolderType::lookupIconName(preferred_type));
if (icon)
return icon;
}
const char* control = NULL;
switch(preferred_type)
{
case LLAssetType::AT_TEXTURE:
@ -1984,7 +2029,7 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name)
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
renameLinkedItems(cat->getUUID(),new_name);
model->updateLinkedObjects(cat->getUUID());
model->notifyObservers();
}
@ -2066,15 +2111,24 @@ void LLFolderBridge::pasteLinkFromClipboard()
LLInventoryModel* model = getInventoryModel();
if(model)
{
LLInventoryItem* item = NULL;
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
S32 count = objects.count();
LLUUID parent_id(mUUID);
for(S32 i = 0; i < count; i++)
{
item = model->getItem(objects.get(i));
if (item)
const LLUUID &object_id = objects.get(i);
if (LLInventoryCategory *cat = model->getCategory(object_id))
{
link_inventory_item(
gAgent.getID(),
cat->getUUID(),
parent_id,
cat->getName(),
LLAssetType::AT_LINK_FOLDER,
LLPointer<LLInventoryCallback>(NULL));
}
else if (LLInventoryItem *item = model->getItem(object_id))
{
link_inventory_item(
gAgent.getID(),
@ -2103,7 +2157,7 @@ void LLFolderBridge::folderOptionsMenu()
const LLInventoryCategory* category = model->getCategory(mUUID);
bool is_default_folder = category &&
(LLAssetType::AT_NONE != category->getPreferredType());
(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()));
// calling card related functionality for folders.
@ -2199,7 +2253,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mItems.push_back(std::string("New Gesture"));
mItems.push_back(std::string("New Clothes"));
mItems.push_back(std::string("New Body Parts"));
mItems.push_back(std::string("Change Type"));
LLViewerInventoryCategory *cat = getCategory();
if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
{
mDisabledItems.push_back(std::string("Change Type"));
}
getClipboardEntries(false, mItems, mDisabledItems, flags);
//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
@ -2268,26 +2329,27 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
BOOL accept = FALSE;
switch(cargo_type)
{
case DAD_TEXTURE:
case DAD_SOUND:
case DAD_CALLINGCARD:
case DAD_LANDMARK:
case DAD_SCRIPT:
case DAD_OBJECT:
case DAD_NOTECARD:
case DAD_CLOTHING:
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
drop);
break;
case DAD_CATEGORY:
accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
case DAD_TEXTURE:
case DAD_SOUND:
case DAD_CALLINGCARD:
case DAD_LANDMARK:
case DAD_SCRIPT:
case DAD_OBJECT:
case DAD_NOTECARD:
case DAD_CLOTHING:
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_LINK:
accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
drop);
break;
default:
break;
break;
case DAD_CATEGORY:
accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
drop);
break;
default:
break;
}
return accept;
}
@ -2490,14 +2552,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
BOOL is_movable = TRUE;
switch( inv_item->getType() )
switch( inv_item->getActualType() )
{
case LLAssetType::AT_ROOT_CATEGORY:
is_movable = FALSE;
break;
case LLAssetType::AT_CATEGORY:
is_movable = ( LLAssetType::AT_NONE == ((LLInventoryCategory*)inv_item)->getPreferredType() );
is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType());
break;
default:
break;
@ -2511,11 +2573,11 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID(), TRUE);
break;
case LLAssetType::AT_OBJECT:
is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
is_movable = !avatar->isWearingAttachment(inv_item->getUUID(), TRUE);
break;
default:
break;
@ -3435,7 +3497,7 @@ LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
}
LLInventoryItem* item = getItem();
if (item->getActualType() == LLAssetType::AT_LINK)
if (LLAssetType::lookupIsLinkType(item->getActualType()))
{
font |= LLFontGL::ITALIC;
}
@ -3533,13 +3595,18 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
LLInventoryItem* item = getItem();
if (item && LLAssetType::lookupIsLinkType(item->getActualType()))
{
items.push_back(std::string("Goto Link"));
}
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
LLObjectBridge::sContextMenuItemID = mUUID;
LLInventoryItem* item = getItem();
if(item)
{
LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
@ -3619,7 +3686,7 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
renameLinkedItems(item->getUUID(),new_name);
model->updateLinkedObjects(item->getUUID());
model->notifyObservers();
@ -4513,6 +4580,11 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Open"));
}
if (item && LLAssetType::lookupIsLinkType(item->getActualType()))
{
items.push_back(std::string("Goto Link"));
}
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
@ -5093,3 +5165,94 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
hideContextEntries(menu, items, disabled_items);
}
// +=================================================+
// | LLLinkBridge |
// +=================================================+
// For broken links.
std::string LLLinkFolderBridge::sPrefix("Link: ");
LLUIImagePtr LLLinkFolderBridge::getIcon() const
{
LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
if (LLViewerInventoryItem *item = getItem())
{
if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
{
preferred_type = cat->getPreferredType();
}
}
return LLFolderBridge::getIcon(preferred_type);
}
void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
// *TODO: Translate
lldebugs << "LLLink::buildContextMenu()" << llendl;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
if(isInTrash())
{
items.push_back(std::string("Purge Item"));
if (!isItemRemovable())
{
disabled_items.push_back(std::string("Purge Item"));
}
items.push_back(std::string("Restore Item"));
}
else
{
items.push_back(std::string("Goto Link"));
items.push_back(std::string("Delete"));
if (!isItemRemovable())
{
disabled_items.push_back(std::string("Delete"));
}
}
hideContextEntries(menu, items, disabled_items);
}
void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
if ("goto" == action)
{
gotoItem(folder);
return;
}
LLItemBridge::performAction(folder,model,action);
}
void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
{
const LLUUID &cat_uuid = getFolderID();
if (!cat_uuid.isNull())
{
if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
{
if (LLInventoryModel* model = getInventoryModel())
{
model->fetchDescendentsOf(cat_uuid);
}
base_folder->setOpen(TRUE);
folder->setSelectionFromRoot(base_folder,TRUE);
}
}
}
const LLUUID &LLLinkFolderBridge::getFolderID() const
{
if (LLViewerInventoryItem *link_item = getItem())
{
if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
{
const LLUUID& cat_uuid = cat->getUUID();
return cat_uuid;
}
}
return LLUUID::null;
}

View File

@ -133,6 +133,7 @@ public:
// This method is a convenience function which creates the correct
// type of bridge based on some basic information
static LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
const LLUUID& uuid,
@ -156,6 +157,7 @@ public:
}
virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
virtual void openItem() {}
virtual void gotoItem(LLFolderView *folder) {} // for links
virtual void previewItem() {openItem();}
virtual void showProperties();
virtual BOOL isItemRenameable() const { return TRUE; }
@ -231,6 +233,7 @@ public:
virtual void selectItem();
virtual void restoreItem();
virtual void restoreToWorld();
virtual void gotoItem(LLFolderView *folder);
virtual LLUIImagePtr getIcon() const;
virtual const std::string& getDisplayName() const;
@ -274,6 +277,8 @@ public:
virtual LLAssetType::EType getPreferredType() const;
virtual LLUIImagePtr getIcon() const;
static LLUIImagePtr getIcon(LLAssetType::EType asset_type);
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem();
virtual void pasteFromClipboard();
@ -591,6 +596,27 @@ protected:
static std::string sPrefix;
};
class LLLinkFolderBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
virtual const std::string& getPrefix() { return sPrefix; }
virtual LLUIImagePtr getIcon() const;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
virtual void gotoItem(LLFolderView *folder);
protected:
LLLinkFolderBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
LLItemBridge(inventory, uuid) {}
const LLUUID &getFolderID() const;
protected:
static std::string sPrefix;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction (& its derived classes)
//

View File

@ -475,6 +475,35 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
}
}
void LLInventoryModel::updateLinkedObjects(const LLUUID& object_id)
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
LLLinkedItemIDMatches is_linked_item_match(object_id);
collectDescendentsIf(gInventory.getRootFolderID(),
cat_array,
item_array,
LLInventoryModel::INCLUDE_TRASH,
is_linked_item_match);
for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
cat_iter != cat_array.end();
cat_iter++)
{
LLViewerInventoryCategory *linked_cat = (*cat_iter);
addChangedMask(LLInventoryObserver::LABEL, linked_cat->getUUID());
};
for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
iter != item_array.end();
iter++)
{
LLViewerInventoryItem *linked_item = (*iter);
addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
};
notifyObservers();
}
void LLInventoryModel::collectLinkedItems(const LLUUID& id,
item_array_t& items)
{
@ -825,10 +854,10 @@ void LLInventoryModel::purgeObject(const LLUUID &id)
void LLInventoryModel::purgeLinkedObjects(const LLUUID &id)
{
LLInventoryItem* itemp = getItem(id);
if (!itemp) return;
LLInventoryObject* objectp = getObject(id);
if (!objectp) return;
if (LLAssetType::lookupIsLinkType(itemp->getActualType()))
if (LLAssetType::lookupIsLinkType(objectp->getActualType()))
{
return;
}

View File

@ -181,7 +181,6 @@ public:
cat_array_t& categories,
item_array_t& items,
BOOL include_trash);
void collectDescendentsIf(const LLUUID& id,
cat_array_t& categories,
item_array_t& items,
@ -192,8 +191,9 @@ public:
// Assumes item_id is itself not a linked item.
void collectLinkedItems(const LLUUID& item_id,
item_array_t& items);
// This method will return false if this inventory model is in an usabel state.
// Updates all linked objects pointing to this id.
void updateLinkedObjects(const LLUUID& object_id);
// The inventory model usage is sensitive to the initial construction of the
// model.
bool isInventoryUsable();

View File

@ -473,6 +473,14 @@ LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT]
&LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
&LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
},
// Source: DAD_LINK
{
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
&LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
},
};
LLToolDragAndDrop::LLToolDragAndDrop()
@ -1894,7 +1902,7 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
acceptable = FALSE;
break;
case LLAssetType::AT_OBJECT:
if(my_avatar->isWearingAttachment(item->getUUID()))
if(my_avatar->isWearingAttachment(item->getUUID(), TRUE))
{
acceptable = FALSE;
}

View File

@ -403,7 +403,8 @@ void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
void LLViewerInventoryCategory::updateServer(BOOL is_new) const
{
// communicate that change with the server.
if(LLAssetType::AT_NONE != mPreferredType)
if (LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
{
LLNotifications::instance().add("CannotModifyProtectedCategories");
return;
@ -427,7 +428,7 @@ void LLViewerInventoryCategory::removeFromServer( void )
llinfos << "Removing inventory category " << mUUID << " from server."
<< llendl;
// communicate that change with the server.
if(LLAssetType::AT_NONE != mPreferredType)
if(LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
{
LLNotifications::instance().add("CannotRemoveProtectedCategories");
return;
@ -977,7 +978,10 @@ LLAssetType::EType LLViewerInventoryItem::getType() const
{
return linked_item->getType();
}
if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
{
return linked_category->getType();
}
return LLInventoryItem::getType();
}
@ -997,6 +1001,10 @@ const std::string& LLViewerInventoryItem::getName() const
{
return linked_item->getName();
}
if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
{
return linked_category->getName();
}
return LLInventoryItem::getName();
}

View File

@ -141,7 +141,6 @@ public:
};
LLTransactionID getTransactionID() const { return mTransactionID; }
protected:
const LLViewerInventoryItem *getLinkedItem() const;
const LLViewerInventoryCategory *getLinkedCategory() const;

View File

@ -76,6 +76,14 @@
function="Inventory.DoCreate"
parameter="category" />
</menu_item_call>
<menu_item_call
label="New Current"
layout="topleft"
name="New Current">
<menu_item_call.on_click
function="Inventory.DoCreate"
parameter="current" />
</menu_item_call>
<menu_item_call
label="New Script"
layout="topleft"
@ -230,6 +238,91 @@
parameter="eyes" />
</menu_item_call>
</menu>
<menu
label="Change Type"
layout="topleft"
name="Change Type">
<menu_item_call
label="Default"
layout="topleft"
name="Default">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_default" />
</menu_item_call>
<menu_item_call
label="Gloves"
layout="topleft"
name="Gloves">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_gloves" />
</menu_item_call>
<menu_item_call
label="Jacket"
layout="topleft"
name="Jacket">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_jacket" />
</menu_item_call>
<menu_item_call
label="Pants"
layout="topleft"
name="Pants">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_pants" />
</menu_item_call>
<menu_item_call
label="Shape"
layout="topleft"
name="Shape">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_shape" />
</menu_item_call>
<menu_item_call
label="Shoes"
layout="topleft"
name="Shoes">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_shoes" />
</menu_item_call>
<menu_item_call
label="Shirt"
layout="topleft"
name="Shirt">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_shirt" />
</menu_item_call>
<menu_item_call
label="Skirt"
layout="topleft"
name="Skirt">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_skirt" />
</menu_item_call>
<menu_item_call
label="Underpants"
layout="topleft"
name="Underpants">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_underpants" />
</menu_item_call>
<menu_item_call
label="Undershirt"
layout="topleft"
name="Undershirt">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="change_folder_type_undershirt" />
</menu_item_call>
</menu>
<menu_item_call
label="Teleport"
layout="topleft"
@ -270,6 +363,14 @@
function="Inventory.DoToSelected"
parameter="restore" />
</menu_item_call>
<menu_item_call
label="Goto Link"
layout="topleft"
name="Goto Link">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="goto" />
</menu_item_call>
<menu_item_call
label="Open"
layout="topleft"

View File

@ -346,6 +346,8 @@ this texture in your inventory
<string name="no_modify" value=" (no modify)" />
<string name="no_copy" value=" (no copy)" />
<string name="worn" value=" (worn)" />
<string name="link" value=" (link)" />
<string name="broken_link" value=" (broken_link)" />
<string name="LoadingContents">Loading contents...</string>
<string name="NoContents">No contents</string>