diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 8391f3d2f..88c64bde1 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -214,17 +214,16 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_ bool LLAssetType::lookupCanLink(EType asset_type) { //Check that enabling all these other types as linkable doesn't break things. - /*const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); const AssetEntry *entry = dict->lookup(asset_type); if (entry) { return entry->mCanLink; } return false; - */ - return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY || - asset_type == AT_BODYPART || asset_type == AT_GESTURE); + /*return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY || + asset_type == AT_BODYPART || asset_type == AT_GESTURE);*/ } // static diff --git a/indra/newview/cofmgr.cpp b/indra/newview/cofmgr.cpp index bac05e2ff..3820517ae 100644 --- a/indra/newview/cofmgr.cpp +++ b/indra/newview/cofmgr.cpp @@ -264,7 +264,7 @@ void LLCOFMgr::addCOFItemLink(const LLInventoryItem* pItem, LLPointergetLinkedUUID(), getCOF(), pItem->getName(), strDescr, LLAssetType::AT_LINK, cb); } -bool LLCOFMgr::isLinkInCOF(const LLUUID& idItem) +bool LLCOFMgr::isLinkInCOF(const LLUUID& idItem) const { LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items; LLLinkedItemIDMatches f(gInventory.getLinkedItemID(idItem)); @@ -287,6 +287,34 @@ void LLCOFMgr::removeCOFItemLinks(const LLUUID& idItem) } } +BOOL LLCOFMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const +{ + if (!isLinkInCOF(obj_id)) return FALSE; + + // If a non-link somehow ended up in COF, allow deletion. + const LLInventoryObject *obj = gInventory.getObject(obj_id); + if (obj && !obj->getIsLinkType()) + { + return FALSE; + } + + // For now, don't allow direct deletion from the COF. Instead, force users + // to choose "Detach" or "Take Off". + return TRUE; + /* + const LLInventoryObject *obj = gInventory.getObject(obj_id); + if (!obj) return FALSE; + + // Can't delete bodyparts, since this would be equivalent to removing the item. + if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE; + + // Can't delete the folder link, since this is saved for bookkeeping. + if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE; + + return FALSE; + */ +} + // ============================================================================ // Attachment functions // diff --git a/indra/newview/cofmgr.h b/indra/newview/cofmgr.h index 10d819001..50d812c68 100644 --- a/indra/newview/cofmgr.h +++ b/indra/newview/cofmgr.h @@ -31,7 +31,8 @@ public: static const LLUUID getCOF() { return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); } static void getDescendentsOfAssetType(const LLUUID& idCat, LLInventoryModel::item_array_t& items, LLAssetType::EType typeAsset, bool fFollowFolderLinks); - bool isLinkInCOF(const LLUUID& idItem); + bool isLinkInCOF(const LLUUID& idItem) const; + BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; protected: void addCOFItemLink(const LLUUID& idItem, LLPointer cb = NULL); void addCOFItemLink(const LLInventoryItem* pItem, LLPointer cb = NULL); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index e35aa57b1..7b41bf74b 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -38,8 +38,10 @@ #include "llagent.h" #include "llbutton.h" #include "llfocusmgr.h" +#include "llfoldervieweventlistener.h" #include "llinventoryview.h" #include "llinventorymodel.h" +#include "llinventoryfunctions.h" #include "lllineeditor.h" #include "llscrolllistctrl.h" #include "lltextbox.h" diff --git a/indra/newview/llfloaterlandmark.cpp b/indra/newview/llfloaterlandmark.cpp index f9b81bbe5..b6dd5bd2a 100644 --- a/indra/newview/llfloaterlandmark.cpp +++ b/indra/newview/llfloaterlandmark.cpp @@ -39,6 +39,7 @@ #include "llcheckboxctrl.h" #include "llviewerparcelmgr.h" #include "llfolderview.h" +#include "llfoldervieweventlistener.h" #include "llinventory.h" #include "llinventoryfunctions.h" #include "llinventoryview.h" diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 16a4f1379..049164d0d 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -45,6 +45,7 @@ #include "llinventory.h" #include "llcallbacklist.h" +#include "llfoldervieweventlistener.h" #include "llinventoryclipboard.h" // *TODO: remove this once hack below gone. #include "llinventoryview.h"// hacked in for the bonus context menu items. #include "llkeyboard.h" diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 9e4f9e24b..c8125c057 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -71,64 +71,7 @@ class LLFolderViewItem; class LLFolderView; class LLInventoryModel; class LLScrollableContainerView; - -class LLFolderViewEventListener -{ -public: - virtual ~LLFolderViewEventListener( void ) {} - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual PermissionMask getPermissionMask() const = 0; - virtual LLUIImagePtr getIcon() const = 0; - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; - virtual void openItem( void ) = 0; - virtual void previewItem( void ) = 0; - virtual void selectItem(void) = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder - virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed - virtual BOOL removeItem() = 0; - virtual void removeBatch(LLDynamicArray& batch) = 0; - virtual void move( LLFolderViewEventListener* parent_listener ) = 0; - virtual BOOL isItemCopyable() const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() const = 0; - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - virtual BOOL isUpToDate() const = 0; - virtual BOOL hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) {} - - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) = 0; - - // This method is called when the object being referenced by the - // bridge is actually dropped. This allows for cleanup of the old - // view, reference counting, etc. -// virtual void dropped() = 0; - - // this method accesses the parent and arranges and sets it as - // specified. - void arrangeAndSet(LLFolderViewItem* focus, BOOL set_selection, - BOOL take_keyboard_focus = TRUE); -}; +class LLFolderViewEventListener; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h new file mode 100644 index 000000000..deefa298b --- /dev/null +++ b/indra/newview/llfoldervieweventlistener.h @@ -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 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& 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 diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 304d8d5b3..14cad7cc6 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -43,6 +43,7 @@ #include "llagent.h" #include "llcallingcard.h" #include "llcheckboxctrl.h" // for radio buttons +#include "llfoldervieweventlistener.h" #include "llnotificationsutil.h" #include "llradiogroup.h" #include "llspinctrl.h" @@ -410,7 +411,7 @@ class LLDoCreate : public inventory_panel_listener_t LLInventoryModel* model = mPtr->getModel(); if(!model) return false; std::string type = userdata.asString(); - do_create(model, mPtr, type, LLFolderBridge::sSelf); + do_create(model, mPtr, type, LLFolderBridge::sSelf.get()); return true; } }; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 37172bd71..5efa9fab4 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -52,6 +52,7 @@ #include "llspinctrl.h" #include "lltextbox.h" #include "llui.h" +#include "llviewerfoldertype.h" #include "llviewercontrol.h" #include "llfirstuse.h" @@ -251,21 +252,7 @@ time_t LLInvFVBridge::getCreationDate() const // Can be destroyed (or moved to trash) BOOL LLInvFVBridge::isItemRemovable() { - LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - const LLInventoryObject *obj = model->getItem(mUUID); - if (obj && obj->getIsLinkType()) - { - return TRUE; - } - if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return TRUE; - } - return FALSE; + return get_is_item_removable(getInventoryModel(), mUUID); } // Can be moved to another folder @@ -645,6 +632,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } else { + if (LLAssetType::lookupCanLink(obj->getType())) + { + items.push_back(std::string("Find Links")); + } items.push_back(std::string("Rename")); if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) { @@ -654,13 +645,21 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if (show_asset_id) { items.push_back(std::string("Copy Asset UUID")); - if ((!( isItemPermissive() || gAgent.isGodlike())) - || (flags & FIRST_SELECTED_ITEM) == 0) + + bool is_asset_knowable = false; + + LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); + if (inv_item) + { + is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType()); + } + if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 + || (! ( isItemPermissive() || gAgent.isGodlike() ) ) + || (flags & FIRST_SELECTED_ITEM) == 0) { disabled_items.push_back(std::string("Copy Asset UUID")); } } - items.push_back(std::string("Copy Separator")); items.push_back(std::string("Copy")); @@ -898,27 +897,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - // - bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID()); - // - 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 new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent_id); - // - if(send_parent_update) - // - new_item->updateParentOnServer(restamp); - model->updateItem(new_item); - model->notifyObservers(); - } + change_item_parent(model, item, new_parent_id, restamp); } // static @@ -927,21 +906,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - if(cat->getParentUUID() != new_parent_id) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent_id); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); - } + change_category_parent(model, cat, new_parent_id, restamp); } LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, @@ -1540,11 +1505,7 @@ BOOL LLItemBridge::isItemPermissive() const LLViewerInventoryItem* item = getItem(); if(item) { - U32 mask = item->getPermissions().getMaskBase(); - if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - return TRUE; - } + return item->getIsFullPerm(); } return FALSE; } @@ -1553,7 +1514,7 @@ BOOL LLItemBridge::isItemPermissive() const // | LLFolderBridge | // +=================================================+ -LLFolderBridge* LLFolderBridge::sSelf=NULL; +LLHandle LLFolderBridge::sSelf; // Can be moved to another folder BOOL LLFolderBridge::isItemMovable() @@ -2210,13 +2171,7 @@ void LLFolderBridge::openItem() BOOL LLFolderBridge::isItemRenameable() const { - LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); - if(cat && ((cat->getPreferredType() == LLFolderType::FT_NONE) || (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) - && (cat->getOwnerID() == gAgent.getID())) - { - return TRUE; - } - return FALSE; + return get_is_category_renameable(getInventoryModel(), mUUID); } void LLFolderBridge::restoreItem() @@ -2247,82 +2202,34 @@ LLFolderType::EType LLFolderBridge::getPreferredType() const // Icons for folders are based on the preferred type LLUIImagePtr LLFolderBridge::getIcon() const { - const char* control = NULL; LLFolderType::EType preferred_type = LLFolderType::FT_NONE; LLViewerInventoryCategory* cat = getCategory(); if(cat) { preferred_type = cat->getPreferredType(); } - switch(preferred_type) - { - case LLFolderType::FT_TEXTURE: - control = "inv_folder_texture.tga"; - break; - case LLFolderType::FT_SOUND: - control = "inv_folder_sound.tga"; - break; - case LLFolderType::FT_CALLINGCARD: - control = "inv_folder_callingcard.tga"; - break; - case LLFolderType::FT_LANDMARK: - control = "inv_folder_landmark.tga"; - break; - //case LLFolderType::FT_SCRIPT: - case LLFolderType::FT_LSL_TEXT: - control = "inv_folder_script.tga"; - break; - case LLFolderType::FT_OBJECT: - control = "inv_folder_object.tga"; - break; - case LLFolderType::FT_NOTECARD: - control = "inv_folder_notecard.tga"; - break; - //case LLFolderType::FT_CATEGORY: - // control = "inv_folder_plain_closed.tga"; - // break; - case LLFolderType::FT_CLOTHING: - control = "inv_folder_clothing.tga"; - break; - case LLFolderType::FT_BODYPART: - control = "inv_folder_bodypart.tga"; - break; - case LLFolderType::FT_TRASH: - control = "inv_folder_trash.tga"; - break; - case LLFolderType::FT_SNAPSHOT_CATEGORY: - control = "inv_folder_snapshot.tga"; - break; - case LLFolderType::FT_LOST_AND_FOUND: - control = "inv_folder_lostandfound.tga"; - break; - case LLFolderType::FT_ANIMATION: - control = "inv_folder_animation.tga"; - break; - case LLFolderType::FT_GESTURE: - control = "inv_folder_gesture.tga"; - break; - default: - control = "inv_folder_plain_closed.tga"; - break; - } - return LLUI::getUIImage(control); + return getIcon(preferred_type); +} + +// static +LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) +{ + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); + /*case LLAssetType::AT_MESH: + control = "inv_folder_mesh.tga"; + break;*/ +} + +LLUIImagePtr LLFolderBridge::getOpenIcon() const +{ + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); + } BOOL LLFolderBridge::renameItem(const std::string& new_name) { - if(!isItemRenameable()) return FALSE; - LLInventoryModel* model = mInventoryPanel->getModel(); - if(!model) return FALSE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat && (cat->getName() != new_name)) - { - LLPointer new_cat = new LLViewerInventoryCategory(cat); - new_cat->rename(new_name); - new_cat->updateServer(FALSE); - model->updateCategory(new_cat); - model->notifyObservers(); - } + rename_category(getInventoryModel(), mUUID, new_name); + // return FALSE because we either notified observers (& therefore // rebuilt) or we didn't update. return FALSE; @@ -2475,14 +2382,15 @@ void LLFolderBridge::pasteLinkFromClipboard() void LLFolderBridge::staticFolderOptionsMenu() { - if (!sSelf) return; - sSelf->folderOptionsMenu(); + LLFolderBridge* selfp = sSelf.get(); + if (selfp) + { + selfp->folderOptionsMenu(); + } } void LLFolderBridge::folderOptionsMenu() { - menuentry_vec_t disabled_items; - // *TODO: Translate LLInventoryModel* model = getInventoryModel(); @@ -2511,7 +2419,12 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("IM All Contacts In Folder")); } } - + + if (!isItemRemovable()) + { + mDisabledItems.push_back(std::string("Delete")); + } + // wearables related functionality for folders. //is_wearable LLFindWearables is_wearable; @@ -2539,7 +2452,11 @@ void LLFolderBridge::folderOptionsMenu() } mItems.push_back(std::string("Take Off Items")); } - hide_context_entries(*mMenu, mItems, disabled_items); + LLMenuGL* menup = dynamic_cast(mMenu.get()); + if (menup) + { + hide_context_entries(*menup, mItems, mDisabledItems); + } } BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) @@ -2576,11 +2493,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // [/RLVa:KB] if (lost_and_found_id == mUUID) - { + { // This is the lost+found folder. mItems.push_back(std::string("Empty Lost And Found")); - } - + } + + // clear out old menu and folder pointers + mMenu.markDead(); + sSelf.markDead(); if (cof_id == mUUID) { mItems.push_back(std::string("Take Off Items")); @@ -2649,16 +2569,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mWearables=TRUE; } - mMenu = &menu; - sSelf = this; - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); - LLInventoryFetchDescendentsObserver::folder_ref_t folders; + uuid_vec_t folders; LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); if (category) { - folders.push_back(category->getUUID()); + folders.push_back(category->getUUID()); } + + mMenu = menu.getHandle(); + sSelf = getHandle(); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); fetch->fetchDescendents(folders); inc_busy_count(); if(fetch->isEverythingComplete()) @@ -4342,11 +4263,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) model->updateItem(new_item); model->notifyObservers(); - LLVOAvatar* avatar = gAgentAvatarp; - if( avatar ) + if (isAgentAvatarValid()) { - LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); - if( obj ) + LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() ); + if(obj) { LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 8806c466a..0279c850f 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -35,7 +35,7 @@ #include "llcallingcard.h" #include "llfloaterproperties.h" -#include "llfolderview.h" +#include "llfoldervieweventlistener.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" //#include "llinventoryview.h" @@ -302,7 +302,11 @@ public: virtual LLFolderType::EType getPreferredType() const; virtual LLUIImagePtr getIcon() const; + virtual LLUIImagePtr getOpenIcon() const; + static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); + virtual BOOL renameItem(const std::string& new_name); + virtual BOOL removeItem(); virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); @@ -322,6 +326,7 @@ public: static void createWearable(LLUUID parent_folder_id, LLWearableType::EType type); LLViewerInventoryCategory* getCategory() const; + LLHandle getHandle() { mHandle.bind(this); return mHandle; } protected: // menu callbacks @@ -350,15 +355,17 @@ protected: void modifyOutfit(BOOL append, BOOL replace = FALSE); menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items public: - static LLFolderBridge* sSelf; + static LLHandle sSelf; static void staticFolderOptionsMenu(); void folderOptionsMenu(); + private: BOOL mCallingCards; BOOL mWearables; - LLMenuGL* mMenu; + LLHandle mMenu; menuentry_vec_t mItems; menuentry_vec_t mDisabledItems; + LLRootHandle mHandle; }; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 5cd8e7a41..b8bf57300 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -106,7 +106,10 @@ void change_item_parent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - if (item->getParentUUID() != new_parent_id) + // + bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID()); + // + if(item->getParentUUID() != new_parent_id) { LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); @@ -117,6 +120,9 @@ void change_item_parent(LLInventoryModel* model, LLPointer new_item = new LLViewerInventoryItem(item); new_item->setParent(new_parent_id); + // + if(send_parent_update) + // new_item->updateParentOnServer(restamp); model->updateItem(new_item); model->notifyObservers(); @@ -153,6 +159,27 @@ void change_category_parent(LLInventoryModel* model, model->notifyObservers(); } + +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 new_cat = new LLViewerInventoryCategory(cat); + new_cat->rename(new_name); + new_cat->updateServer(FALSE); + model->updateCategory(new_cat); + + model->notifyObservers(); +} + class LLInventoryCollectAllItems : public LLInventoryCollectFunctor { public: @@ -308,6 +335,57 @@ BOOL get_can_item_be_worn(const LLUUID& id) return FALSE; } +BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id) +{ + if (!model) + { + return FALSE; + } + + // Can't delete an item that's in the library. + if(!model->isObjectDescendentOf(id, gInventory.getRootFolderID())) + { + return FALSE; + } + + // Disable delete from COF folder; have users explicitly choose "detach/take off", + // unless the item is not worn but in the COF (i.e. is bugged). + if (LLCOFMgr::instance().getIsProtectedCOFItem(id)) + { + if (get_is_item_worn(id)) + { + return FALSE; + } + } + + const LLInventoryObject *obj = model->getItem(id); + if (obj && obj->getIsLinkType()) + { + return TRUE; + } + if (get_is_item_worn(id)) + { + return FALSE; + } + return TRUE; +} + +BOOL get_is_category_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; +} ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 7cd944cad..7f7a26486 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -47,6 +47,11 @@ BOOL get_is_item_worn(const LLUUID& id); // Could this item be worn (correct type + not already being worn) BOOL get_can_item_be_worn(const LLUUID& id); +BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id); + +BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id); + +BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id); void change_item_parent(LLInventoryModel* model, LLViewerInventoryItem* item, @@ -57,6 +62,8 @@ void change_category_parent(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& new_parent_id, BOOL restamp); +void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); + // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 09678c6c7..5745b5704 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -50,6 +50,7 @@ #include "llviewerinventory.h" #include "llviewermessage.h" #include "llfoldertype.h" +#include "llviewerfoldertype.h" #include "llviewerwindow.h" #include "llviewerregion.h" #include "llappviewer.h" @@ -77,6 +78,8 @@ #include "process.h" #endif +const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; +const S32 MAX_FETCH_RETRIES = 10; BOOL LLInventoryModel::sBackgroundFetchActive = FALSE; BOOL LLInventoryModel::sAllFoldersFetched = FALSE; BOOL LLInventoryModel::sFullFetchStarted = FALSE; @@ -90,6 +93,7 @@ S16 LLInventoryModel::sBulkFetchCount = 0; // RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue static std::deque sFetchQueue; + // Increment this if the inventory contents change in a non-backwards-compatible way. // For viewers with link items support, former caches are incorrect. const S32 LLInventoryModel::sCurrentInvCacheVersion = 2; @@ -99,67 +103,8 @@ const S32 LLInventoryModel::sCurrentInvCacheVersion = 2; ///---------------------------------------------------------------------------- //BOOL decompress_file(const char* src_filename, const char* dst_filename); -const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; -const S32 MAX_FETCH_RETRIES = 10; -const char CACHE_FORMAT_STRING[] = "%s.inv"; -const char* NEW_CATEGORY_NAME = "New Folder"; -const char* NEW_CATEGORY_NAMES[LLFolderType::FT_COUNT] = -{ - "Textures", // FT_TEXTURE = 0, - "Sounds", // FT_SOUND = 1, - "Calling Cards", // FT_CALLINGCARD = 2, - "Landmarks", // FT_LANDMARK = 3, - "Scripts", // AT_SCRIPT (deprecated?) - "Clothing", // FT_CLOTHING = 5, - "Objects", // FT_OBJECT = 6, - "Notecards", // FT_NOTECARD = 7, - "New Folder", // FT_ROOT_INVENTORY = 8, - "Inventory", // AT_ROOT_CATEGORY - "Scripts", // FT_LSL_TEXT = 10, - "Scripts", // AT_LSL_BYTECODE - "Uncompressed Images", // AT_TEXTURE_TGA - "Body Parts", // FT_BODYPART = 13, - "Trash", // FT_TRASH = 14, - "Photo Album", // FT_SNAPSHOT_CATEGORY = 15, - "Lost And Found", // FT_LOST_AND_FOUND = 16, - "Uncompressed Sounds", // AT_SOUND_WAV - "Uncompressed Images", // AT_IMAGE_TGA - "Uncompressed Images", // AT_IMAGE_JPEG - "Animations", // FT_ANIMATION = 20, - "Gestures", // FT_GESTURE = 21, - "New Folder", // AT_SIMSTATE - "Favorites", // FT_FAVORITE = 23, - "New Folder", - "New Folder", - "New Ensemble", // FT_ENSEMBLE_START = 26, - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", - "New Ensemble", // FT_ENSEMBLE_END = 45, - "Current Outfit", // FT_CURRENT_OUTFIT = 46, - "New Outfit", // FT_OUTFIT = 47, - "My Outfits", // FT_MY_OUTFITS = 48, - "Mesh", // FT_MESH = 49, - "Inbox", // FT_INBOX = 50, - "Outbox", // FT_OUTBOX = 51, - "Basic Root" // FT_BASIC_ROOT = 52 -}; +const char CACHE_FORMAT_STRING[] = "%s.inv"; struct InventoryIDPtrLess { @@ -600,10 +545,10 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, { name.assign(pname); } - else if(preferred_type < (LLFolderType::EType)0 || preferred_type >= LLFolderType::FT_COUNT) - name.assign(NEW_CATEGORY_NAME); else - name.assign(NEW_CATEGORY_NAMES[preferred_type]); + { + name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type)); + } if ( callback && user_data ) //callback required for acked message. { @@ -996,10 +941,10 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) } } - /*else if (new_item->getType() == LLAssetType::AT_GESTURE) + else if (new_item->getType() == LLAssetType::AT_GESTURE) { mask |= LLInventoryObserver::GESTURE; - }*/ + } addChangedMask(mask, new_item->getUUID()); return mask; } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 0d3bdb930..e07beabd4 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -55,6 +55,7 @@ public: REMOVE = 8, // something deleted STRUCTURE = 16, // structural change, eg, item or folder moved CALLING_CARD = 32, // online, grant status, cancel, etc change + GESTURE = 64, ALL = 0xffffffff }; virtual ~LLInventoryObserver() {}; diff --git a/indra/newview/llpanelinventory.cpp b/indra/newview/llpanelinventory.cpp index 89eff24d2..c4dd9e00a 100644 --- a/indra/newview/llpanelinventory.cpp +++ b/indra/newview/llpanelinventory.cpp @@ -49,6 +49,7 @@ #include "lldarray.h" #include "llfontgl.h" #include "llassetstorage.h" +#include "llfoldervieweventlistener.h" #include "llinventory.h" #include "llinventorybridge.h" #include "llinventorydefines.h" diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 75aca382d..d09dbdb4c 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -44,6 +44,7 @@ #include "lldraghandle.h" #include "llfocusmgr.h" #include "llfolderview.h" +#include "llfoldervieweventlistener.h" #include "llinventory.h" #include "llinventoryfunctions.h" #include "llinventoryview.h" diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp new file mode 100644 index 000000000..85dbcc562 --- /dev/null +++ b/indra/newview/llviewerfoldertype.cpp @@ -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::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 name_vec_t; + name_vec_t mAllowedNames; + BOOL mIsQuiet; +}; + +class LLViewerFolderDictionary : public LLSingleton, + public LLDictionary +{ +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; +} diff --git a/indra/newview/llviewerfoldertype.h b/indra/newview/llviewerfoldertype.h new file mode 100644 index 000000000..f5938de61 --- /dev/null +++ b/indra/newview/llviewerfoldertype.h @@ -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 +#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