summaryrefslogtreecommitdiff
path: root/indra/newview/llinventorybridge.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llinventorybridge.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llinventorybridge.cpp6071
1 files changed, 3766 insertions, 2305 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index db7d4f4c8f..a047ed6fee 100644..100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1,185 +1,198 @@
-/**
+/**
* @file llinventorybridge.cpp
* @brief Implementation of the Inventory-Folder-View-Bridge classes.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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 <utility> // for std::pair<>
-
-#include "llfloaterinventory.h"
#include "llinventorybridge.h"
-#include "message.h"
+// external projects
+#include "lltransfersourceasset.h"
+#include "llavatarnamecache.h" // IDEVO
#include "llagent.h"
+#include "llagentcamera.h"
#include "llagentwearables.h"
-#include "llcallingcard.h"
-#include "llcheckboxctrl.h" // for radio buttons
+#include "llappearancemgr.h"
+#include "llattachmentsmgr.h"
+#include "llavataractions.h"
+#include "llfavoritesbar.h" // management of favorites folder
+#include "llfloateropenobject.h"
#include "llfloaterreg.h"
-#include "llradiogroup.h"
-#include "llspinctrl.h"
-#include "lltextbox.h"
-#include "llui.h"
-
-#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfoldertype.h"
-#include "llfloaterchat.h"
-#include "llfloatercustomize.h"
-#include "llfloaterproperties.h"
+#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
-#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llfriendcard.h"
-#include "llavataractions.h"
#include "llgesturemgr.h"
-#include "lliconctrl.h"
+#include "llgiveinventory.h"
+#include "llfloaterimcontainer.h"
+#include "llimview.h"
+#include "llclipboard.h"
+#include "llinventorydefines.h"
+#include "llinventoryfunctions.h"
+#include "llinventoryicon.h"
#include "llinventorymodel.h"
-#include "llinventoryclipboard.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventorypanel.h"
+#include "llmarketplacefunctions.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewscript.h"
-#include "llpreviewsound.h"
#include "llpreviewtexture.h"
-#include "llresmgr.h"
-#include "llscrollcontainer.h"
-#include "llimview.h"
+#include "llselectmgr.h"
+#include "llsidepanelappearance.h"
#include "lltooldraganddrop.h"
-#include "llviewertexturelist.h"
-#include "llviewerinventory.h"
+#include "lltrans.h"
+#include "llviewerassettype.h"
+#include "llviewerfoldertype.h"
+#include "llviewermenu.h"
+#include "llviewermessage.h"
#include "llviewerobjectlist.h"
-#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llwearable.h"
-#include "llwearablelist.h"
-#include "llviewermessage.h"
#include "llviewerregion.h"
+#include "llviewerwindow.h"
#include "llvoavatarself.h"
-#include "lltabcontainer.h"
-#include "lluictrlfactory.h"
-#include "llselectmgr.h"
-#include "llsidetray.h"
-#include "llfloateropenobject.h"
-#include "lltrans.h"
-#include "llappearancemgr.h"
+#include "llwearablelist.h"
+#include "llwearableitemslist.h"
+#include "lllandmarkactions.h"
+#include "llpanellandmarks.h"
+
+void copy_slurl_to_clipboard_callback_inv(const std::string& slurl);
+
+// Marketplace outbox current disabled
+#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1
+#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0
+#define BLOCK_WORN_ITEMS_IN_OUTBOX 1
+
+typedef std::pair<LLUUID, LLUUID> two_uuids_t;
+typedef std::list<two_uuids_t> two_uuids_list_t;
+
+const F32 SOUND_GAIN = 1.0f;
+
+struct LLMoveInv
+{
+ LLUUID mObjectID;
+ LLUUID mCategoryID;
+ two_uuids_list_t mMoveList;
+ void (*mCallback)(S32, void*);
+ void* mUserData;
+};
using namespace LLOldEvents;
-// Helpers
-// bug in busy count inc/dec right now, logic is complex... do we really need it?
-void inc_busy_count()
+// Function declarations
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
+bool confirm_attachment_rez(const LLSD& notification, const LLSD& response);
+void teleport_via_landmark(const LLUUID& asset_id);
+static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);
+static BOOL can_move_to_landmarks(LLInventoryItem* inv_item);
+static bool check_category(LLInventoryModel* model,
+ const LLUUID& cat_id,
+ LLInventoryPanel* active_panel,
+ LLInventoryFilter* filter);
+static bool check_item(const LLUUID& item_id,
+ LLInventoryPanel* active_panel,
+ LLInventoryFilter* filter);
+
+// Helper functions
+
+bool isAddAction(const std::string& action)
{
-// gViewerWindow->getWindow()->incBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
+ return ("wear" == action || "attach" == action || "activate" == action);
}
-void dec_busy_count()
+
+bool isRemoveAction(const std::string& action)
{
-// gViewerWindow->getWindow()->decBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
+ return ("take_off" == action || "detach" == action || "deactivate" == action);
}
-// Function declarations
-void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
-void remove_inventory_category_from_avatar(LLInventoryCategory* category);
-void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
-bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
-bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
-
-std::string ICON_NAME[ICON_NAME_COUNT] =
-{
- "Inv_Texture",
- "Inv_Sound",
- "Inv_CallingCard",
- "Inv_CallingCard",
- "Inv_Landmark",
- "Inv_Landmark",
- "Inv_Script",
- "Inv_Clothing",
- "Inv_Object",
- "Inv_Object",
- "Inv_Notecard",
- "Inv_Skin",
- "Inv_Snapshot",
-
- "Inv_BodyShape",
- "Inv_Skin",
- "Inv_Hair",
- "Inv_Eye",
- "Inv_Shirt",
- "Inv_Pants",
- "Inv_Shoe",
- "Inv_Socks",
- "Inv_Jacket",
- "Inv_Gloves",
- "Inv_Undershirt",
- "Inv_Underpants",
- "Inv_Skirt",
- "inv_item_alpha.tga",
- "inv_item_tattoo.tga",
-
- "Inv_Animation",
- "Inv_Gesture",
-
- "inv_item_linkitem.tga",
- "inv_item_linkfolder.tga"
-};
-
+bool isMarketplaceCopyAction(const std::string& action)
+{
+ return (("copy_to_outbox" == action) || ("move_to_outbox" == action));
+}
-// +=================================================+
-// | LLInventoryPanelObserver |
-// +=================================================+
-void LLInventoryPanelObserver::changed(U32 mask)
+bool isMarketplaceSendAction(const std::string& action)
{
- mIP->modelChanged(mask);
+ return ("send_to_marketplace" == action);
}
+// Used by LLFolderBridge as callback for directory fetching recursion
+class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids) : LLInventoryFetchDescendentsObserver(ids) {}
+ ~LLRightClickInventoryFetchDescendentsObserver() {}
+ virtual void execute(bool clear_observer = false);
+ virtual void done()
+ {
+ execute(true);
+ }
+};
+
+// Used by LLFolderBridge as callback for directory content items fetching
+class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver
+{
+public:
+ LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : LLInventoryFetchItemsObserver(ids) { };
+ ~LLRightClickInventoryFetchObserver() {}
+ void execute(bool clear_observer = false)
+ {
+ if (clear_observer)
+ {
+ gInventory.removeObserver(this);
+ delete this;
+ }
+ // we've downloaded all the items, so repaint the dialog
+ LLFolderBridge::staticFolderOptionsMenu();
+ }
+ virtual void done()
+ {
+ execute(true);
+ }
+};
// +=================================================+
// | LLInvFVBridge |
// +=================================================+
-LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
-mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
+LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid) :
+ mUUID(uuid),
+ mRoot(root),
+ mInvType(LLInventoryType::IT_NONE),
+ mIsLink(FALSE),
+ LLFolderViewModelItemInventory(inventory->getRootViewModel())
{
- mInventoryPanel = inventory->getHandle();
+ mInventoryPanel = inventory->getInventoryPanelHandle();
+ const LLInventoryObject* obj = getInventoryObject();
+ mIsLink = obj && obj->getIsLinkType();
}
const std::string& LLInvFVBridge::getName() const
{
- LLInventoryObject* obj = getInventoryObject();
+ const LLInventoryObject* obj = getInventoryObject();
if(obj)
{
return obj->getName();
@@ -189,71 +202,52 @@ const std::string& LLInvFVBridge::getName() const
const std::string& LLInvFVBridge::getDisplayName() const
{
- return getName();
+ if(mDisplayName.empty())
+ {
+ buildDisplayName();
+ }
+
+ return mDisplayName;
}
// Folders have full perms
PermissionMask LLInvFVBridge::getPermissionMask() const
{
-
return PERM_ALL;
}
// virtual
-LLAssetType::EType LLInvFVBridge::getPreferredType() const
+LLFolderType::EType LLInvFVBridge::getPreferredType() const
{
- return LLAssetType::AT_NONE;
+ return LLFolderType::FT_NONE;
}
// Folders don't have creation dates.
time_t LLInvFVBridge::getCreationDate() const
{
- return 0;
+ LLInventoryObject* objectp = getInventoryObject();
+ if (objectp)
+ {
+ return objectp->getCreationDate();
+ }
+ return (time_t)0;
}
-// Can be destoryed (or moved to trash)
-BOOL LLInvFVBridge::isItemRemovable()
+void LLInvFVBridge::setCreationDate(time_t creation_date_utc)
{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ LLInventoryObject* objectp = getInventoryObject();
+ if (objectp)
{
- return TRUE;
+ objectp->setCreationDate(creation_date_utc);
}
- return FALSE;
}
-// Sends an update to all link items that point to the base item.
-void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- if (itemp->getIsLinkType())
- {
- return;
- }
-
- LLInventoryModel::item_array_t item_array;
- model->collectLinkedItems(item_id, item_array);
- for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
- iter != item_array.end();
- iter++)
- {
- LLViewerInventoryItem *linked_item = (*iter);
- if (linked_item->getUUID() == item_id) continue;
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
- new_item->rename(new_name);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
- // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
- }
- model->notifyObservers();
+// Can be destroyed (or moved to trash)
+BOOL LLInvFVBridge::isItemRemovable() const
+{
+ return get_is_item_removable(getInventoryModel(), mUUID);
}
// Can be moved to another folder
@@ -262,24 +256,53 @@ BOOL LLInvFVBridge::isItemMovable() const
return TRUE;
}
+BOOL LLInvFVBridge::isLink() const
+{
+ return mIsLink;
+}
+
+BOOL LLInvFVBridge::isLibraryItem() const
+{
+ return gInventory.isObjectDescendentOf(getUUID(),gInventory.getLibraryRootFolderID());
+}
+
/*virtual*/
/**
* @brief Adds this item into clipboard storage
*/
-void LLInvFVBridge::cutToClipboard()
+BOOL LLInvFVBridge::cutToClipboard() const
{
- if(isItemMovable())
+ const LLInventoryObject* obj = gInventory.getObject(mUUID);
+ if (obj && isItemMovable() && isItemRemovable())
{
- LLInventoryClipboard::instance().cut(mUUID);
+ LLClipboard::instance().setCutMode(true);
+ return LLClipboard::instance().addToClipboard(mUUID);
}
+ return FALSE;
}
+
+BOOL LLInvFVBridge::copyToClipboard() const
+{
+ const LLInventoryObject* obj = gInventory.getObject(mUUID);
+ if (obj && isItemCopyable())
+ {
+ return LLClipboard::instance().addToClipboard(mUUID);
+ }
+ return FALSE;
+}
+
// *TODO: make sure this does the right thing
void LLInvFVBridge::showProperties()
{
- LLFloaterReg::showInstance("properties", mUUID);
+ show_item_profile(mUUID);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
}
-void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
+void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)
{
// Deactivate gestures when moving them into Trash
LLInvFVBridge* bridge;
@@ -288,34 +311,34 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
LLViewerInventoryCategory* cat = NULL;
LLInventoryModel::cat_array_t descendent_categories;
LLInventoryModel::item_array_t descendent_items;
- S32 count = batch.count();
+ S32 count = batch.size();
S32 i,j;
for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
+ {
+ bridge = (LLInvFVBridge*)(batch[i]);
if(!bridge || !bridge->isItemRemovable()) continue;
item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
if (item)
{
if(LLAssetType::AT_GESTURE == item->getType())
{
- LLGestureManager::instance().deactivateGesture(item->getUUID());
+ LLGestureMgr::instance().deactivateGesture(item->getUUID());
}
}
}
for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
+ {
+ bridge = (LLInvFVBridge*)(batch[i]);
if(!bridge || !bridge->isItemRemovable()) continue;
cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
if (cat)
{
gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
- for (j=0; j<descendent_items.count(); j++)
+ for (j=0; j<descendent_items.size(); j++)
{
if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
{
- LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
+ LLGestureMgr::instance().deactivateGesture(descendent_items[j]->getUUID());
}
}
}
@@ -323,7 +346,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
removeBatchNoCheck(batch);
}
-void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
+void LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch)
{
// this method moves a bunch of items and folders to the trash. As
// per design guidelines for the inventory model, the message is
@@ -334,24 +357,38 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
LLInventoryModel* model = getInventoryModel();
if(!model) return;
LLMessageSystem* msg = gMessageSystem;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLViewerInventoryItem* item = NULL;
- LLViewerInventoryCategory* cat = NULL;
- std::vector<LLUUID> move_ids;
+ uuid_vec_t move_ids;
LLInventoryModel::update_map_t update;
bool start_new_message = true;
- S32 count = batch.count();
+ S32 count = batch.size();
S32 i;
+
+ // first, hide any 'preview' floaters that correspond to the items
+ // being deleted.
for(i = 0; i < count; ++i)
{
- bridge = (LLInvFVBridge*)(batch.get(i));
+ bridge = (LLInvFVBridge*)(batch[i]);
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
+ if(item)
+ {
+ LLPreview::hide(item->getUUID());
+ }
+ }
+
+ // do the inventory move to trash
+
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch[i]);
if(!bridge || !bridge->isItemRemovable()) continue;
item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
if(item)
{
if(item->getParentUUID() == trash_id) continue;
move_ids.push_back(item->getUUID());
- LLPreview::hide(item->getUUID());
--update[item->getParentUUID()];
++update[trash_id];
if(start_new_message)
@@ -383,11 +420,12 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
gInventory.accountForUpdate(update);
update.clear();
}
+
for(i = 0; i < count; ++i)
{
- bridge = (LLInvFVBridge*)(batch.get(i));
+ bridge = (LLInvFVBridge*)(batch[i]);
if(!bridge || !bridge->isItemRemovable()) continue;
- cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
if(cat)
{
if(cat->getParentUUID() == trash_id) continue;
@@ -422,11 +460,16 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
}
// move everything.
- std::vector<LLUUID>::iterator it = move_ids.begin();
- std::vector<LLUUID>::iterator end = move_ids.end();
+ uuid_vec_t::iterator it = move_ids.begin();
+ uuid_vec_t::iterator end = move_ids.end();
for(; it != end; ++it)
{
gInventory.moveObject((*it), trash_id);
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if (item)
+ {
+ model->updateItem(item);
+ }
}
// notify inventory observers.
@@ -435,7 +478,8 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
BOOL LLInvFVBridge::isClipboardPasteable() const
{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ // Return FALSE on degenerated cases: empty clipboard, no inventory, no agent
+ if (!LLClipboard::instance().hasContents() || !isAgentInventory())
{
return FALSE;
}
@@ -445,29 +489,36 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
return FALSE;
}
- const LLUUID &agent_id = gAgent.getID();
+ // In cut mode, whatever is on the clipboard is always pastable
+ if (LLClipboard::instance().isCutMode())
+ {
+ return TRUE;
+ }
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
+ // In normal mode, we need to check each element of the clipboard to know if we can paste or not
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+ S32 count = objects.size();
for(S32 i = 0; i < count; i++)
{
- const LLUUID &item_id = objects.get(i);
+ const LLUUID &item_id = objects.at(i);
- // Can't paste folders
+ // Folders are pastable if all items in there are copyable
const LLInventoryCategory *cat = model->getCategory(item_id);
if (cat)
{
+ LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, item_id);
+ if (!cat_br.isItemCopyable())
return FALSE;
+ // Skip to the next item in the clipboard
+ continue;
}
- const LLInventoryItem *item = model->getItem(item_id);
- if (item)
+ // Each item must be copyable to be pastable
+ LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id);
+ if (!item_br.isItemCopyable())
{
- if (!item->getPermissions().allowCopyBy(agent_id))
- {
- return FALSE;
- }
+ return FALSE;
}
}
return TRUE;
@@ -475,7 +526,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ if (!LLClipboard::instance().hasContents() || !isAgentInventory())
{
return FALSE;
}
@@ -485,12 +536,12 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return FALSE;
}
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+ S32 count = objects.size();
for(S32 i = 0; i < count; i++)
{
- const LLInventoryItem *item = model->getItem(objects.get(i));
+ const LLInventoryItem *item = model->getItem(objects.at(i));
if (item)
{
if (!LLAssetType::lookupCanLink(item->getActualType()))
@@ -498,8 +549,8 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return FALSE;
}
}
- const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
- if (cat && !LLAssetType::lookupCanLink(cat->getPreferredType()))
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.at(i));
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
return FALSE;
}
@@ -507,122 +558,362 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return TRUE;
}
-void hideContextEntries(LLMenuGL& menu,
- const std::vector<std::string> &entries_to_show,
- const std::vector<std::string> &disabled_entries)
+void disable_context_entries_if_present(LLMenuGL& menu,
+ const menuentry_vec_t &disabled_entries)
+{
+ const LLView::child_list_t *list = menu.getChildList();
+ for (LLView::child_list_t::const_iterator itor = list->begin();
+ itor != list->end();
+ ++itor)
+ {
+ LLView *menu_item = (*itor);
+ std::string name = menu_item->getName();
+
+ // descend into split menus:
+ LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item);
+ if ((name == "More") && branchp)
+ {
+ disable_context_entries_if_present(*branchp->getBranch(), disabled_entries);
+ }
+
+ bool found = false;
+ menuentry_vec_t::const_iterator itor2;
+ for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ menu_item->setVisible(TRUE);
+ // A bit of a hack so we can remember that some UI element explicitly set this to be visible
+ // so that some other UI element from multi-select doesn't later set this invisible.
+ menu_item->pushVisible(TRUE);
+
+ menu_item->setEnabled(FALSE);
+ }
+ }
+}
+void hide_context_entries(LLMenuGL& menu,
+ const menuentry_vec_t &entries_to_show,
+ const menuentry_vec_t &disabled_entries)
{
const LLView::child_list_t *list = menu.getChildList();
- LLView::child_list_t::const_iterator itor;
- for (itor = list->begin(); itor != list->end(); ++itor)
+ // For removing double separators or leading separator. Start at true so that
+ // if the first element is a separator, it will not be shown.
+ bool is_previous_entry_separator = true;
+
+ for (LLView::child_list_t::const_iterator itor = list->begin();
+ itor != list->end();
+ ++itor)
{
- std::string name = (*itor)->getName();
+ LLView *menu_item = (*itor);
+ std::string name = menu_item->getName();
// descend into split menus:
- LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
+ LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item);
if ((name == "More") && branchp)
{
- hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries);
+ hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
}
-
-
+
bool found = false;
- std::vector<std::string>::const_iterator itor2;
+ menuentry_vec_t::const_iterator itor2;
for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
{
if (*itor2 == name)
{
found = true;
+ break;
}
}
+
+ // Don't allow multiple separators in a row (e.g. such as if there are no items
+ // between two separators).
+ if (found)
+ {
+ const bool is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL);
+ found = !(is_entry_separator && is_previous_entry_separator);
+ is_previous_entry_separator = is_entry_separator;
+ }
+
if (!found)
{
- (*itor)->setVisible(FALSE);
+ if (!menu_item->getLastVisible())
+ {
+ menu_item->setVisible(FALSE);
+ }
+
+ menu_item->setEnabled(FALSE);
}
else
{
- for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+ menu_item->setVisible(TRUE);
+ // A bit of a hack so we can remember that some UI element explicitly set this to be visible
+ // so that some other UI element from multi-select doesn't later set this invisible.
+ menu_item->pushVisible(TRUE);
+
+ bool enabled = (menu_item->getEnabled() == TRUE);
+ for (itor2 = disabled_entries.begin(); enabled && (itor2 != disabled_entries.end()); ++itor2)
{
- if (*itor2 == name)
- {
- (*itor)->setEnabled(FALSE);
- }
+ enabled &= (*itor2 != name);
}
+
+ menu_item->setEnabled(enabled);
}
}
}
// Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
- std::vector<std::string> &items,
- std::vector<std::string> &disabled_items, U32 flags)
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ menuentry_vec_t &items,
+ menuentry_vec_t &disabled_items, U32 flags)
{
- items.push_back(std::string("Rename"));
- if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Rename"));
- }
+ const LLInventoryObject *obj = getInventoryObject();
- if (show_asset_id)
+ if (obj)
{
- items.push_back(std::string("Copy Asset UUID"));
- if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
- || (flags & FIRST_SELECTED_ITEM) == 0)
+ if (obj->getIsLinkType())
{
- disabled_items.push_back(std::string("Copy Asset UUID"));
+ items.push_back(std::string("Find Original"));
+ if (isLinkedObjectMissing())
+ {
+ disabled_items.push_back(std::string("Find Original"));
+ }
}
- }
+ else
+ {
+ if (LLAssetType::lookupCanLink(obj->getType()))
+ {
+ items.push_back(std::string("Find Links"));
+ }
- items.push_back(std::string("Copy Separator"));
+ if (!isInboxFolder())
+ {
+ items.push_back(std::string("Rename"));
+ if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
+ }
+ }
+
+ if (show_asset_id)
+ {
+ items.push_back(std::string("Copy Asset UUID"));
- items.push_back(std::string("Copy"));
- if (!isItemCopyable())
- {
- disabled_items.push_back(std::string("Copy"));
+ bool is_asset_knowable = false;
+
+ LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID);
+ if (inv_item)
+ {
+ is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType());
+ }
+ if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308
+ || (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Copy Asset UUID"));
+ }
+ }
+ items.push_back(std::string("Copy Separator"));
+
+ items.push_back(std::string("Copy"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Copy"));
+ }
+
+ items.push_back(std::string("Cut"));
+ if (!isItemMovable() || !isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Cut"));
+ }
+
+ if (canListOnMarketplace())
+ {
+ items.push_back(std::string("Marketplace Separator"));
+
+ items.push_back(std::string("Merchant Copy"));
+ if (!canListOnMarketplaceNow())
+ {
+ disabled_items.push_back(std::string("Merchant Copy"));
+ }
+ }
+ }
}
- items.push_back(std::string("Paste"));
- if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ // Don't allow items to be pasted directly into the COF or the inbox/outbox
+ if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder())
+ {
+ items.push_back(std::string("Paste"));
+ }
+ if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0))
{
disabled_items.push_back(std::string("Paste"));
}
- items.push_back(std::string("Paste As Link"));
- if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+ if (gSavedSettings.getBOOL("InventoryLinking"))
{
- disabled_items.push_back(std::string("Paste As Link"));
+ items.push_back(std::string("Paste As Link"));
+ if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste As Link"));
+ }
}
+
items.push_back(std::string("Paste Separator"));
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
+ addDeleteContextMenuOptions(items, disabled_items);
+
+ // If multiple items are selected, disable properties (if it exists).
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
{
- disabled_items.push_back(std::string("Delete"));
+ disabled_items.push_back(std::string("Properties"));
}
}
void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
+ LL_DEBUGS() << "LLInvFVBridge::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ if(isItemInTrash())
{
- items.push_back(std::string("PurgeItem"));
- if (!isItemRemovable())
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
+ }
+ else
+ {
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+
+ addOpenRightClickMenuOption(items);
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+bool get_selection_item_uuids(LLFolderView::selected_items_t& selected_items, uuid_vec_t& ids)
+{
+ uuid_vec_t results;
+ S32 non_item = 0;
+ for(LLFolderView::selected_items_t::iterator it = selected_items.begin(); it != selected_items.end(); ++it)
+ {
+ LLItemBridge *view_model = dynamic_cast<LLItemBridge *>((*it)->getViewModelItem());
+
+ if(view_model && view_model->getUUID().notNull())
+ {
+ results.push_back(view_model->getUUID());
+ }
+ else
+ {
+ non_item++;
+ }
+ }
+ if (non_item == 0)
+ {
+ ids = results;
+ return true;
+ }
+ return false;
+}
+
+void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items,
+ menuentry_vec_t &disabled_items)
+{
+ const LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ items.push_back(std::string("Find Original"));
+ if (isLinkedObjectMissing())
{
- disabled_items.push_back(std::string("PurgeItem"));
+ disabled_items.push_back(std::string("Find Original"));
}
- items.push_back(std::string("RestoreItem"));
+ }
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+ items.push_back(std::string("Restore Item"));
+}
+
+void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
+ menuentry_vec_t &disabled_items)
+{
+
+ const LLInventoryObject *obj = getInventoryObject();
+
+ // Don't allow delete as a direct option from COF folder.
+ if (obj && obj->getIsLinkType() && isCOFFolder() && get_is_item_worn(mUUID))
+ {
+ return;
+ }
+
+ // "Remove link" and "Delete" are the same operation.
+ if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
+ {
+ items.push_back(std::string("Remove Link"));
}
else
{
+ items.push_back(std::string("Delete"));
+ }
+
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+}
+
+void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items)
+{
+ const LLInventoryObject *obj = getInventoryObject();
+ const BOOL is_link = (obj && obj->getIsLinkType());
+
+ if (is_link)
+ items.push_back(std::string("Open Original"));
+ else
items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
+}
- getClipboardEntries(true, items, disabled_items, flags);
+void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags,
+ menuentry_vec_t &items,
+ menuentry_vec_t &disabled_items)
+{
+ items.push_back(std::string("Rename"));
+ items.push_back(std::string("Delete"));
+
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
}
- hideContextEntries(menu, items, disabled_items);
+
+#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
+ if (isOutboxFolderDirectParent())
+ {
+ items.push_back(std::string("Marketplace Separator"));
+ items.push_back(std::string("Marketplace Send"));
+
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Marketplace Send"));
+ }
+ }
+#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
}
// *TODO: remove this
@@ -634,18 +925,18 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
if(obj)
{
- *type = LLAssetType::lookupDragAndDropType(obj->getActualType());
+ *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
if(*type == DAD_NONE)
{
return FALSE;
}
-
+
*id = obj->getUUID();
- //object_ids.put(obj->getUUID());
+ //object_ids.push_back(obj->getUUID());
if (*type == DAD_CATEGORY)
{
- gInventory.startBackgroundFetch(obj->getUUID());
+ LLInventoryModelBackgroundFetch::instance().start(obj->getUUID());
}
rv = TRUE;
@@ -667,33 +958,53 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const
LLInventoryModel* LLInvFVBridge::getInventoryModel() const
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
return panel ? panel->getModel() : NULL;
}
-BOOL LLInvFVBridge::isInTrash() const
+LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const
+{
+ LLInventoryPanel* panel = mInventoryPanel.get();
+ return panel ? &(panel->getFilter()) : NULL;
+}
+
+BOOL LLInvFVBridge::isItemInTrash() const
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return model->isObjectDescendentOf(mUUID, trash_id);
}
BOOL LLInvFVBridge::isLinkedObjectInTrash() const
{
- if (isInTrash()) return TRUE;
+ if (isItemInTrash()) return TRUE;
const LLInventoryObject *obj = getInventoryObject();
if (obj && obj->getIsLinkType())
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
}
return FALSE;
}
+BOOL LLInvFVBridge::isLinkedObjectMissing() const
+{
+ const LLInventoryObject *obj = getInventoryObject();
+ if (!obj)
+ {
+ return TRUE;
+ }
+ if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
BOOL LLInvFVBridge::isAgentInventory() const
{
const LLInventoryModel* model = getInventoryModel();
@@ -704,14 +1015,54 @@ BOOL LLInvFVBridge::isAgentInventory() const
BOOL LLInvFVBridge::isCOFFolder() const
{
- const LLInventoryModel* model = getInventoryModel();
- if(!model) return TRUE;
- const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
+ return LLAppearanceMgr::instance().getIsInCOF(mUUID);
+}
+
+BOOL LLInvFVBridge::isInboxFolder() const
+{
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false);
+
+ if (inbox_id.isNull())
{
- return TRUE;
+ return FALSE;
}
- return FALSE;
+
+ return gInventory.isObjectDescendentOf(mUUID, inbox_id);
+}
+
+BOOL LLInvFVBridge::isOutboxFolder() const
+{
+ const LLUUID outbox_id = getOutboxFolder();
+
+ if (outbox_id.isNull())
+ {
+ return FALSE;
+ }
+
+ return gInventory.isObjectDescendentOf(mUUID, outbox_id);
+}
+
+BOOL LLInvFVBridge::isOutboxFolderDirectParent() const
+{
+ BOOL outbox_is_parent = FALSE;
+
+ const LLInventoryCategory *cat = gInventory.getCategory(mUUID);
+
+ if (cat)
+ {
+ const LLUUID outbox_id = getOutboxFolder();
+
+ outbox_is_parent = (outbox_id.notNull() && (outbox_id == cat->getParentUUID()));
+ }
+
+ return outbox_is_parent;
+}
+
+const LLUUID LLInvFVBridge::getOutboxFolder() const
+{
+ const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+
+ return outbox_id;
}
BOOL LLInvFVBridge::isItemPermissive() const
@@ -722,64 +1073,27 @@ BOOL LLInvFVBridge::isItemPermissive() const
// static
void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
LLViewerInventoryItem* item,
- const LLUUID& new_parent,
+ const LLUUID& new_parent_id,
BOOL restamp)
{
- if(item->getParentUUID() != new_parent)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->setParent(new_parent);
- new_item->updateParentOnServer(restamp);
- model->updateItem(new_item);
- model->notifyObservers();
- }
+ model->changeItemParent(item, new_parent_id, restamp);
}
// static
void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
- const LLUUID& new_parent,
+ const LLUUID& new_parent_id,
BOOL restamp)
{
- if(cat->getParentUUID() != new_parent)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->setParent(new_parent);
- new_cat->updateParentOnServer(restamp);
- model->updateCategory(new_cat);
- model->notifyObservers();
- }
-}
-
-
-const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
-{
- const std::string rv= LLInventoryType::lookup(inv_type);
- if(rv.empty())
- {
- return std::string("<invalid>");
- }
- return rv;
+ model->changeCategoryParent(cat, new_parent_id, restamp);
}
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
+ LLFolderViewModelInventory* view_model,
+ LLFolderView* root,
const LLUUID& uuid,
U32 flags)
{
@@ -789,112 +1103,121 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_TEXTURE:
if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLTextureBridge(inventory, uuid, inv_type);
+ new_listener = new LLTextureBridge(inventory, root, uuid, inv_type);
break;
case LLAssetType::AT_SOUND:
if(!(inv_type == LLInventoryType::IT_SOUND))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLSoundBridge(inventory, uuid);
+ new_listener = new LLSoundBridge(inventory, root, uuid);
break;
case LLAssetType::AT_LANDMARK:
if(!(inv_type == LLInventoryType::IT_LANDMARK))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLLandmarkBridge(inventory, uuid, flags);
+ new_listener = new LLLandmarkBridge(inventory, root, uuid, flags);
break;
-
+
case LLAssetType::AT_CALLINGCARD:
if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLCallingCardBridge(inventory, uuid);
+ new_listener = new LLCallingCardBridge(inventory, root, uuid);
break;
case LLAssetType::AT_SCRIPT:
if(!(inv_type == LLInventoryType::IT_LSL))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLScriptBridge(inventory, uuid);
+ new_listener = new LLItemBridge(inventory, root, uuid);
break;
case LLAssetType::AT_OBJECT:
if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
+ new_listener = new LLObjectBridge(inventory, root, uuid, inv_type, flags);
break;
case LLAssetType::AT_NOTECARD:
if(!(inv_type == LLInventoryType::IT_NOTECARD))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLNotecardBridge(inventory, uuid);
+ new_listener = new LLNotecardBridge(inventory, root, uuid);
break;
case LLAssetType::AT_ANIMATION:
if(!(inv_type == LLInventoryType::IT_ANIMATION))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLAnimationBridge(inventory, uuid);
+ new_listener = new LLAnimationBridge(inventory, root, uuid);
break;
case LLAssetType::AT_GESTURE:
if(!(inv_type == LLInventoryType::IT_GESTURE))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLGestureBridge(inventory, uuid);
+ new_listener = new LLGestureBridge(inventory, root, uuid);
break;
case LLAssetType::AT_LSL_TEXT:
if(!(inv_type == LLInventoryType::IT_LSL))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLLSLTextBridge(inventory, uuid);
+ new_listener = new LLLSLTextBridge(inventory, root, uuid);
break;
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
if(!(inv_type == LLInventoryType::IT_WEARABLE))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
}
- new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
+ new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, LLWearableType::inventoryFlagsToWearableType(flags));
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);
+ new_listener = new LLLinkFolderBridge(inventory, root, uuid);
break;
}
- new_listener = new LLFolderBridge(inventory, uuid);
+ new_listener = new LLFolderBridge(inventory, root, 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);
+ new_listener = new LLLinkItemBridge(inventory, root, uuid);
break;
+ case LLAssetType::AT_MESH:
+ if(!(inv_type == LLInventoryType::IT_MESH))
+ {
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
+ }
+ new_listener = new LLMeshBridge(inventory, root, uuid);
+ break;
+
+ case LLAssetType::AT_IMAGE_TGA:
+ case LLAssetType::AT_IMAGE_JPEG:
+ //LL_WARNS() << LLAssetType::lookup(asset_type) << " asset type is unhandled for uuid " << uuid << LL_ENDL;
+ break;
+
default:
- llinfos << "Unhandled asset type (llassetstorage.h): "
- << (S32)asset_type << llendl;
+ LL_INFOS() << "Unhandled asset type (llassetstorage.h): "
+ << (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << LL_ENDL;
break;
}
@@ -908,49 +1231,194 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
{
- LLInventoryCategory* cat = model->getCategory(uuid);
- if (cat)
- {
- model->purgeDescendentsOf(uuid);
- model->notifyObservers();
- }
LLInventoryObject* obj = model->getObject(uuid);
if (obj)
{
- model->purgeObject(uuid);
- model->notifyObservers();
+ remove_inventory_object(uuid, NULL);
+ }
+}
+
+bool LLInvFVBridge::canShare() const
+{
+ bool can_share = false;
+
+ if (isAgentInventory())
+ {
+ const LLInventoryModel* model = getInventoryModel();
+ if (model)
+ {
+ const LLViewerInventoryItem *item = model->getItem(mUUID);
+ if (item)
+ {
+ if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item))
+ {
+ can_share = LLGiveInventory::isInventoryGiveAcceptable(item);
+ }
+ }
+ else
+ {
+ // Categories can be given.
+ can_share = (model->getCategory(mUUID) != NULL);
+ }
+ }
+ }
+
+ return can_share;
+}
+
+bool LLInvFVBridge::canListOnMarketplace() const
+{
+#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+
+ LLInventoryModel * model = getInventoryModel();
+
+ const LLViewerInventoryCategory * cat = model->getCategory(mUUID);
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return false;
+ }
+
+ if (!isAgentInventory())
+ {
+ return false;
+ }
+
+ if (getOutboxFolder().isNull())
+ {
+ return false;
+ }
+
+ if (isInboxFolder() || isOutboxFolder())
+ {
+ return false;
}
+
+ LLViewerInventoryItem * item = model->getItem(mUUID);
+ if (item)
+ {
+ if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+ {
+ return false;
+ }
+
+ if (LLAssetType::AT_CALLINGCARD == item->getType())
+ {
+ return false;
+ }
+ }
+
+ return true;
+
+#else
+ return false;
+#endif
}
+bool LLInvFVBridge::canListOnMarketplaceNow() const
+{
+#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU
+
+ bool can_list = true;
+
+ // Do not allow listing while import is in progress
+ if (LLMarketplaceInventoryImporter::instanceExists())
+ {
+ can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress();
+ }
+
+ const LLInventoryObject* obj = getInventoryObject();
+ can_list &= (obj != NULL);
+
+ if (can_list)
+ {
+ const LLUUID& object_id = obj->getLinkedUUID();
+ can_list = object_id.notNull();
+
+ if (can_list)
+ {
+ LLFolderViewFolder * object_folderp = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL;
+ if (object_folderp)
+ {
+ can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading();
+ }
+ }
+
+ if (can_list)
+ {
+ // Get outbox id
+ const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+ LLFolderViewItem * outbox_itemp = mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL;
+
+ if (outbox_itemp)
+ {
+ MASK mask = 0x0;
+ BOOL drop = FALSE;
+ EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
+ void * cargo_data = (void *) obj;
+ std::string tooltip_msg;
+
+ can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+ }
+ }
+ }
+
+ return can_list;
+
+#else
+ return false;
+#endif
+}
+
+LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const
+{
+ if (gInventory.isObjectDescendentOf(getUUID(), gInventory.getRootFolderID()))
+ {
+ return LLToolDragAndDrop::SOURCE_AGENT;
+ }
+ else if (gInventory.isObjectDescendentOf(getUUID(), gInventory.getLibraryRootFolderID()))
+ {
+ return LLToolDragAndDrop::SOURCE_LIBRARY;
+ }
+
+ return LLToolDragAndDrop::SOURCE_VIEWER;
+}
+
+
+
// +=================================================+
// | InventoryFVBridgeBuilder |
// +=================================================+
-LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+LLInvFVBridge* LLInventoryFolderViewModelBuilder::createBridge(LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
+ LLFolderViewModelInventory* view_model,
+ LLFolderView* root,
const LLUUID& uuid,
U32 flags /* = 0x00 */) const
{
return LLInvFVBridge::createBridge(asset_type,
- actual_asset_type,
- inv_type,
- inventory,
- uuid,
- flags);
+ actual_asset_type,
+ inv_type,
+ inventory,
+ view_model,
+ root,
+ uuid,
+ flags);
}
// +=================================================+
// | LLItemBridge |
// +=================================================+
-void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
{
if ("goto" == action)
{
- gotoItem(folder);
+ gotoItem();
}
- if ("open" == action)
+
+ if ("open" == action || "open_original" == action)
{
openItem();
return;
@@ -978,13 +1446,19 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
else if ("copy_uuid" == action)
{
// Single item only
- LLInventoryItem* item = model->getItem(mUUID);
+ LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
if(!item) return;
- LLUUID asset_id = item->getAssetUUID();
+ LLUUID asset_id = item->getProtectedAssetUUID();
std::string buffer;
asset_id.toString(buffer);
- gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
+ gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer));
+ return;
+ }
+ else if ("cut" == action)
+ {
+ cutToClipboard();
+ gInventory.removeObject(mUUID);
return;
}
else if ("copy" == action)
@@ -994,14 +1468,13 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
}
else if ("paste" == action)
{
- // Single item only
LLInventoryItem* itemp = model->getItem(mUUID);
if (!itemp) return;
- LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID());
if (!folder_view_itemp) return;
- folder_view_itemp->getListener()->pasteFromClipboard();
+ folder_view_itemp->getViewModelItem()->pasteFromClipboard();
return;
}
else if ("paste_link" == action)
@@ -1010,30 +1483,96 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
LLInventoryItem* itemp = model->getItem(mUUID);
if (!itemp) return;
- LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID());
if (!folder_view_itemp) return;
- folder_view_itemp->getListener()->pasteLinkFromClipboard();
+ folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();
return;
}
+ else if (isMarketplaceCopyAction(action))
+ {
+ LL_INFOS() << "Copy item to marketplace action!" << LL_ENDL;
+
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+ copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());
+ }
+ else if ("copy_slurl" == action)
+ {
+ LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
+ if(item)
+ {
+ LLUUID asset_id = item->getAssetUUID();
+ LLLandmark* landmark = gLandmarkList.getAsset(asset_id);
+ if (landmark)
+ {
+ LLVector3d global_pos;
+ landmark->getGlobalPos(global_pos);
+ LLLandmarkActions::getSLURLfromPosGlobal(global_pos, &copy_slurl_to_clipboard_callback_inv, true);
+ }
+ }
+ }
+ else if ("show_on_map" == action)
+ {
+ doActionOnCurSelectedLandmark(boost::bind(&LLItemBridge::doShowOnMap, this, _1));
+ }
+}
+
+void LLItemBridge::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)
+{
+ LLViewerInventoryItem* cur_item = getItem();
+ if(cur_item && cur_item->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getUUID(), cb);
+ if (landmark)
+ {
+ cb(landmark);
+ }
+ }
+}
+
+void LLItemBridge::doShowOnMap(LLLandmark* landmark)
+{
+ LLVector3d landmark_global_pos;
+ // landmark has already been tested for NULL by calling routine
+ if (landmark->getGlobalPos(landmark_global_pos))
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
+ {
+ worldmap_instance->trackLocation(landmark_global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+}
+
+void copy_slurl_to_clipboard_callback_inv(const std::string& slurl)
+{
+ gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotificationsUtil::add("CopySLURL", args);
}
void LLItemBridge::selectItem()
{
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
- if(item && !item->isComplete())
+ LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
+ if(item && !item->isFinished())
{
- item->fetchFromServer();
+ //item->fetchFromServer();
+ LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
}
}
void LLItemBridge::restoreItem()
{
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
if(item)
{
LLInventoryModel* model = getInventoryModel();
- const LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
// do not restamp on restore.
LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
}
@@ -1041,7 +1580,10 @@ void LLItemBridge::restoreItem()
void LLItemBridge::restoreToWorld()
{
- LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem();
+ //Similar functionality to the drag and drop rez logic
+ bool remove_from_inventory = false;
+
+ LLViewerInventoryItem* itemp = static_cast<LLViewerInventoryItem*>(getItem());
if (itemp)
{
LLMessageSystem* msg = gMessageSystem;
@@ -1053,23 +1595,20 @@ void LLItemBridge::restoreToWorld()
msg->nextBlockFast(_PREHASH_InventoryData);
itemp->packMessage(msg);
msg->sendReliable(gAgent.getRegion()->getHost());
- }
-
- //Similar functionality to the drag and drop rez logic
- BOOL remove_from_inventory = FALSE;
-
- //remove local inventory copy, sim will deal with permissions and removing the item
- //from the actual inventory if its a no-copy etc
- if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
- {
- remove_from_inventory = TRUE;
- }
- // Check if it's in the trash. (again similar to the normal rez logic)
- const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
- if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
- {
- remove_from_inventory = TRUE;
+ //remove local inventory copy, sim will deal with permissions and removing the item
+ //from the actual inventory if its a no-copy etc
+ if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ remove_from_inventory = true;
+ }
+
+ // Check if it's in the trash. (again similar to the normal rez logic)
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
+ {
+ remove_from_inventory = true;
+ }
}
if(remove_from_inventory)
@@ -1079,12 +1618,12 @@ void LLItemBridge::restoreToWorld()
}
}
-void LLItemBridge::gotoItem(LLFolderView *folder)
+void LLItemBridge::gotoItem()
{
LLInventoryObject *obj = getInventoryObject();
if (obj && obj->getIsLinkType())
{
- LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
if (active_panel)
{
active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
@@ -1094,64 +1633,71 @@ void LLItemBridge::gotoItem(LLFolderView *folder)
LLUIImagePtr LLItemBridge::getIcon() const
{
- return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
+ LLInventoryObject *obj = getInventoryObject();
+ if (obj)
+ {
+ return LLInventoryIcon::getIcon(obj->getType(),
+ LLInventoryType::IT_NONE,
+ mIsLink);
+ }
+
+ return LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT);
}
-PermissionMask LLItemBridge::getPermissionMask() const
+LLUIImagePtr LLItemBridge::getIconOverlay() const
{
- LLViewerInventoryItem* item = getItem();
- PermissionMask perm_mask = 0;
- if(item)
+ if (getItem() && getItem()->getIsLinkType())
{
- BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
- BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
- BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
-
- if (copy) perm_mask |= PERM_COPY;
- if (mod) perm_mask |= PERM_MODIFY;
- if (xfer) perm_mask |= PERM_TRANSFER;
-
+ return LLUI::getUIImage("Inv_Link");
}
- return perm_mask;
+ return NULL;
}
-const std::string& LLItemBridge::getDisplayName() const
+PermissionMask LLItemBridge::getPermissionMask() const
{
- if(mDisplayName.empty())
- {
- buildDisplayName(getItem(), mDisplayName);
- }
- return mDisplayName;
+ LLViewerInventoryItem* item = getItem();
+ PermissionMask perm_mask = 0;
+ if (item) perm_mask = item->getPermissionMask();
+ return perm_mask;
}
-void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
+void LLItemBridge::buildDisplayName() const
{
- if(item)
+ if(getItem())
{
- name.assign(item->getName());
+ mDisplayName.assign(getItem()->getName());
}
else
{
- name.assign(LLStringUtil::null);
+ mDisplayName.assign(LLStringUtil::null);
+ }
+
+ mSearchableName.assign(mDisplayName);
+ mSearchableName.append(getLabelSuffix());
+ LLStringUtil::toUpper(mSearchableName);
+
+ //Name set, so trigger a sort
+ if(mParent)
+ {
+ mParent->requestSort();
}
}
LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
-{
+{
U8 font = LLFontGL::NORMAL;
-
- if( gAgentWearables.isWearingItem( mUUID ) )
+ const LLViewerInventoryItem* item = getItem();
+
+ if (get_is_item_worn(mUUID))
{
- // llinfos << "BOLD" << llendl;
+ // LL_INFOS() << "BOLD" << LL_ENDL;
font |= LLFontGL::BOLD;
}
-
- const LLViewerInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
+ else if(item && item->getIsLinkType())
{
font |= LLFontGL::ITALIC;
}
+
return (LLFontGL::StyleFlags)font;
}
@@ -1159,25 +1705,26 @@ std::string LLItemBridge::getLabelSuffix() const
{
// String table is loaded before login screen and inventory items are
// loaded after login, so LLTrans should be ready.
- static std::string NO_COPY =LLTrans::getString("no_copy");
+ static std::string NO_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)
+ if(item)
{
- // it's a bit confusing to put nocopy/nomod/etc on calling cards.
+ // Any type can have the link suffix...
+ BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
+ if (broken_link) return BROKEN_LINK;
+
+ BOOL link = item->getIsLinkType();
+ if (link) return LINK;
+
+ // ...but it's a bit confusing to put nocopy/nomod/etc suffixes on calling cards.
if(LLAssetType::AT_CALLINGCARD != item->getType()
&& item->getPermissions().getOwner() == gAgent.getID())
{
- BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
- if (broken_link) return BROKEN_LINK;
-
- BOOL link = item->getIsLinkType();
- if (link) return LINK;
-
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
if (!copy)
{
@@ -1221,6 +1768,17 @@ BOOL LLItemBridge::isItemRenameable() const
{
return FALSE;
}
+
+ if (!item->isFinished()) // EXT-8662
+ {
+ return FALSE;
+ }
+
+ if (isInboxFolder())
+ {
+ return FALSE;
+ }
+
return (item->getPermissions().allowModifyBy(gAgent.getID()));
}
return FALSE;
@@ -1237,34 +1795,71 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
LLViewerInventoryItem* item = getItem();
if(item && (item->getName() != new_name))
{
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->rename(new_name);
- buildDisplayName(new_item, mDisplayName);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
- model->updateLinkedObjects(item->getUUID());
-
- model->notifyObservers();
+ LLSD updates;
+ updates["name"] = new_name;
+ update_inventory_item(item->getUUID(),updates, NULL);
}
// return FALSE because we either notified observers (& therefore
// rebuilt) or we didn't update.
return FALSE;
}
-
BOOL LLItemBridge::removeItem()
{
if(!isItemRemovable())
{
return FALSE;
}
+
// move it to the trash
LLPreview::hide(mUUID, TRUE);
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = getItem();
+ if (!item) return FALSE;
+
+ // Already in trash
+ if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE;
+
+ LLNotification::Params params("ConfirmItemDeleteHasLinks");
+ params.functor.function(boost::bind(&LLItemBridge::confirmRemoveItem, this, _1, _2));
+
+ // Check if this item has any links. If generic inventory linking is enabled,
+ // we can't do this check because we may have items in a folder somewhere that is
+ // not yet in memory, so we don't want false negatives. (If disabled, then we
+ // know we only have links in the Outfits folder which we explicitly fetch.)
+ if (!gSavedSettings.getBOOL("InventoryLinking"))
+ {
+ if (!item->getIsLinkType())
+ {
+ LLInventoryModel::item_array_t item_array = gInventory.collectLinksTo(mUUID);
+ const U32 num_links = item_array.size();
+ if (num_links > 0)
+ {
+ // Warn if the user is will break any links when deleting this item.
+ LLNotifications::instance().add(params);
+ return FALSE;
+ }
+ }
+ }
+
+ LLNotifications::instance().forceResponse(params, 0);
+ return TRUE;
+}
+
+BOOL LLItemBridge::confirmRemoveItem(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return FALSE;
+
+ LLInventoryModel* model = getInventoryModel();
+ if (!model) return FALSE;
+
LLViewerInventoryItem* item = getItem();
+ if (!item) return FALSE;
+ const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
// if item is not already in trash
if(item && !model->isObjectDescendentOf(mUUID, trash_id))
{
@@ -1273,11 +1868,7 @@ BOOL LLItemBridge::removeItem()
// delete was successful
return TRUE;
}
- else
- {
- // tried to delete already item in trash (should purge?)
- return FALSE;
- }
+ return FALSE;
}
BOOL LLItemBridge::isItemCopyable() const
@@ -1285,35 +1876,19 @@ BOOL LLItemBridge::isItemCopyable() const
LLViewerInventoryItem* item = getItem();
if (item)
{
- // can't copy worn objects. DEV-15183
- LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
- if( !avatarp )
+ // Can't copy worn objects. DEV-15183
+ if(get_is_item_worn(mUUID))
{
return FALSE;
}
- if( avatarp->isWearingAttachment( mUUID, TRUE ) )
- {
- return FALSE;
- }
-
- // 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()));
+ // You can never copy a link.
if (item->getIsLinkType())
{
return FALSE;
}
- return TRUE;
- }
- return FALSE;
-}
-BOOL LLItemBridge::copyToClipboard() const
-{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
+
+ return item->getPermissions().allowCopyBy(gAgent.getID()) || gSavedSettings.getBOOL("InventoryLinking");
}
return FALSE;
}
@@ -1334,11 +1909,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;
}
@@ -1347,87 +1918,125 @@ BOOL LLItemBridge::isItemPermissive() const
// | LLFolderBridge |
// +=================================================+
-LLFolderBridge* LLFolderBridge::sSelf=NULL;
+LLHandle<LLFolderBridge> LLFolderBridge::sSelf;
// Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable() const
+BOOL LLFolderBridge::isItemMovable() const
{
LLInventoryObject* obj = getInventoryObject();
if(obj)
{
- return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType()));
+ // If it's a protected type folder, we can't move it
+ if (LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()))
+ return FALSE;
+ return TRUE;
}
return FALSE;
}
void LLFolderBridge::selectItem()
{
+ // Have no fear: the first thing start() does is to test if everything for that folder has been fetched...
+ LLInventoryModelBackgroundFetch::instance().start(getUUID(), true);
}
-
-// Can be destroyed (or moved to trash)
-BOOL LLFolderBridge::isItemRemovable()
+void LLFolderBridge::buildDisplayName() const
{
- LLInventoryModel* model = getInventoryModel();
- if(!model)
+ LLFolderType::EType preferred_type = getPreferredType();
+
+ // *TODO: to be removed when database supports multi language. This is a
+ // temporary attempt to display the inventory folder in the user locale.
+ // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID
+ // it uses the same way to find localized string
+
+ // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder)
+ // Translation of Accessories folder in Library inventory folder
+ bool accessories = false;
+ if(getName() == "Accessories")
{
- return FALSE;
+ //To ensure that Accessories folder is in Library we have to check its parent folder.
+ //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model
+ LLInventoryCategory* cat = gInventory.getCategory(getUUID());
+ if(cat)
+ {
+ const LLUUID& parent_folder_id = cat->getParentUUID();
+ accessories = (parent_folder_id == gInventory.getLibraryRootFolderID());
+ }
}
- if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ //"Accessories" inventory category has folder type FT_NONE. So, this folder
+ //can not be detected as protected with LLFolderType::lookupIsProtectedType
+ mDisplayName.assign(getName());
+ if (accessories || LLFolderType::lookupIsProtectedType(preferred_type))
{
- return FALSE;
+ LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD());
}
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( !avatar )
+ mSearchableName.assign(mDisplayName);
+ mSearchableName.append(getLabelSuffix());
+ LLStringUtil::toUpper(mSearchableName);
+
+ //Name set, so trigger a sort
+ if(mParent)
+ {
+ mParent->requestSort();
+ }
+}
+
+
+void LLFolderBridge::update()
+{
+ // we know we have children but haven't fetched them (doesn't obey filter)
+ bool loading = !isUpToDate() && hasChildren() && mFolderViewItem->isOpen();
+
+ if (loading != mIsLoading)
{
- return FALSE;
+ if ( loading )
+ {
+ // Measure how long we've been in the loading state
+ mTimeSinceRequestStart.reset();
+ }
+ mIsLoading = loading;
+
+ mFolderViewItem->refresh();
}
+}
- LLInventoryCategory* category = model->getCategory(mUUID);
- if( !category )
+
+// Iterate through a folder's children to determine if
+// all the children are removable.
+class LLIsItemRemovable : public LLFolderViewFunctor
+{
+public:
+ LLIsItemRemovable() : mPassed(TRUE) {}
+ virtual void doFolder(LLFolderViewFolder* folder)
{
- return FALSE;
+ mPassed &= folder->getViewModelItem()->isItemRemovable();
}
-
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
+ virtual void doItem(LLFolderViewItem* item)
{
- return FALSE;
+ mPassed &= item->getViewModelItem()->isItemRemovable();
}
+ BOOL mPassed;
+};
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
-
- S32 i;
- for( i = 0; i < descendent_categories.count(); i++ )
+// Can be destroyed (or moved to trash)
+BOOL LLFolderBridge::isItemRemovable() const
+{
+ if (!get_is_category_removable(getInventoryModel(), mUUID))
{
- LLInventoryCategory* category = descendent_categories[i];
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
- {
- return FALSE;
- }
+ return FALSE;
}
- for( i = 0; i < descendent_items.count(); i++ )
+ LLInventoryPanel* panel = mInventoryPanel.get();
+ LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL);
+ if (folderp)
{
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
+ LLIsItemRemovable folder_test;
+ folderp->applyFunctorToChildren(folder_test);
+ if (!folder_test.mPassed)
{
- if( gAgentWearables.isWearingItem( item->getUUID(), TRUE ) )
- {
- return FALSE;
- }
- }
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
- {
- if( avatar->isWearingAttachment( item->getUUID(), TRUE ) )
- {
- return FALSE;
- }
+ return FALSE;
}
}
@@ -1449,17 +2058,67 @@ BOOL LLFolderBridge::isUpToDate() const
BOOL LLFolderBridge::isItemCopyable() const
{
- return TRUE;
+ // Folders are copyable if items in them are, recursively, copyable.
+
+ // Get the content of the folder
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(mUUID,cat_array,item_array);
+
+ // Check the items
+ LLInventoryModel::item_array_t item_array_copy = *item_array;
+ for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
+ {
+ LLInventoryItem* item = *iter;
+ LLItemBridge item_br(mInventoryPanel.get(), mRoot, item->getUUID());
+ if (!item_br.isItemCopyable())
+ return FALSE;
}
-BOOL LLFolderBridge::copyToClipboard() const
+ // Check the folders
+ LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
+ LLViewerInventoryCategory* category = *iter;
+ LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, category->getUUID());
+ if (!cat_br.isItemCopyable())
+ return FALSE;
+ }
+
return TRUE;
}
- return FALSE;
+
+BOOL LLFolderBridge::isClipboardPasteable() const
+{
+ if ( ! LLInvFVBridge::isClipboardPasteable() )
+ return FALSE;
+
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if ( !model )
+ {
+ return FALSE;
+ }
+
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+ const LLViewerInventoryCategory *current_cat = getCategory();
+
+ // Search for the direct descendent of current Friends subfolder among all pasted items,
+ // and return false if is found.
+ for(S32 i = objects.size() - 1; i >= 0; --i)
+ {
+ const LLUUID &obj_id = objects.at(i);
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+
+ }
+ return TRUE;
}
BOOL LLFolderBridge::isClipboardPasteableAsLink() const
@@ -1469,7 +2128,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
return FALSE;
}
-
+
const LLInventoryModel* model = getInventoryModel();
if (!model)
{
@@ -1479,164 +2138,426 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
const LLViewerInventoryCategory *current_cat = getCategory();
if (current_cat)
{
+ const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
const LLUUID &current_cat_id = current_cat->getUUID();
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+ S32 count = objects.size();
for(S32 i = 0; i < count; i++)
{
- const LLInventoryCategory *cat = model->getCategory(objects.get(i));
+ const LLUUID &obj_id = objects.at(i);
+ const LLInventoryCategory *cat = model->getCategory(obj_id);
if (cat)
{
const LLUUID &cat_id = cat->getUUID();
// Don't allow recursive pasting
- if ((cat_id == current_cat_id) ||
+ if ((cat_id == current_cat_id) ||
model->isObjectDescendentOf(current_cat_id, cat_id))
{
return FALSE;
}
}
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( is_in_friend_folder )
+ {
+ // If object is direct descendent of current Friends subfolder than return false.
+ // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
+ // in case type of obj_id is LLInventoryItem.
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
}
}
return TRUE;
}
-BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
- BOOL drop)
+static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg)
{
- // This should never happen, but if an inventory item is incorrectly parented,
- // the UI will get confused and pass in a NULL.
- if(!inv_cat) return FALSE;
+ // Collapse links directly to items/folders
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+ LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+ if (linked_item != NULL)
+ {
+ inv_item = linked_item;
+ }
+
+ bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
+ if (!allow_transfer)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer");
+ return false;
+ }
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
+#if BLOCK_WORN_ITEMS_IN_OUTBOX
+ bool worn = get_is_item_worn(inv_item->getUUID());
+ if (worn)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxWorn");
+ return false;
+ }
+#endif
+
+ bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType());
+ if (calling_card)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard");
+ return false;
+ }
+
+ return true;
+}
+
+
+int get_folder_levels(LLInventoryCategory* inv_cat)
+{
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
+ int max_child_levels = 0;
- // cannot drag categories into library
- if(!isAgentInventory())
+ for (S32 i=0; i < cats->size(); ++i)
{
- return FALSE;
+ LLInventoryCategory* category = cats->at(i);
+ max_child_levels = llmax(max_child_levels, get_folder_levels(category));
+ }
+
+ return 1 + max_child_levels;
+}
+
+int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id)
+{
+ int depth = 0;
+
+ if (ancestor_id == descendant_id) return depth;
+
+ const LLInventoryCategory* category = gInventory.getCategory(descendant_id);
+
+ while(category)
+ {
+ LLUUID parent_id = category->getParentUUID();
+
+ if (parent_id.isNull()) break;
+
+ depth++;
+
+ if (parent_id == ancestor_id) return depth;
+
+ category = gInventory.getCategory(parent_id);
}
+ LL_WARNS() << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL;
+ return -1;
+}
+
+BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
+ BOOL drop,
+ std::string& tooltip_msg)
+{
+
+ LLInventoryModel* model = getInventoryModel();
+
+ if (!inv_cat) return FALSE; // shouldn't happen, but in case item is incorrectly parented in which case inv_cat will be NULL
+ if (!model) return FALSE;
+ if (!isAgentAvatarValid()) return FALSE;
+ if (!isAgentInventory()) return FALSE; // cannot drag categories into library
+
+ LLInventoryPanel* destination_panel = mInventoryPanel.get();
+ if (!destination_panel) return false;
+
+ LLInventoryFilter* filter = getInventoryFilter();
+ if (!filter) return false;
+
+ const LLUUID &cat_id = inv_cat->getUUID();
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
+ const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id);
+
// check to make sure source is agent inventory, and is represented there.
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
- BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
+ const BOOL is_agent_inventory = (model->getCategory(cat_id) != NULL)
&& (LLToolDragAndDrop::SOURCE_AGENT == source);
BOOL accept = FALSE;
- S32 i;
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- if(is_agent_inventory)
- {
- const LLUUID& cat_id = inv_cat->getUUID();
-
- // Is the destination the trash?
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- BOOL move_is_into_trash = (mUUID == trash_id)
- || model->isObjectDescendentOf(mUUID, trash_id);
- BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType()));
- LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
- if (move_is_into_current_outfit || move_is_into_outfit)
+ U64 filter_types = filter->getFilterTypes();
+ BOOL use_filter = filter_types && (filter_types&LLInventoryFilter::FILTERTYPE_DATE || (filter_types&LLInventoryFilter::FILTERTYPE_OBJECT)==0);
+
+ if (is_agent_inventory)
+ {
+ const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
+ const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
+ const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
+
+ const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
+ const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
+
+ //--------------------------------------------------------------------------------
+ // Determine if folder can be moved.
+ //
+
+ BOOL is_movable = TRUE;
+
+ if (is_movable && (mUUID == cat_id))
{
- // BAP - restrictions?
- is_movable = true;
+ is_movable = FALSE;
+ tooltip_msg = LLTrans::getString("TooltipDragOntoSelf");
}
- if( is_movable )
+ if (is_movable && (model->isObjectDescendentOf(mUUID, cat_id)))
{
- gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
-
- for( i = 0; i < descendent_categories.count(); i++ )
+ is_movable = FALSE;
+ tooltip_msg = LLTrans::getString("TooltipDragOntoOwnChild");
+ }
+ if (is_movable && LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
+ {
+ is_movable = FALSE;
+ // tooltip?
+ }
+ if (is_movable && move_is_into_outfit)
+ {
+ is_movable = FALSE;
+ // tooltip?
+ }
+ if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE)))
+ {
+ is_movable = FALSE;
+ // tooltip?
+ }
+
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ if (is_movable)
+ {
+ model->collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
+ for (S32 i=0; i < descendent_categories.size(); ++i)
{
LLInventoryCategory* category = descendent_categories[i];
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
{
- // ...can't move "special folders" like Textures
+ // Can't move "special folders" (e.g. Textures Folder).
is_movable = FALSE;
break;
}
}
+ }
+ U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
+ if (is_movable
+ && move_is_into_current_outfit
+ && descendent_items.size() > max_items_to_wear)
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
+ gInventory.collectDescendentsIf(cat_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ not_worn);
+
+ if (items.size() > max_items_to_wear)
+ {
+ // Can't move 'large' folders into current outfit: MAINT-4086
+ is_movable = FALSE;
+ LLStringUtil::format_map_t args;
+ args["AMOUNT"] = llformat("%d", max_items_to_wear);
+ tooltip_msg = LLTrans::getString("TooltipTooManyWearables",args);
+ }
+ }
+ if (is_movable && move_is_into_trash)
+ {
+ for (S32 i=0; i < descendent_items.size(); ++i)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (get_is_item_worn(item->getUUID()))
+ {
+ is_movable = FALSE;
+ break; // It's generally movable, but not into the trash.
+ }
+ }
+ }
+ if (is_movable && move_is_into_landmarks)
+ {
+ for (S32 i=0; i < descendent_items.size(); ++i)
+ {
+ LLViewerInventoryItem* item = descendent_items[i];
+
+ // Don't move anything except landmarks and categories into Landmarks folder.
+ // We use getType() instead of getActua;Type() to allow links to landmarks and folders.
+ if (LLAssetType::AT_LANDMARK != item->getType() && LLAssetType::AT_CATEGORY != item->getType())
+ {
+ is_movable = FALSE;
+ break; // It's generally movable, but not into Landmarks.
+ }
+ }
+ }
+ if (is_movable && move_is_into_outbox)
+ {
+ const int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat);
- if( is_movable )
+ if (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))
{
- if( move_is_into_trash )
+ tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels");
+ is_movable = FALSE;
+ }
+ else
+ {
+ int dragged_folder_count = descendent_categories.size();
+ int existing_item_count = 0;
+ int existing_folder_count = 0;
+
+ const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
+
+ if (master_folder != NULL)
{
- for( i = 0; i < descendent_items.count(); i++ )
+ if (model->isObjectDescendentOf(cat_id, master_folder->getUUID()))
{
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
+ // Don't use count because we're already inside the same category anyway
+ dragged_folder_count = 0;
+ }
+ else
+ {
+ existing_folder_count = 1; // Include the master folder in the count!
+
+ // If we're in the drop operation as opposed to the drag without drop, we are doing a
+ // single category at a time so don't block based on the total amount of cargo data items
+ if (drop)
{
- if( gAgentWearables.isWearingItem( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
+ dragged_folder_count += 1;
}
else
- if( item->getType() == LLAssetType::AT_OBJECT )
{
- if( avatar->isWearingAttachment( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
+ // NOTE: The cargo id's count is a total of categories AND items but we err on the side of
+ // prevention rather than letting too many folders into the hierarchy of the outbox,
+ // when we're dragging the item to a new parent
+ dragged_folder_count += LLToolDragAndDrop::instance().getCargoCount();
+ }
+ }
+
+ // Tally the total number of categories and items inside the master folder
+
+ LLInventoryModel::cat_array_t existing_categories;
+ LLInventoryModel::item_array_t existing_items;
+
+ model->collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
+
+ existing_folder_count += existing_categories.size();
+ existing_item_count += existing_items.size();
+ }
+ else
+ {
+ // Assume a single category is being dragged to the outbox since we evaluate one at a time
+ // when not putting them under a parent item.
+ dragged_folder_count += 1;
+ }
+
+ const int nested_folder_count = existing_folder_count + dragged_folder_count;
+ const int nested_item_count = existing_item_count + descendent_items.size();
+
+ if (nested_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount"))
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders");
+ is_movable = FALSE;
+ }
+ else if (nested_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects");
+ is_movable = FALSE;
+ }
+
+ if (is_movable == TRUE)
+ {
+ for (S32 i=0; i < descendent_items.size(); ++i)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (!can_move_to_outbox(item, tooltip_msg))
+ {
+ is_movable = FALSE;
+ break;
}
}
}
}
}
-
- accept = is_movable
- && (mUUID != cat_id) // Can't move a folder into itself
- && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
- && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity
- if(accept && drop)
+ if (is_movable)
+ {
+ LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+ is_movable = active_panel != NULL;
+
+ // For a folder to pass the filter all its descendants are required to pass.
+ // We make this exception to allow reordering folders within an inventory panel,
+ // which has a filter applied, like Recent tab for example.
+ // There may be folders which are displayed because some of their descendants pass
+ // the filter, but other don't, and thus remain hidden. Without this check,
+ // such folders would not be allowed to be moved within a panel.
+ if (destination_panel == active_panel)
+ {
+ is_movable = true;
+ }
+ else
+ {
+ LLFolderView* active_folder_view = NULL;
+
+ if (is_movable)
+ {
+ active_folder_view = active_panel->getRootFolder();
+ is_movable = active_folder_view != NULL;
+ }
+
+ if (is_movable && use_filter)
+ {
+ // Check whether the folder being dragged from active inventory panel
+ // passes the filter of the destination panel.
+ is_movable = check_category(model, cat_id, active_panel, filter);
+ }
+ }
+ }
+ //
+ //--------------------------------------------------------------------------------
+
+ accept = is_movable;
+
+ if (accept && drop)
{
// Look for any gestures and deactivate them
if (move_is_into_trash)
{
- for (i = 0; i < descendent_items.count(); i++)
+ for (S32 i=0; i < descendent_items.size(); i++)
{
LLInventoryItem* item = descendent_items[i];
if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ && LLGestureMgr::instance().isGestureActive(item->getUUID()))
{
- LLGestureManager::instance().deactivateGesture(item->getUUID());
+ LLGestureMgr::instance().deactivateGesture(item->getUUID());
}
}
}
- // if target is an outfit or current outfit folder we use link
- if (move_is_into_current_outfit || move_is_into_outfit)
+ // if target is current outfit folder we use link
+ if (move_is_into_current_outfit &&
+ inv_cat->getPreferredType() == LLFolderType::FT_NONE)
{
-#if SUPPORT_ENSEMBLES
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceManager::wearEnsemble(inv_cat);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_cat->getUUID(),
- mUUID,
- inv_cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- cb);
- }
-#endif
+ // traverse category and add all contents to currently worn.
+ BOOL append = true;
+ LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
+ }
+ else if (move_is_into_outbox && !move_is_from_outbox)
+ {
+ copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId());
}
else
{
-
+ if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))
+ {
+ set_dad_inbox_object(cat_id);
+ }
+
// Reparent the folder and restamp children if it's moving
// into trash.
LLInvFVBridge::changeCategoryParent(
@@ -1647,13 +2568,37 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
- else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ else if (LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ if (move_is_into_outbox)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+ accept = FALSE;
+ }
+ else
+ {
+ accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter);
+ }
+ }
+ else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
{
- // content category has same ID as object itself
- LLUUID object_id = inv_cat->getUUID();
- LLUUID category_id = mUUID;
- accept = move_inv_category_world_to_agent(object_id, category_id, drop);
+ if (move_is_into_outbox)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+ accept = FALSE;
+ }
+ else
+ {
+ // Accept folders that contain complete outfits.
+ accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(cat_id);
+ }
+
+ if (accept && drop)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, true, false);
+ }
}
+
return accept;
}
@@ -1668,16 +2613,17 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
{
dialog = "MoveInventoryFromObject";
}
- LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotificationsUtil::add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
}
// Move/copy all inventory items from the Contents folder of an in-world
// object to the agent's inventory, inside a given category.
-BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
const LLUUID& category_id,
BOOL drop,
void (*callback)(S32, void*),
- void* user_data)
+ void* user_data,
+ LLInventoryFilter* filter)
{
// Make sure the object exists. If we allowed dragging from
// anonymous objects, it would be possible to bypass
@@ -1686,33 +2632,46 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
LLViewerObject* object = gObjectList.findObject(object_id);
if(!object)
{
- llinfos << "Object not found for drop." << llendl;
+ LL_INFOS() << "Object not found for drop." << LL_ENDL;
return FALSE;
}
// this folder is coming from an object, as there is only one folder in an object, the root,
// we need to collect the entire contents and handle them as a group
- InventoryObjectList inventory_objects;
+ LLInventoryObject::object_list_t inventory_objects;
object->getInventoryContents(inventory_objects);
if (inventory_objects.empty())
{
- llinfos << "Object contents not found for drop." << llendl;
+ LL_INFOS() << "Object contents not found for drop." << LL_ENDL;
return FALSE;
}
-
- BOOL accept = TRUE;
+
+ BOOL accept = FALSE;
BOOL is_move = FALSE;
+ BOOL use_filter = FALSE;
+ if (filter)
+ {
+ U64 filter_types = filter->getFilterTypes();
+ use_filter = filter_types && (filter_types&LLInventoryFilter::FILTERTYPE_DATE || (filter_types&LLInventoryFilter::FILTERTYPE_OBJECT)==0);
+ }
// coming from a task. Need to figure out if the person can
// move/copy this item.
- InventoryObjectList::iterator it = inventory_objects.begin();
- InventoryObjectList::iterator end = inventory_objects.end();
+ LLInventoryObject::object_list_t::iterator it = inventory_objects.begin();
+ LLInventoryObject::object_list_t::iterator end = inventory_objects.end();
for ( ; it != end; ++it)
{
+ LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(it->get());
+ if (!item)
+ {
+ LL_WARNS() << "Invalid inventory item for drop" << LL_ENDL;
+ continue;
+ }
+
// coming from a task. Need to figure out if the person can
// move/copy this item.
- LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
+ LLPermissions perm(item->getPermissions());
if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
&& perm.allowTransferTo(gAgent.getID())))
// || gAgent.isGodlike())
@@ -1727,9 +2686,14 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
is_move = TRUE;
accept = TRUE;
}
- else
+
+ if (accept && use_filter)
+ {
+ accept = filter->check(item);
+ }
+
+ if (!accept)
{
- accept = FALSE;
break;
}
}
@@ -1737,7 +2701,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
if(drop && accept)
{
it = inventory_objects.begin();
- InventoryObjectList::iterator first_it = inventory_objects.begin();
LLMoveInv* move_inv = new LLMoveInv;
move_inv->mObjectID = object_id;
move_inv->mCategoryID = category_id;
@@ -1765,178 +2728,141 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
return accept;
}
-bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
+void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)
{
- // Valid COF items are:
- // - links to wearables (body parts or clothing)
- // - links to attachments
- // - links to gestures
- // - links to ensemble folders
- LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
- if (linked_item)
- {
- LLAssetType::EType type = linked_item->getType();
- return (type == LLAssetType::AT_CLOTHING ||
- type == LLAssetType::AT_BODYPART ||
- type == LLAssetType::AT_GESTURE ||
- type == LLAssetType::AT_OBJECT);
- }
- else
+ // Bail out immediately if no descendents
+ if( mComplete.empty() )
{
- LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
- // BAP remove AT_NONE support after ensembles are fully working?
- return (linked_category &&
- ((linked_category->getPreferredType() == LLAssetType::AT_NONE) ||
- (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType()))));
- }
-}
-
-
-bool LLFindWearables::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- if(item)
- {
- if((item->getType() == LLAssetType::AT_CLOTHING)
- || (item->getType() == LLAssetType::AT_BODYPART))
+ LL_WARNS() << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << LL_ENDL;
+ if (clear_observer)
{
- return TRUE;
+ gInventory.removeObserver(this);
+ delete this;
}
+ return;
}
- return FALSE;
-}
-
-
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
-{
-public:
- LLRightClickInventoryFetchObserver() :
- mCopyItems(false)
- { };
- LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
- mCatID(cat_id),
- mCopyItems(copy_items)
- { };
- virtual void done()
+ // Copy the list of complete fetched folders while "this" is still valid
+ uuid_vec_t completed_folder = mComplete;
+
+ // Clean up, and remove this as an observer now since recursive calls
+ // could notify observers and throw us into an infinite loop.
+ if (clear_observer)
{
- // we've downloaded all the items, so repaint the dialog
- LLFolderBridge::staticFolderOptionsMenu();
-
gInventory.removeObserver(this);
delete this;
}
-
-protected:
- LLUUID mCatID;
- bool mCopyItems;
-
-};
-
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
-{
-public:
- LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
- ~LLRightClickInventoryFetchDescendentsObserver() {}
- virtual void done();
-protected:
- bool mCopyItems;
-};
-
-void LLRightClickInventoryFetchDescendentsObserver::done()
-{
- // Avoid passing a NULL-ref as mCompleteFolders.front() down to
- // gInventory.collectDescendents()
- if( mCompleteFolders.empty() )
+ for (uuid_vec_t::iterator current_folder = completed_folder.begin(); current_folder != completed_folder.end(); ++current_folder)
{
- llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
+ // Get the information on the fetched folder items and subfolders and fetch those
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array);
- // What we do here is get the complete information on the items in
- // the library, and set up an observer that will wait for that to
- // happen.
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(mCompleteFolders.front(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- S32 count = item_array.count();
-#if 0 // HACK/TODO: Why?
- // This early causes a giant menu to get produced, and doesn't seem to be needed.
- if(!count)
- {
- llwarns << "Nothing fetched in category " << mCompleteFolders.front()
- << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-#endif
+ S32 item_count(0);
+ if( item_array )
+ {
+ item_count = item_array->size();
+ }
+
+ S32 cat_count(0);
+ if( cat_array )
+ {
+ cat_count = cat_array->size();
+ }
- LLRightClickInventoryFetchObserver* outfit;
- outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
- LLInventoryFetchObserver::item_ref_t ids;
- for(S32 i = 0; i < count; ++i)
- {
- ids.push_back(item_array.get(i)->getUUID());
- }
+ // Move to next if current folder empty
+ if ((item_count == 0) && (cat_count == 0))
+ {
+ continue;
+ }
- // clean up, and remove this as an observer since the call to the
- // outfit could notify observers and throw us into an infinite
- // loop.
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
+ uuid_vec_t ids;
+ LLRightClickInventoryFetchObserver* outfit = NULL;
+ LLRightClickInventoryFetchDescendentsObserver* categories = NULL;
- // increment busy count and either tell the inventory to check &
- // call done, or add this object to the inventory for observation.
- inc_busy_count();
+ // Fetch the items
+ if (item_count)
+ {
+ for (S32 i = 0; i < item_count; ++i)
+ {
+ ids.push_back(item_array->at(i)->getUUID());
+ }
+ outfit = new LLRightClickInventoryFetchObserver(ids);
+ }
+ // Fetch the subfolders
+ if (cat_count)
+ {
+ for (S32 i = 0; i < cat_count; ++i)
+ {
+ ids.push_back(cat_array->at(i)->getUUID());
+ }
+ categories = new LLRightClickInventoryFetchDescendentsObserver(ids);
+ }
- // do the fetch
- outfit->fetchItems(ids);
- outfit->done(); //Not interested in waiting and this will be right 99% of the time.
+ // Perform the item fetch
+ if (outfit)
+ {
+ outfit->startFetch();
+ outfit->execute(); // Not interested in waiting and this will be right 99% of the time.
+ delete outfit;
//Uncomment the following code for laggy Inventory UI.
-/* if(outfit->isEverythingComplete())
+ /*
+ if (outfit->isFinished())
{
- // everything is already here - call done.
- outfit->done();
+ // everything is already here - call done.
+ outfit->execute();
+ delete outfit;
}
else
{
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(outfit);
- }*/
+ // it's all on its way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit);
+ }
+ */
+ }
+ // Perform the subfolders fetch : this is where we truly recurse down the folder hierarchy
+ if (categories)
+ {
+ categories->startFetch();
+ if (categories->isFinished())
+ {
+ // everything is already here - call done.
+ categories->execute();
+ delete categories;
+ }
+ else
+ {
+ // it's all on its way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(categories);
+ }
+ }
+ }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryWearObserver
//
-// Observer for "copy and wear" operation to support knowing
+// Observer for "copy and wear" operation to support knowing
// when the all of the contents have been added to inventory.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInventoryCopyAndWearObserver : public LLInventoryObserver
{
public:
- LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
+ LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count, bool folder_added=false, bool replace=false) :
+ mCatID(cat_id), mContentsCount(count), mFolderAdded(folder_added), mReplace(replace){}
virtual ~LLInventoryCopyAndWearObserver() {}
virtual void changed(U32 mask);
protected:
LLUUID mCatID;
int mContentsCount;
- BOOL mFolderAdded;
+ bool mFolderAdded;
+ bool mReplace;
};
@@ -1945,7 +2871,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
{
if((mask & (LLInventoryObserver::ADD)) != 0)
{
- if (!mFolderAdded)
+ if (!mFolderAdded)
{
const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
@@ -1953,7 +2879,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
std::set<LLUUID>::const_iterator id_end = changed_items.end();
for (;id_it != id_end; ++id_it)
{
- if ((*id_it) == mCatID)
+ if ((*id_it) == mCatID)
{
mFolderAdded = TRUE;
break;
@@ -1961,14 +2887,13 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
}
}
- if (mFolderAdded)
+ if (mFolderAdded)
{
LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
-
if (NULL == category)
{
- llwarns << "gInventory.getCategory(" << mCatID
- << ") was NULL" << llendl;
+ LL_WARNS() << "gInventory.getCategory(" << mCatID
+ << ") was NULL" << LL_ENDL;
}
else
{
@@ -1976,10 +2901,10 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
mContentsCount)
{
gInventory.removeObserver(this);
- LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
+ LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, !mReplace);
delete this;
}
- }
+ }
}
}
@@ -1987,11 +2912,16 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
-void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
{
if ("open" == action)
{
- openItem();
+ LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mInventoryPanel.get()->getItemByID(mUUID));
+ if (f)
+ {
+ f->toggleOpen();
+ }
+
return;
}
else if ("paste" == action)
@@ -2014,20 +2944,15 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
modifyOutfit(FALSE);
return;
}
-#if SUPPORT_ENSEMBLES
- else if ("wearasensemble" == action)
+ else if ("addtooutfit" == action)
{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
- LLAppearanceManager::wearEnsemble(cat,true);
+ modifyOutfit(TRUE);
return;
}
-#endif
- else if ("addtooutfit" == action)
+ else if ("cut" == action)
{
- modifyOutfit(TRUE);
+ cutToClipboard();
+ gInventory.removeObject(mUUID);
return;
}
else if ("copy" == action)
@@ -2041,12 +2966,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
- remove_inventory_category_from_avatar ( cat );
+
+ LLAppearanceMgr::instance().takeOffOutfit( cat->getLinkedUUID() );
return;
- }
+ }
else if ("purge" == action)
- {
+ {
purgeItem(model, mUUID);
return;
}
@@ -2055,13 +2980,41 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
restoreItem();
return;
}
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ else if ("delete_system_folder" == action)
+ {
+ removeSystemFolder();
+ }
+#endif
+ else if (isMarketplaceCopyAction(action))
+ {
+ LL_INFOS() << "Copy folder to marketplace action!" << LL_ENDL;
+
+ LLInventoryCategory * cat = gInventory.getCategory(mUUID);
+ if (!cat) return;
+
+ const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+ copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());
+ }
+#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
+ else if (isMarketplaceSendAction(action))
+ {
+ LL_INFOS() << "Send to marketplace action!" << LL_ENDL;
+
+ LLInventoryCategory * cat = gInventory.getCategory(mUUID);
+ if (!cat) return;
+
+ send_to_marketplace(cat);
+ }
+#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
}
void LLFolderBridge::openItem()
{
- lldebugs << "LLFolderBridge::openItem()" << llendl;
+ LL_DEBUGS() << "LLFolderBridge::openItem()" << LL_ENDL;
LLInventoryModel* model = getInventoryModel();
if(!model) return;
+ if(mUUID.isNull()) return;
bool fetching_inventory = model->fetchDescendentsOf(mUUID);
// Only change folder type if we have the folder contents.
if (!fetching_inventory)
@@ -2083,19 +3036,16 @@ void LLFolderBridge::determineFolderType()
{
LLInventoryModel* model = getInventoryModel();
LLViewerInventoryCategory* category = model->getCategory(mUUID);
- category->determineFolderType();
+ if (category)
+ {
+ category->determineFolderType();
+ }
}
}
BOOL LLFolderBridge::isItemRenameable() const
{
- LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
- if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())
- && (cat->getOwnerID() == gAgent.getID()))
- {
- return TRUE;
- }
- return FALSE;
+ return get_is_category_renameable(getInventoryModel(), mUUID);
}
void LLFolderBridge::restoreItem()
@@ -2105,15 +3055,15 @@ void LLFolderBridge::restoreItem()
if(cat)
{
LLInventoryModel* model = getInventoryModel();
- LLUUID new_parent = model->findCategoryUUIDForType(cat->getType());
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
// do not restamp children on restore
LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
}
}
-LLAssetType::EType LLFolderBridge::getPreferredType() const
+LLFolderType::EType LLFolderBridge::getPreferredType() const
{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
@@ -2126,7 +3076,7 @@ LLAssetType::EType LLFolderBridge::getPreferredType() const
// Icons for folders are based on the preferred type
LLUIImagePtr LLFolderBridge::getIcon() const
{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
@@ -2135,30 +3085,43 @@ LLUIImagePtr LLFolderBridge::getIcon() const
return getIcon(preferred_type);
}
-LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type)
+// static
+LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
{
- // we only have one folder image now
- return LLUI::getUIImage("Inv_FolderClosed");
+ return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE));
}
-BOOL LLFolderBridge::renameItem(const std::string& new_name)
+LLUIImagePtr LLFolderBridge::getIconOpen() const
{
- if(!isItemRenameable())
- return FALSE;
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat && (cat->getName() != new_name))
- {
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->rename(new_name);
- new_cat->updateServer(FALSE);
- model->updateCategory(new_cat);
- model->updateLinkedObjects(cat->getUUID());
+ return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));
- model->notifyObservers();
+}
+
+LLUIImagePtr LLFolderBridge::getIconOverlay() const
+{
+ if (getInventoryObject() && getInventoryObject()->getIsLinkType())
+ {
+ return LLUI::getUIImage("Inv_Link");
}
+ return NULL;
+}
+
+std::string LLFolderBridge::getLabelSuffix() const
+{
+ static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f);
+ return mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay()
+ ? llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str())
+ : LLStringUtil::null;
+}
+
+BOOL LLFolderBridge::renameItem(const std::string& new_name)
+{
+
+ LLScrollOnRenameObserver *observer = new LLScrollOnRenameObserver(mUUID, mRoot);
+ gInventory.addObserver(observer);
+
+ rename_category(getInventoryModel(), mUUID, new_name);
+
// return FALSE because we either notified observers (& therefore
// rebuilt) or we didn't update.
return FALSE;
@@ -2170,63 +3133,190 @@ BOOL LLFolderBridge::removeItem()
{
return FALSE;
}
- // move it to the trash
- LLPreview::hide(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
+ const LLViewerInventoryCategory *cat = getCategory();
+
+ LLSD payload;
+ LLSD args;
+ args["FOLDERNAME"] = cat->getName();
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ LLNotification::Params params("ConfirmDeleteProtectedCategory");
+ params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2));
+ LLNotifications::instance().forceResponse(params, 0);
+ return TRUE;
+}
- // Look for any gestures and deactivate them
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
- S32 i;
- for (i = 0; i < descendent_items.count(); i++)
+BOOL LLFolderBridge::removeSystemFolder()
+{
+ const LLViewerInventoryCategory *cat = getCategory();
+ if (!LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
- LLInventoryItem* item = descendent_items[i];
- if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(item->getUUID()))
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
+ return FALSE;
}
- // go ahead and do the normal remove if no 'last calling
- // cards' are being removed.
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
+ LLSD payload;
+ LLSD args;
+ args["FOLDERNAME"] = cat->getName();
+
+ LLNotification::Params params("ConfirmDeleteProtectedCategory");
+ params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2));
{
- LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
+ LLNotifications::instance().add(params);
}
-
return TRUE;
}
+bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ // if they choose delete, do it. Otherwise, don't do anything
+ if(option == 0)
+ {
+ // move it to the trash
+ LLPreview::hide(mUUID);
+ getInventoryModel()->removeCategory(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//Recursively update the folder's creation date
+void LLFolderBridge::updateHierarchyCreationDate(time_t date)
+{
+ if(getCreationDate() < date)
+ {
+ setCreationDate(date);
+ if(mParent)
+ {
+ static_cast<LLFolderBridge *>(mParent)->updateHierarchyCreationDate(date);
+ }
+ }
+}
+
void LLFolderBridge::pasteFromClipboard()
{
LLInventoryModel* model = getInventoryModel();
if(model && isClipboardPasteable())
{
- LLInventoryItem* item = NULL;
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+ const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
+ const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
+
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
+ const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
+ const BOOL move_is_into_favorites = (mUUID == favorites_id);
+
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+
+ if (move_is_into_outbox)
+ {
+ LLFolderViewItem * outbox_itemp = mInventoryPanel.get()->getItemByID(mUUID);
+
+ if (outbox_itemp)
+ {
+ LLToolDragAndDrop::instance().setCargoCount(objects.size());
+
+ BOOL can_list = TRUE;
+
+ for (std::vector<LLUUID>::const_iterator iter = objects.begin();
+ (iter != objects.end()) && (can_list == TRUE);
+ ++iter)
+ {
+ const LLUUID& item_id = (*iter);
+ LLInventoryItem *item = model->getItem(item_id);
+
+ if (item)
+ {
+ MASK mask = 0x0;
+ BOOL drop = FALSE;
+ EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType());
+ void * cargo_data = (void *) item;
+ std::string tooltip_msg;
+
+ can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+ }
+ }
+
+ LLToolDragAndDrop::instance().resetCargoCount();
+
+ if (can_list == FALSE)
+ {
+ // Notify user of failure somehow -- play error sound? modal dialog?
+ return;
+ }
+ }
+ }
+
const LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
+
+ for (std::vector<LLUUID>::const_iterator iter = objects.begin();
+ iter != objects.end();
+ ++iter)
{
- item = model->getItem(objects.get(i));
- if (item)
+ const LLUUID& item_id = (*iter);
+
+ LLInventoryItem *item = model->getItem(item_id);
+ LLInventoryObject *obj = model->getObject(item_id);
+ if (obj)
{
- if(LLInventoryClipboard::instance().isCutMode())
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ if (item && can_move_to_outfit(item, move_is_into_current_outfit))
+ {
+ dropToOutfit(item, move_is_into_current_outfit);
+ }
+ }
+ else if (move_is_into_favorites)
+ {
+ if (item && can_move_to_landmarks(item))
+ {
+ dropToFavorites(item);
+ }
+ }
+ else if (LLClipboard::instance().isCutMode())
+ {
+ // Do a move to "paste" a "cut"
+ // move_inventory_item() is not enough, as we have to update inventory locally too
+ if (LLAssetType::AT_CATEGORY == obj->getType())
+ {
+ LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
+ llassert(vicat);
+ if (vicat)
+ {
+ //changeCategoryParent() implicity calls dirtyFilter
+ changeCategoryParent(model, vicat, parent_id, FALSE);
+ }
+ }
+ else
{
- // move_inventory_item() is not enough,
- //we have to update inventory locally too
- changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+ LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ llassert(viitem);
+ if (viitem)
+ {
+ //changeItemParent() implicity calls dirtyFilter
+ changeItemParent(model, viitem, parent_id, FALSE);
+ }
+ }
}
else
{
+ // Do a "copy" to "paste" a regular copy clipboard
+ if (LLAssetType::AT_CATEGORY == obj->getType())
+ {
+ LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
+ llassert(vicat);
+ if (vicat)
+ {
+ copy_inventory_category(model, vicat, parent_id);
+ }
+ }
+ else
+ {
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
@@ -2238,107 +3328,66 @@ void LLFolderBridge::pasteFromClipboard()
}
}
}
+ // Change mode to paste for next paste
+ LLClipboard::instance().setCutMode(false);
+ }
}
void LLFolderBridge::pasteLinkFromClipboard()
{
- const LLInventoryModel* model = getInventoryModel();
+ LLInventoryModel* model = getInventoryModel();
if(model)
{
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+ const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
+
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
+ const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
+
+ if (move_is_into_outbox)
+ {
+ // Notify user of failure somehow -- play error sound? modal dialog?
+ return;
+ }
+
+ const LLUUID parent_id(mUUID);
+
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+ for (std::vector<LLUUID>::const_iterator iter = objects.begin();
+ iter != objects.end();
+ ++iter)
{
- const LLUUID &object_id = objects.get(i);
-#if SUPPORT_ENSEMBLES
- if (LLInventoryCategory *cat = model->getCategory(object_id))
+ const LLUUID &object_id = (*iter);
+ if (move_is_into_current_outfit || move_is_into_outfit)
{
- link_inventory_item(
- gAgent.getID(),
- cat->getUUID(),
- parent_id,
- cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- LLPointer<LLInventoryCallback>(NULL));
+ LLInventoryItem *item = model->getItem(object_id);
+ if (item && can_move_to_outfit(item, move_is_into_current_outfit))
+ {
+ dropToOutfit(item, move_is_into_current_outfit);
+ }
}
- else
-#endif
- if (LLInventoryItem *item = model->getItem(object_id))
+ else if (LLConstPointer<LLInventoryObject> obj = model->getObject(object_id))
{
- link_inventory_item(
- gAgent.getID(),
- item->getUUID(),
- parent_id,
- item->getName(),
- LLAssetType::AT_LINK,
- LLPointer<LLInventoryCallback>(NULL));
+ link_inventory_object(parent_id, obj, LLPointer<LLInventoryCallback>(NULL));
}
}
+ // Change mode to paste for next paste
+ LLClipboard::instance().setCutMode(false);
}
}
void LLFolderBridge::staticFolderOptionsMenu()
{
- if (!sSelf) return;
- sSelf->folderOptionsMenu();
-}
-
-void LLFolderBridge::folderOptionsMenu()
-{
- std::vector<std::string> disabled_items;
-
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
-
- const LLInventoryCategory* category = model->getCategory(mUUID);
- LLAssetType::EType type = category->getPreferredType();
- const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type);
- // BAP change once we're no longer treating regular categories as ensembles.
- const bool is_ensemble = category && (type == LLAssetType::AT_NONE ||
- LLAssetType::lookupIsEnsembleCategoryType(type));
-
- // calling card related functionality for folders.
+ LLFolderBridge* selfp = sSelf.get();
- // Only enable calling-card related options for non-default folders.
- if (!is_default_folder)
+ if (selfp && selfp->mRoot)
{
- LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
- if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
- {
- mItems.push_back(std::string("Calling Card Separator"));
- mItems.push_back(std::string("Conference Chat Folder"));
- mItems.push_back(std::string("IM All Contacts In Folder"));
- }
- }
-
- // wearables related functionality for folders.
- //is_wearable
- LLFindWearables is_wearable;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
- if (mWearables ||
- checkFolderForContentsOfType(model, is_wearable) ||
- checkFolderForContentsOfType(model, is_object) ||
- checkFolderForContentsOfType(model, is_gesture) )
- {
- mItems.push_back(std::string("Folder Wearables Separator"));
-
- // Only enable add/replace outfit for non-default folders.
- if (!is_default_folder)
- {
- mItems.push_back(std::string("Add To Outfit"));
- mItems.push_back(std::string("Replace Outfit"));
- }
- if (is_ensemble)
- {
- mItems.push_back(std::string("Wear As Ensemble"));
- }
- mItems.push_back(std::string("Take Off Items"));
+ selfp->mRoot->updateMenu();
}
- hideContextEntries(*mMenu, mItems, disabled_items);
}
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@@ -2350,137 +3399,266 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
item_array,
LLInventoryModel::EXCLUDE_TRASH,
is_type);
- return ((item_array.count() > 0) ? TRUE : FALSE );
+ return ((item_array.size() > 0) ? TRUE : FALSE );
}
-// Flags unused
-void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items)
{
- mItems.clear();
- mDisabledItems.clear();
-
- lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
-// std::vector<std::string> disabled_items;
LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ llassert(model != NULL);
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ const LLUUID favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
- mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
- mDisabledItems.clear(); //adding code to clear out disabled members from previous
if (lost_and_found_id == mUUID)
- {
+ {
// This is the lost+found folder.
- mItems.push_back(std::string("Empty Lost And Found"));
- }
+ items.push_back(std::string("Empty Lost And Found"));
+ disabled_items.push_back(std::string("New Folder"));
+ disabled_items.push_back(std::string("New Script"));
+ disabled_items.push_back(std::string("New Note"));
+ disabled_items.push_back(std::string("New Gesture"));
+ disabled_items.push_back(std::string("New Clothes"));
+ disabled_items.push_back(std::string("New Body Parts"));
+ }
+ if (favorites == mUUID)
+ {
+ disabled_items.push_back(std::string("New Folder"));
+ }
if(trash_id == mUUID)
{
// This is the trash.
- mItems.push_back(std::string("Empty Trash"));
+ items.push_back(std::string("Empty Trash"));
}
- else if(model->isObjectDescendentOf(mUUID, trash_id))
+ else if(isItemInTrash())
{
// This is a folder in the trash.
- mItems.clear(); // clear any items that used to exist
- mItems.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- mDisabledItems.push_back(std::string("Purge Item"));
- }
-
- mItems.push_back(std::string("Restore Item"));
+ items.clear(); // clear any items that used to exist
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else if(isAgentInventory()) // do not allow creating in library
{
- LLViewerInventoryCategory *cat = getCategory();
-
+ LLViewerInventoryCategory *cat = getCategory();
// BAP removed protected check to re-enable standard ops in untyped folders.
// Not sure what the right thing is to do here.
- if (!isCOFFolder() && cat /*&&
- LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
- {
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
- mItems.push_back(std::string("Change Type"));
-
- LLViewerInventoryCategory *cat = getCategory();
- if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
+ {
+ if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox
{
- mDisabledItems.push_back(std::string("Change Type"));
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ {
+ items.push_back(std::string("New Folder"));
+ }
+
+ items.push_back(std::string("New Script"));
+ items.push_back(std::string("New Note"));
+ items.push_back(std::string("New Gesture"));
+ items.push_back(std::string("New Clothes"));
+ items.push_back(std::string("New Body Parts"));
}
-
- getClipboardEntries(false, mItems, mDisabledItems, flags);
+ getClipboardEntries(false, items, disabled_items, flags);
}
else
{
// Want some but not all of the items from getClipboardEntries for outfits.
- if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT)
+ if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
{
- mItems.push_back(std::string("Rename"));
- mItems.push_back(std::string("Delete"));
+ items.push_back(std::string("Rename"));
+
+ addDeleteContextMenuOptions(items, disabled_items);
+ // EXT-4030: disallow deletion of currently worn outfit
+ const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
+ if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
}
}
- //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
+ //Added by aura to force inventory pull on right-click to display folder options correctly. 07-17-06
mCallingCards = mWearables = FALSE;
-
+
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
if (checkFolderForContentsOfType(model, is_callingcard))
{
mCallingCards=TRUE;
}
-
+
LLFindWearables is_wearable;
LLIsType is_object( LLAssetType::AT_OBJECT );
LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
+
if (checkFolderForContentsOfType(model, is_wearable) ||
checkFolderForContentsOfType(model, is_object) ||
checkFolderForContentsOfType(model, is_gesture) )
{
mWearables=TRUE;
}
-
- mMenu = &menu;
- sSelf = this;
- LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
+ }
- LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- if (category)
+ // Preemptively disable system folder removal if more than one item selected.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Delete System Folder"));
+ }
+
+ if (!isOutboxFolder())
+ {
+ items.push_back(std::string("Share"));
+ if (!canShare())
{
- folders.push_back(category->getUUID());
+ disabled_items.push_back(std::string("Share"));
}
- fetch->fetchDescendents(folders);
- inc_busy_count();
- if(fetch->isEverythingComplete())
+ }
+ // Add menu items that are dependent on the contents of the folder.
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID);
+ if (category)
+ {
+ uuid_vec_t folders;
+ folders.push_back(category->getUUID());
+
+ sSelf = getHandle();
+ LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders);
+ fetch->startFetch();
+ if (fetch->isFinished())
{
- // everything is already here - call done.
- fetch->done();
+ // Do not call execute() or done() here as if the folder is here, there's likely no point drilling down
+ // This saves lots of time as buildContextMenu() is called a lot
+ delete fetch;
+ buildContextMenuFolderOptions(flags, items, disabled_items);
}
else
{
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
+ // it's all on its way - add an observer, and the inventory will call done for us when everything is here.
gInventory.addObserver(fetch);
+ }
+}
+}
+
+void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items)
+{
+ // Build folder specific options back up
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ const LLInventoryCategory* category = model->getCategory(mUUID);
+ if(!category) return;
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if (trash_id == mUUID) return;
+ if (isItemInTrash()) return;
+ if (!isAgentInventory()) return;
+ if (isOutboxFolder()) return;
+
+ LLFolderType::EType type = category->getPreferredType();
+ const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
+ // BAP change once we're no longer treating regular categories as ensembles.
+ const bool is_ensemble = (type == LLFolderType::FT_NONE ||
+ LLFolderType::lookupIsEnsembleType(type));
+
+ // Only enable calling-card related options for non-system folders.
+ if (!is_system_folder)
+ {
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
+ {
+ items.push_back(std::string("Calling Card Separator"));
+ items.push_back(std::string("Conference Chat Folder"));
+ items.push_back(std::string("IM All Contacts In Folder"));
}
}
- else
+
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (LLFolderType::lookupIsProtectedType(type))
+ {
+ items.push_back(std::string("Delete System Folder"));
+ }
+#endif
+
+ // wearables related functionality for folders.
+ //is_wearable
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (mWearables ||
+ checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
{
- mItems.push_back(std::string("--no options--"));
- mDisabledItems.push_back(std::string("--no options--"));
+ items.push_back(std::string("Folder Wearables Separator"));
+
+ // Only enable add/replace outfit for non-system folders.
+ if (!is_system_folder)
+ {
+ // Adding an outfit onto another (versus replacing) doesn't make sense.
+ if (type != LLFolderType::FT_OUTFIT)
+ {
+ items.push_back(std::string("Add To Outfit"));
+ }
+
+ items.push_back(std::string("Replace Outfit"));
+ }
+ if (is_ensemble)
+ {
+ items.push_back(std::string("Wear As Ensemble"));
+ }
+ items.push_back(std::string("Remove From Outfit"));
+ if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
+ {
+ disabled_items.push_back(std::string("Remove From Outfit"));
+ }
+ if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
+ {
+ disabled_items.push_back(std::string("Replace Outfit"));
+ }
+ if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID))
+ {
+ disabled_items.push_back(std::string("Add To Outfit"));
+ }
+ items.push_back(std::string("Outfit Separator"));
}
- hideContextEntries(menu, mItems, mDisabledItems);
}
-BOOL LLFolderBridge::hasChildren() const
+// Flags unused
+void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ sSelf.markDead();
+
+ // fetch contents of this folder, as context menu can depend on contents
+ // still, user would have to open context menu again to see the changes
+ gInventory.fetchDescendentsOf(getUUID());
+
+
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+
+ LL_DEBUGS() << "LLFolderBridge::buildContextMenu()" << LL_ENDL;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ buildContextMenuOptions(flags, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
+
+ // Reposition the menu, in case we're adding items to an existing menu.
+ menu.needsArrange();
+ menu.arrangeAndClear();
+}
+
+bool LLFolderBridge::hasChildren() const
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
@@ -2491,9 +3669,12 @@ BOOL LLFolderBridge::hasChildren() const
BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
- void* cargo_data)
+ void* cargo_data,
+ std::string& tooltip_msg)
{
- //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
+ LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
+
+ //LL_INFOS() << "LLFolderBridge::dragOrDrop()" << LL_ENDL;
BOOL accept = FALSE;
switch(cargo_type)
{
@@ -2502,15 +3683,31 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_CALLINGCARD:
case DAD_LANDMARK:
case DAD_SCRIPT:
+ case DAD_CLOTHING:
case DAD_OBJECT:
case DAD_NOTECARD:
- case DAD_CLOTHING:
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
+ case DAD_MESH:
+ accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
+ break;
case DAD_LINK:
- accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
- drop);
+ // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER.
+ // If we have an item of AT_LINK_FOLDER type we should process the linked
+ // category being dragged or dropped into folder.
+ if (inv_item && LLAssetType::AT_LINK_FOLDER == inv_item->getActualType())
+ {
+ LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID());
+ if (linked_category)
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg);
+ }
+ }
+ else
+ {
+ accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
+ }
break;
case DAD_CATEGORY:
if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
@@ -2519,10 +3716,14 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
}
else
{
- accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop, tooltip_msg);
}
break;
+ case DAD_ROOT_CATEGORY:
+ case DAD_NONE:
+ break;
default:
+ LL_WARNS() << "Unhandled cargo type for drag&drop " << cargo_type << LL_ENDL;
break;
}
return accept;
@@ -2547,111 +3748,95 @@ void LLFolderBridge::pasteClipboard(void* user_data)
if(self) self->pasteFromClipboard();
}
-void LLFolderBridge::createNewCategory(void* user_data)
-{
- LLFolderBridge* bridge = (LLFolderBridge*)user_data;
- if(!bridge) return;
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
- if (!panel) return;
- LLInventoryModel* model = panel->getModel();
- if(!model) return;
- LLUUID id;
- id = model->createNewCategory(bridge->getUUID(),
- LLAssetType::AT_NONE,
- LLStringUtil::null);
- model->notifyObservers();
-
- // At this point, the bridge has probably been deleted, but the
- // view is still there.
- panel->setSelection(id, TAKE_FOCUS_YES);
-}
-
void LLFolderBridge::createNewShirt(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT);
}
void LLFolderBridge::createNewPants(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_PANTS);
}
void LLFolderBridge::createNewShoes(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHOES);
}
void LLFolderBridge::createNewSocks(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SOCKS);
}
void LLFolderBridge::createNewJacket(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_JACKET);
}
void LLFolderBridge::createNewSkirt(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SKIRT);
}
void LLFolderBridge::createNewGloves(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_GLOVES);
}
void LLFolderBridge::createNewUndershirt(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_UNDERSHIRT);
}
void LLFolderBridge::createNewUnderpants(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_UNDERPANTS);
}
void LLFolderBridge::createNewShape(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHAPE);
}
void LLFolderBridge::createNewSkin(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SKIN);
}
void LLFolderBridge::createNewHair(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_HAIR);
}
void LLFolderBridge::createNewEyes(void* user_data)
{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES);
}
-// static
-void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
+EInventorySortGroup LLFolderBridge::getSortGroup() const
{
- if(!bridge) return;
- LLUUID parent_id = bridge->getUUID();
- createWearable(parent_id, type);
+ LLFolderType::EType preferred_type = getPreferredType();
+
+ if (preferred_type == LLFolderType::FT_TRASH)
+ {
+ return SG_TRASH_FOLDER;
+ }
+
+ if(LLFolderType::lookupIsProtectedType(preferred_type))
+ {
+ return SG_SYSTEM_FOLDER;
+ }
+
+ return SG_NORMAL_FOLDER;
}
-// Separate function so can be called by global menu as well as right-click
-// menu.
+
// static
-void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type)
+void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type)
{
- LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
- LLAssetType::EType asset_type = wearable->getAssetType();
- LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
- create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
- parent_id, wearable->getTransactionID(), wearable->getName(),
- wearable->getDescription(), asset_type, inv_type, wearable->getType(),
- wearable->getPermissions().getMaskNextOwner(),
- LLPointer<LLInventoryCallback>(NULL));
+ if(!bridge) return;
+ LLUUID parent_id = bridge->getUUID();
+ LLAgentWearables::createWearable(type, false, parent_id);
}
void LLFolderBridge::modifyOutfit(BOOL append)
@@ -2660,10 +3845,27 @@ void LLFolderBridge::modifyOutfit(BOOL append)
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
- // BAP - was:
- // wear_inventory_category_on_avatar( cat, append );
- LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
+
+ // checking amount of items to wear
+ U32 max_items = gSavedSettings.getU32("WearFolderLimit");
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
+ gInventory.collectDescendentsIf(cat->getUUID(),
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ not_worn);
+
+ if (items.size() > max_items)
+ {
+ LLSD args;
+ args["AMOUNT"] = llformat("%d", max_items);
+ LLNotificationsUtil::add("TooManyWearables", args);
+ return;
+ }
+
+ LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append );
}
// helper stuff
@@ -2671,24 +3873,25 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
{
LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(option == 0 && object)
{
- if (cat_and_wear && cat_and_wear->mWear)
+ if (cat_and_wear && cat_and_wear->mWear) // && !cat_and_wear->mFolderResponded)
{
- InventoryObjectList inventory_objects;
+ LLInventoryObject::object_list_t inventory_objects;
object->getInventoryContents(inventory_objects);
int contents_count = inventory_objects.size()-1; //subtract one for containing folder
-
- LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
+ LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded,
+ cat_and_wear->mReplace);
+
gInventory.addObserver(inventoryObserver);
}
two_uuids_list_t::iterator move_it;
- for (move_it = move_inv->mMoveList.begin();
- move_it != move_inv->mMoveList.end();
- ++move_it)
+ for (move_it = move_inv->mMoveList.begin();
+ move_it != move_inv->mMoveList.end();
+ ++move_it)
{
object->moveInventory(move_it->first, move_it->second);
}
@@ -2706,209 +3909,316 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
return false;
}
-/*
-Next functions intended to reorder items in the inventory folder and save order on server
-Is now used for Favorites folder.
-
-*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
-*/
-void saveItemsOrder(LLInventoryModel::item_array_t& items)
+// Returns true if the item can be moved to Current Outfit or any outfit folder.
+static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
{
- int sortField = 0;
-
- // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
- for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) &&
+ (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) &&
+ (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) &&
+ (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT))
{
- LLViewerInventoryItem* item = *i;
+ return FALSE;
+ }
- item->setSortField(++sortField);
- item->setComplete(TRUE);
- item->updateServer(FALSE);
+ U32 flags = inv_item->getFlags();
+ if(flags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
+ {
+ return FALSE;
+ }
- gInventory.updateItem(item);
+ if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID()))
+ {
+ return FALSE;
}
- gInventory.notifyObservers();
+ return TRUE;
}
-LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+// Returns TRUE if item is a landmark or a link to a landmark
+// and can be moved to Favorites or Landmarks folder.
+static BOOL can_move_to_landmarks(LLInventoryItem* inv_item)
{
- LLInventoryModel::item_array_t::iterator result = items.end();
-
- for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ // Need to get the linked item to know its type because LLInventoryItem::getType()
+ // returns actual type AT_LINK for links, not the asset type of a linked item.
+ if (LLAssetType::AT_LINK == inv_item->getType())
{
- if ((*i)->getUUID() == id)
+ LLInventoryItem* linked_item = gInventory.getItem(inv_item->getLinkedUUID());
+ if (linked_item)
{
- result = i;
- break;
+ return LLAssetType::AT_LANDMARK == linked_item->getType();
}
}
- return result;
+ return LLAssetType::AT_LANDMARK == inv_item->getType();
}
-void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
{
- LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
- LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+ // use callback to rearrange favorite landmarks after adding
+ // to have new one placed before target (on which it was dropped). See EXT-4312.
+ LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();
+ LLInventoryPanel* panel = mInventoryPanel.get();
+ LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ LLFolderViewModelItemInventory* view_model = drag_over_item ? static_cast<LLFolderViewModelItemInventory*>(drag_over_item->getViewModelItem()) : NULL;
+ if (view_model)
+ {
+ cb.get()->setTargetLandmarkId(view_model->getUUID());
+ }
- items.erase(findItemByUUID(items, srcItem->getUUID()));
- items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ cb);
+}
+
+void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
+{
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceMgr::instance().wearItemOnAvatar(inv_item->getUUID(), true, true);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
+ }
}
+// This is used both for testing whether an item can be dropped
+// into the folder, as well as performing the actual drop, depending
+// if drop == TRUE.
BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
- BOOL drop)
+ BOOL drop,
+ std::string& tooltip_msg)
{
LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- // cannot drag into library
- if(!isAgentInventory())
- {
- return FALSE;
- }
+ if (!model || !inv_item) return FALSE;
+ if (!isAgentInventory()) return FALSE; // cannot drag into library
+ if (!isAgentAvatarValid()) return FALSE;
+
+ LLInventoryPanel* destination_panel = mInventoryPanel.get();
+ if (!destination_panel) return false;
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
+ LLInventoryFilter* filter = getInventoryFilter();
+ if (!filter) return false;
+
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
+ const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
+ const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+ const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
+
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_favorites = (mUUID == favorites_id);
+ const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
+ const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
+ const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id);
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
BOOL accept = FALSE;
+ U64 filter_types = filter->getFilterTypes();
+ // We shouldn't allow to drop non recent items into recent tab (or some similar transactions)
+ // while we are allowing to interact with regular filtered inventory
+ BOOL use_filter = filter_types && (filter_types&LLInventoryFilter::FILTERTYPE_DATE || (filter_types&LLInventoryFilter::FILTERTYPE_OBJECT)==0);
LLViewerObject* object = NULL;
if(LLToolDragAndDrop::SOURCE_AGENT == source)
{
+ const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
+
+ const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID());
+
+ //--------------------------------------------------------------------------------
+ // Determine if item can be moved.
+ //
BOOL is_movable = TRUE;
- switch( inv_item->getActualType() )
+
+ switch (inv_item->getActualType())
+ {
+ case LLAssetType::AT_CATEGORY:
+ is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType());
+ break;
+ default:
+ break;
+ }
+ // Can't explicitly drag things out of the COF.
+ if (move_is_outof_current_outfit)
{
- case LLAssetType::AT_ROOT_CATEGORY:
is_movable = FALSE;
- break;
-
- case LLAssetType::AT_CATEGORY:
- is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType());
- break;
- default:
- break;
+ }
+ if (move_is_into_trash)
+ {
+ is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID());
+ }
+ if (is_movable)
+ {
+ // Don't allow creating duplicates in the Calling Card/Friends
+ // subfolders, see bug EXT-1599. Check is item direct descendent
+ // of target folder and forbid item's movement if it so.
+ // Note: isItemDirectDescendentOfCategory checks if
+ // passed category is in the Calling Card/Friends folder
+ is_movable &= !LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(inv_item, getCategory());
}
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
- LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
+ //
+ //--------------------------------------------------------------------------------
- if(is_movable && move_is_into_trash)
+ //--------------------------------------------------------------------------------
+ // Determine if item can be moved & dropped
+ //
+
+ accept = TRUE;
+
+ if (!is_movable)
{
- switch(inv_item->getType())
+ accept = FALSE;
+ }
+ else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites)
+ {
+ accept = FALSE;
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
+ }
+ else if (move_is_into_favorites || move_is_into_landmarks)
+ {
+ accept = can_move_to_landmarks(inv_item);
+ }
+ else if (move_is_into_outbox)
+ {
+ accept = can_move_to_outbox(inv_item, tooltip_msg);
+
+ if (accept)
{
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID(), TRUE);
- break;
-
- case LLAssetType::AT_OBJECT:
- is_movable = !avatar->isWearingAttachment(inv_item->getUUID(), TRUE);
- break;
- default:
- break;
+ const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
+
+ int existing_item_count = LLToolDragAndDrop::instance().getCargoCount();
+
+ if (master_folder != NULL)
+ {
+ LLInventoryModel::cat_array_t existing_categories;
+ LLInventoryModel::item_array_t existing_items;
+
+ gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE);
+
+ existing_item_count += existing_items.size();
+ }
+
+ if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects");
+ accept = FALSE;
+ }
}
}
-
- LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
- // we can move item inside a folder only if this folder is Favorites. See EXT-719
- accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
- if(accept && drop)
+ LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+
+ // Check whether the item being dragged from active inventory panel
+ // passes the filter of the destination panel.
+ if (accept && active_panel && use_filter)
+ {
+ LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID());
+ if (!fv_item) return false;
+
+ accept = filter->check(fv_item->getViewModelItem());
+ }
+
+ if (accept && drop)
{
if (inv_item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
+ && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
{
- LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
+ LLGestureMgr::instance().deactivateGesture(inv_item->getUUID());
}
- // If an item is being dragged between windows, unselect
- // everything in the active window so that we don't follow
- // the selection to its new location (which is very
- // annoying).
- if (LLFloaterInventory::getActiveInventory())
- {
- LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- if (active_panel && (panel != active_panel))
+ // If an item is being dragged between windows, unselect everything in the active window
+ // so that we don't follow the selection to its new location (which is very annoying).
+ // RN: a better solution would be to deselect automatically when an item is moved
+ // and then select any item that is dropped only in the panel that it is dropped in
+ if (active_panel && (destination_panel != active_panel))
{
active_panel->unSelectAll();
}
- }
- // if dragging from/into favorites folder only reorder items
- if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
- {
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- LLIsType is_type(LLAssetType::AT_LANDMARK);
- model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+ //--------------------------------------------------------------------------------
+ // Destination folder logic
+ //
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ // REORDER
+ // (only reorder the item in Favorites folder)
+ if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites)
+ {
+ LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem();
if (itemp)
{
LLUUID srcItemId = inv_item->getUUID();
- LLUUID destItemId = itemp->getListener()->getUUID();
-
- // update order
- updateItemsOrder(items, srcItemId, destItemId);
-
- saveItemsOrder(items);
+ LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID();
+ LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId);
}
}
- else if (favorites_id == mUUID) // if target is the favorites folder we use copy
+
+ // FAVORITES folder
+ // (copy the item)
+ else if (move_is_into_favorites)
{
- copy_inventory_item(
- gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
+ dropToFavorites(inv_item);
}
+ // CURRENT OUTFIT or OUTFIT folder
+ // (link the item)
else if (move_is_into_current_outfit || move_is_into_outfit)
{
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
+ dropToOutfit(inv_item, move_is_into_current_outfit);
+ }
+ else if (move_is_into_outbox)
+ {
+ if (move_is_from_outbox)
{
- LLAppearanceManager::wearItem(inv_item);
+ move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId());
}
else
{
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLAssetType::AT_LINK,
- cb);
+ copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId());
}
}
+ // NORMAL or TRASH folder
+ // (move the item, restamp if into trash)
else
{
- // restamp if the move is into the trash.
+ // set up observer to select item once drag and drop from inbox is complete
+ if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))
+ {
+ set_dad_inbox_object(inv_item->getUUID());
+ }
+
LLInvFVBridge::changeItemParent(
model,
(LLViewerInventoryItem*)inv_item,
mUUID,
move_is_into_trash);
}
+
+ //
+ //--------------------------------------------------------------------------------
}
}
- else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ else if (LLToolDragAndDrop::SOURCE_WORLD == source)
{
// Make sure the object exists. If we allowed dragging from
// anonymous objects, it would be possible to bypass
// permissions.
object = gObjectList.findObject(inv_item->getParentUUID());
- if(!object)
+ if (!object)
{
- llinfos << "Object not found for drop." << llendl;
+ LL_INFOS() << "Object not found for drop." << LL_ENDL;
return FALSE;
}
@@ -2916,10 +4226,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// move/copy this item.
LLPermissions perm(inv_item->getPermissions());
BOOL is_move = FALSE;
- if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
&& perm.allowTransferTo(gAgent.getID())))
-// || gAgent.isGodlike())
-
+ // || gAgent.isGodlike())
{
accept = TRUE;
}
@@ -2931,7 +4240,35 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
is_move = TRUE;
accept = TRUE;
}
- if(drop && accept)
+
+ // Don't allow placing an original item into Current Outfit or an outfit folder
+ // because they must contain only links to wearable items.
+ // *TODO: Probably we should create a link to an item if it was dragged to outfit or COF.
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ accept = FALSE;
+ }
+ // Don't allow to move a single item to Favorites or Landmarks
+ // if it is not a landmark or a link to a landmark.
+ else if ((move_is_into_favorites || move_is_into_landmarks)
+ && !can_move_to_landmarks(inv_item))
+ {
+ accept = FALSE;
+ }
+ else if (move_is_into_outbox)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+ accept = FALSE;
+ }
+
+ // Check whether the item being dragged from in world
+ // passes the filter of the destination panel.
+ if (accept && use_filter)
+ {
+ accept = filter->check(inv_item);
+ }
+
+ if (accept && drop)
{
LLMoveInv* move_inv = new LLMoveInv;
move_inv->mObjectID = inv_item->getParentUUID();
@@ -2945,54 +4282,174 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else
{
+ // store dad inventory item to select added one later. See EXT-4347
+ set_dad_inventory_item(inv_item, mUUID);
+
LLNotification::Params params("MoveInventoryFromObject");
params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
LLNotifications::instance().forceResponse(params, 0);
}
}
-
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
- accept = TRUE;
- if(drop)
+ if (move_is_into_outbox)
{
- copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
- LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
+ tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+ accept = FALSE;
+ }
+ else
+ {
+ // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder
+ // because they must contain only links to wearable items.
+ accept = !(move_is_into_current_outfit || move_is_into_outfit);
+ }
+
+ // Check whether the item being dragged from notecard
+ // passes the filter of the destination panel.
+ if (accept && use_filter)
+ {
+ accept = filter->check(inv_item);
+ }
+
+ if (accept && drop)
+ {
+ copy_inventory_from_notecard(mUUID, // Drop to the chosen destination folder
+ LLToolDragAndDrop::getInstance()->getObjectID(),
+ LLToolDragAndDrop::getInstance()->getSourceID(),
+ inv_item);
}
}
else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
- if(item && item->isComplete())
+ if(item && item->isFinished())
{
accept = TRUE;
- if(drop)
+
+ if (move_is_into_outbox)
{
- copy_inventory_item(
- gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
+ tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+ accept = FALSE;
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
+ }
+ // Don't allow to move a single item to Favorites or Landmarks
+ // if it is not a landmark or a link to a landmark.
+ else if (move_is_into_favorites || move_is_into_landmarks)
+ {
+ accept = can_move_to_landmarks(inv_item);
+ }
+
+ LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+
+ // Check whether the item being dragged from the library
+ // passes the filter of the destination panel.
+ if (accept && active_panel && use_filter)
+ {
+ LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID());
+ if (!fv_item) return false;
+
+ accept = filter->check(fv_item->getViewModelItem());
+ }
+
+ if (accept && drop)
+ {
+ // FAVORITES folder
+ // (copy the item)
+ if (move_is_into_favorites)
+ {
+ dropToFavorites(inv_item);
+ }
+ // CURRENT OUTFIT or OUTFIT folder
+ // (link the item)
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ dropToOutfit(inv_item, move_is_into_current_outfit);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
}
}
}
else
{
- llwarns << "unhandled drag source" << llendl;
+ LL_WARNS() << "unhandled drag source" << LL_ENDL;
}
return accept;
}
-// +=================================================+
-// | LLScriptBridge (DEPRECTED) |
-// +=================================================+
+// static
+bool check_category(LLInventoryModel* model,
+ const LLUUID& cat_id,
+ LLInventoryPanel* active_panel,
+ LLInventoryFilter* filter)
+{
+ if (!model || !active_panel || !filter)
+ return false;
+
+ if (!filter->checkFolder(cat_id))
+ {
+ return false;
+ }
+
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ model->collectDescendents(cat_id, descendent_categories, descendent_items, TRUE);
-LLUIImagePtr LLScriptBridge::getIcon() const
+ S32 num_descendent_categories = descendent_categories.size();
+ S32 num_descendent_items = descendent_items.size();
+
+ if (num_descendent_categories + num_descendent_items == 0)
+ {
+ // Empty folder should be checked as any other folder view item.
+ // If we are filtering by date the folder should not pass because
+ // it doesn't have its own creation date. See LLInvFVBridge::getCreationDate().
+ return check_item(cat_id, active_panel, filter);
+ }
+
+ for (S32 i = 0; i < num_descendent_categories; ++i)
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(!check_category(model, category->getUUID(), active_panel, filter))
+ {
+ return false;
+ }
+ }
+
+ for (S32 i = 0; i < num_descendent_items; ++i)
+ {
+ LLViewerInventoryItem* item = descendent_items[i];
+ if(!check_item(item->getUUID(), active_panel, filter))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// static
+bool check_item(const LLUUID& item_id,
+ LLInventoryPanel* active_panel,
+ LLInventoryFilter* filter)
{
- return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+ if (!active_panel || !filter) return false;
+
+ LLFolderViewItem* fv_item = active_panel->getItemByID(item_id);
+ if (!fv_item) return false;
+
+ return filter->check(fv_item->getViewModelItem());
}
// +=================================================+
@@ -3001,56 +4458,96 @@ LLUIImagePtr LLScriptBridge::getIcon() const
LLUIImagePtr LLTextureBridge::getIcon() const
{
- return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
+ return LLInventoryIcon::getIcon(LLAssetType::AT_TEXTURE, mInvType);
}
-
+
void LLTextureBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
}
-// +=================================================+
-// | LLSoundBridge |
-// +=================================================+
-
-LLUIImagePtr LLSoundBridge::getIcon() const
+bool LLTextureBridge::canSaveTexture(void)
{
- return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return false;
+ }
+
+ const LLViewerInventoryItem *item = model->getItem(mUUID);
+ if (item)
+ {
+ return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
+ }
+ return false;
}
-void LLSoundBridge::openItem()
+void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
+ LL_DEBUGS() << "LLTextureBridge::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ if(isItemInTrash())
{
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
-/*
-// Changed this back to the way it USED to work:
-// only open the preview dialog through the contextual right-click menu
-// double-click just plays the sound
+ else
+ {
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
- LLViewerInventoryItem* item = getItem();
- if(item)
+ addOpenRightClickMenuOption(items);
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Texture Separator"));
+ items.push_back(std::string("Save As"));
+ if (!canSaveTexture())
+ {
+ disabled_items.push_back(std::string("Save As"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// virtual
+void LLTextureBridge::performAction(LLInventoryModel* model, std::string action)
+{
+ if ("save_as" == action)
{
- openSoundPreview((void*)this);
- //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
+ LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ preview_texture->saveAs();
+ }
}
-*/
+ else LLItemBridge::performAction(model, action);
}
-void LLSoundBridge::previewItem()
+// +=================================================+
+// | LLSoundBridge |
+// +=================================================+
+
+void LLSoundBridge::openItem()
{
- LLViewerInventoryItem* item = getItem();
- if(item)
+ const LLViewerInventoryItem* item = getItem();
+ if (item)
{
- send_sound_trigger(item->getAssetUUID(), 1.0);
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
}
@@ -3062,43 +4559,69 @@ void LLSoundBridge::openSoundPreview(void* which)
void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
+ LL_DEBUGS() << "LLSoundBridge::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
- if(isInTrash())
+ if (isOutboxFolder())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else
{
- items.push_back(std::string("Sound Open"));
- items.push_back(std::string("Properties"));
+ if (isItemInTrash())
+ {
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else
+ {
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+ items.push_back(std::string("Sound Open"));
+ items.push_back(std::string("Properties"));
- getClipboardEntries(true, items, disabled_items, flags);
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Sound Separator"));
+ items.push_back(std::string("Sound Play"));
}
- items.push_back(std::string("Sound Separator"));
- items.push_back(std::string("Sound Play"));
+ hide_context_entries(menu, items, disabled_items);
+}
- hideContextEntries(menu, items, disabled_items);
+void LLSoundBridge::performAction(LLInventoryModel* model, std::string action)
+{
+ if ("sound_play" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
+ }
+ }
+ else if ("open" == action)
+ {
+ openSoundPreview((void*)this);
+ }
+ else LLItemBridge::performAction(model, action);
}
// +=================================================+
// | LLLandmarkBridge |
// +=================================================+
-LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
-LLItemBridge(inventory, uuid)
+LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid,
+ U32 flags/* = 0x00*/) :
+ LLItemBridge(inventory, root, uuid)
{
mVisited = FALSE;
- if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
+ if (flags & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED)
{
mVisited = TRUE;
}
@@ -3106,45 +4629,54 @@ LLItemBridge(inventory, uuid)
LLUIImagePtr LLLandmarkBridge::getIcon() const
{
- return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
+ return LLInventoryIcon::getIcon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
}
void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
- lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
- if(isInTrash())
+ LL_DEBUGS() << "LLLandmarkBridge::buildContextMenu()" << LL_ENDL;
+ if(isOutboxFolder())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else
{
- items.push_back(std::string("Landmark Open"));
- items.push_back(std::string("Properties"));
+ if(isItemInTrash())
+ {
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else
+ {
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+ items.push_back(std::string("Landmark Open"));
+ items.push_back(std::string("Properties"));
- getClipboardEntries(true, items, disabled_items, flags);
- }
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
- items.push_back(std::string("Landmark Separator"));
- items.push_back(std::string("About Landmark"));
+ items.push_back(std::string("Landmark Separator"));
+ items.push_back(std::string("url_copy"));
+ items.push_back(std::string("About Landmark"));
+ items.push_back(std::string("show_on_map"));
+ }
// Disable "About Landmark" menu item for
// multiple landmarks selected. Only one landmark
// info panel can be shown at a time.
if ((flags & FIRST_SELECTED_ITEM) == 0)
{
+ disabled_items.push_back(std::string("url_copy"));
disabled_items.push_back(std::string("About Landmark"));
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// Convenience function for the two functions below.
@@ -3162,7 +4694,7 @@ void teleport_via_landmark(const LLUUID& asset_id)
}
// virtual
-void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLLandmarkBridge::performAction(LLInventoryModel* model, std::string action)
{
if ("teleport" == action)
{
@@ -3181,18 +4713,18 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
key["type"] = "landmark";
key["id"] = item->getUUID();
- LLSideTray::getInstance()->showPanel("panel_places", key);
+ LLFloaterSidePanelContainer::showPanel("places", key);
}
}
- else
+ else
{
- LLItemBridge::performAction(folder, model, action);
+ LLItemBridge::performAction(model, action);
}
}
static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
if (option == 0)
@@ -3208,40 +4740,42 @@ static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFro
void LLLandmarkBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
-/*
- LLViewerInventoryItem* item = getItem();
- if( item )
- {
- // Opening (double-clicking) a landmark immediately teleports,
- // but warns you the first time.
- // open_landmark(item);
- LLSD payload;
- payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
- }
-*/
}
// +=================================================+
// | LLCallingCardObserver |
// +=================================================+
-void LLCallingCardObserver::changed(U32 mask)
+class LLCallingCardObserver : public LLFriendObserver
{
- mBridgep->refreshFolderViewItem();
-}
+public:
+ LLCallingCardObserver(LLCallingCardBridge* bridge) : mBridgep(bridge) {}
+ virtual ~LLCallingCardObserver() { mBridgep = NULL; }
+ virtual void changed(U32 mask)
+ {
+ mBridgep->refreshFolderViewItem();
+ if (mask & LLFriendObserver::ONLINE)
+ {
+ mBridgep->checkSearchBySuffixChanges();
+ }
+ }
+protected:
+ LLCallingCardBridge* mBridgep;
+};
// +=================================================+
// | LLCallingCardBridge |
// +=================================================+
-LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
- LLItemBridge(inventory, uuid)
+LLCallingCardBridge::LLCallingCardBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid ) :
+ LLItemBridge(inventory, root, uuid)
{
mObserver = new LLCallingCardObserver(this);
LLAvatarTracker::instance().addObserver(mObserver);
@@ -3255,16 +4789,54 @@ LLCallingCardBridge::~LLCallingCardBridge()
void LLCallingCardBridge::refreshFolderViewItem()
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
+ LLInventoryPanel* panel = mInventoryPanel.get();
+ LLFolderViewItem* itemp = panel ? panel->getItemByID(mUUID) : NULL;
if (itemp)
{
itemp->refresh();
}
}
+void LLCallingCardBridge::checkSearchBySuffixChanges()
+{
+ if (!mDisplayName.empty())
+ {
+ // changes in mDisplayName are processed by rename function and here it will be always same
+ // suffixes are also of fixed length, and we are processing change of one at a time,
+ // so it should be safe to use length (note: mSearchableName is capitalized)
+ S32 old_length = mSearchableName.length();
+ S32 new_length = mDisplayName.length() + getLabelSuffix().length();
+ if (old_length == new_length)
+ {
+ return;
+ }
+ mSearchableName.assign(mDisplayName);
+ mSearchableName.append(getLabelSuffix());
+ LLStringUtil::toUpper(mSearchableName);
+ if (new_length<old_length)
+ {
+ LLInventoryFilter* filter = getInventoryFilter();
+ if (filter && mPassedFilter && mSearchableName.find(filter->getFilterSubString()) == std::string::npos)
+ {
+ // string no longer contains substring
+ // we either have to update all parents manually or restart filter.
+ // dirtyFilter will not work here due to obsolete descendants' generations
+ getInventoryFilter()->setModified(LLFolderViewFilter::FILTER_MORE_RESTRICTIVE);
+ }
+ }
+ else
+ {
+ if (getInventoryFilter())
+ {
+ // mSearchableName became longer, we gained additional suffix and need to repeat filter check.
+ dirtyFilter();
+ }
+ }
+ }
+}
+
// virtual
-void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string action)
{
if ("begin_im" == action)
{
@@ -3272,9 +4844,17 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel*
if (item && (item->getCreatorUUID() != gAgent.getID()) &&
(!item->getCreatorUUID().isNull()))
{
- std::string callingcard_name;
- gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
- gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ std::string callingcard_name = LLCacheName::getDefaultName();
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(item->getCreatorUUID(), &av_name))
+ {
+ callingcard_name = av_name.getCompleteName();
+ }
+ LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ if (session_id != LLUUID::null)
+ {
+ LLFloaterIMContainer::getInstance()->showConversation(session_id);
+ }
}
}
else if ("lure" == action)
@@ -3286,7 +4866,17 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel*
LLAvatarActions::offerTeleport(item->getCreatorUUID());
}
}
- else LLItemBridge::performAction(folder, model, action);
+ else if ("request_lure" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ LLAvatarActions::teleportRequest(item->getCreatorUUID());
+ }
+ }
+
+ else LLItemBridge::performAction(model, action);
}
LLUIImagePtr LLCallingCardBridge::getIcon() const
@@ -3297,7 +4887,7 @@ LLUIImagePtr LLCallingCardBridge::getIcon() const
{
online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
}
- return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
+ return LLInventoryIcon::getIcon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
}
std::string LLCallingCardBridge::getLabelSuffix() const
@@ -3316,39 +4906,46 @@ std::string LLCallingCardBridge::getLabelSuffix() const
void LLCallingCardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
/*
- LLViewerInventoryItem* item = getItem();
- if(item && !item->getCreatorUUID().isNull())
- {
- LLAvatarActions::showProfile(item->getCreatorUUID());
- }
+ LLViewerInventoryItem* item = getItem();
+ if(item && !item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
*/
}
void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
+ LL_DEBUGS() << "LLCallingCardBridge::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
- if(isInTrash())
+ if(isItemInTrash())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
}
else
{
- items.push_back(std::string("Open"));
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Open"));
+ }
+ addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
@@ -3357,10 +4954,15 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
BOOL good_card = (item
&& (LLUUID::null != item->getCreatorUUID())
&& (item->getCreatorUUID() != gAgent.getID()));
- BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
+ BOOL user_online = FALSE;
+ if (item)
+ {
+ user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
+ }
items.push_back(std::string("Send Instant Message Separator"));
items.push_back(std::string("Send Instant Message"));
items.push_back(std::string("Offer Teleport..."));
+ items.push_back(std::string("Request Teleport..."));
items.push_back(std::string("Conference Chat"));
if (!good_card)
@@ -3370,15 +4972,17 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
if (!good_card || !user_online)
{
disabled_items.push_back(std::string("Offer Teleport..."));
+ disabled_items.push_back(std::string("Request Teleport..."));
disabled_items.push_back(std::string("Conference Chat"));
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
- void* cargo_data)
+ void* cargo_data,
+ std::string& tooltip_msg)
{
LLViewerInventoryItem* item = getItem();
BOOL rv = FALSE;
@@ -3387,16 +4991,17 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
// check the type
switch(cargo_type)
{
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_CLOTHING:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_CLOTHING:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_MESH:
{
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
const LLPermissions& perm = inv_item->getPermissions();
@@ -3406,7 +5011,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
rv = TRUE;
if(drop)
{
- LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
+ LLGiveInventory::doGiveInventoryItem(item->getCreatorUUID(),
(LLInventoryItem*)cargo_data);
}
}
@@ -3419,7 +5024,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
}
break;
}
- case DAD_CATEGORY:
+ case DAD_CATEGORY:
{
LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
if( gInventory.getCategory( inv_cat->getUUID() ) )
@@ -3427,7 +5032,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
rv = TRUE;
if(drop)
{
- LLToolDragAndDrop::giveInventoryCategory(
+ LLGiveInventory::doGiveInventoryCategory(
item->getCreatorUUID(),
inv_cat);
}
@@ -3441,65 +5046,33 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
}
break;
}
- default:
- break;
+ default:
+ break;
}
}
return rv;
}
-BOOL LLCallingCardBridge::removeItem()
-{
- if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
- {
- LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
- return FALSE;
- }
- else
- {
- return LLItemBridge::removeItem();
- }
-}
// +=================================================+
// | LLNotecardBridge |
// +=================================================+
-LLUIImagePtr LLNotecardBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
-}
-
void LLNotecardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
-
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
- }
-*/
}
-
// +=================================================+
// | LLGestureBridge |
// +=================================================+
-LLUIImagePtr LLGestureBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
-}
-
LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
{
- if( LLGestureManager::instance().isGestureActive(mUUID) )
+ if( LLGestureMgr::instance().isGestureActive(mUUID) )
{
return LLFontGL::BOLD;
}
@@ -3511,9 +5084,11 @@ LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
std::string LLGestureBridge::getLabelSuffix() const
{
- if( LLGestureManager::instance().isGestureActive(mUUID) )
+ if( LLGestureMgr::instance().isGestureActive(mUUID) )
{
- return LLItemBridge::getLabelSuffix() + " (active)";
+ LLStringUtil::format_map_t args;
+ args["[GESLABEL]"] = LLItemBridge::getLabelSuffix();
+ return LLTrans::getString("ActiveGesture", args);
}
else
{
@@ -3522,11 +5097,11 @@ std::string LLGestureBridge::getLabelSuffix() const
}
// virtual
-void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLGestureBridge::performAction(LLInventoryModel* model, std::string action)
{
- if ("activate" == action)
+ if (isAddAction(action))
{
- LLGestureManager::instance().activateGesture(mUUID);
+ LLGestureMgr::instance().activateGesture(mUUID);
LLViewerInventoryItem* item = gInventory.getItem(mUUID);
if (!item) return;
@@ -3536,9 +5111,9 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
gInventory.updateItem(item);
gInventory.notifyObservers();
}
- else if ("deactivate" == action)
+ else if (isRemoveAction(action))
{
- LLGestureManager::instance().deactivateGesture(mUUID);
+ LLGestureMgr::instance().deactivateGesture(mUUID);
LLViewerInventoryItem* item = gInventory.getItem(mUUID);
if (!item) return;
@@ -3548,142 +5123,203 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
gInventory.updateItem(item);
gInventory.notifyObservers();
}
- else LLItemBridge::performAction(folder, model, action);
+ else if("play" == action)
+ {
+ if(!LLGestureMgr::instance().isGestureActive(mUUID))
+ {
+ // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList.
+ BOOL inform_server = TRUE;
+ BOOL deactivate_similar = FALSE;
+ LLGestureMgr::instance().setGestureLoadedCallback(mUUID, boost::bind(&LLGestureBridge::playGesture, mUUID));
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ llassert(item);
+ if (item)
+ {
+ LLGestureMgr::instance().activateGestureWithAsset(mUUID, item->getAssetUUID(), inform_server, deactivate_similar);
+ }
+ }
+ else
+ {
+ playGesture(mUUID);
+ }
+ }
+ else LLItemBridge::performAction(model, action);
}
void LLGestureBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
- preview->setFocus(TRUE);
- }
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
*/
}
BOOL LLGestureBridge::removeItem()
{
- // Force close the preview window, if it exists
- LLGestureManager::instance().deactivateGesture(mUUID);
+ // Grab class information locally since *this may be deleted
+ // within this function. Not a great pattern...
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return FALSE;
+ }
+ const LLUUID item_id = mUUID;
+
+ // This will also force close the preview window, if it exists.
+ // This may actually delete *this, if mUUID is in the COF.
+ LLGestureMgr::instance().deactivateGesture(item_id);
+
+ // If deactivateGesture deleted *this, then return out immediately.
+ if (!model->getObject(item_id))
+ {
+ return TRUE;
+ }
+
return LLItemBridge::removeItem();
}
void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
+ LL_DEBUGS() << "LLGestureBridge::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ if(isItemInTrash())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
}
else
{
- items.push_back(std::string("Open"));
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+
+ addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
items.push_back(std::string("Gesture Separator"));
- items.push_back(std::string("Activate"));
- items.push_back(std::string("Deactivate"));
+ if (LLGestureMgr::instance().isGestureActive(getUUID()))
+ {
+ items.push_back(std::string("Deactivate"));
+ }
+ else
+ {
+ items.push_back(std::string("Activate"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// static
+void LLGestureBridge::playGesture(const LLUUID& item_id)
+{
+ if (LLGestureMgr::instance().isGesturePlaying(item_id))
+ {
+ LLGestureMgr::instance().stopGesture(item_id);
+ }
+ else
+ {
+ LLGestureMgr::instance().playGesture(item_id);
}
- hideContextEntries(menu, items, disabled_items);
}
+
// +=================================================+
// | LLAnimationBridge |
// +=================================================+
-LLUIImagePtr LLAnimationBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
-}
-
void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
- lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
- if(isInTrash())
+ LL_DEBUGS() << "LLAnimationBridge::buildContextMenu()" << LL_ENDL;
+ if(isOutboxFolder())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ items.push_back(std::string("Delete"));
}
else
{
- items.push_back(std::string("Animation Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
+ if(isItemInTrash())
+ {
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else
+ {
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+ items.push_back(std::string("Animation Open"));
+ items.push_back(std::string("Properties"));
- items.push_back(std::string("Animation Separator"));
- items.push_back(std::string("Animation Play"));
- items.push_back(std::string("Animation Audition"));
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
- hideContextEntries(menu, items, disabled_items);
+ items.push_back(std::string("Animation Separator"));
+ items.push_back(std::string("Animation Play"));
+ items.push_back(std::string("Animation Audition"));
+ }
+ hide_context_entries(menu, items, disabled_items);
}
// virtual
-void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLAnimationBridge::performAction(LLInventoryModel* model, std::string action)
{
if ((action == "playworld") || (action == "playlocal"))
{
if (getItem())
{
- LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
- if ("playworld" == action) activate = LLPreviewAnim::PLAY;
- if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
-
+ LLSD::String activate = "NONE";
+ if ("playworld" == action) activate = "Inworld";
+ if ("playlocal" == action) activate = "Locally";
+
LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
if (preview)
{
- preview->activate(activate);
+ preview->play(activate);
}
}
}
else
{
- LLItemBridge::performAction(folder, model, action);
+ LLItemBridge::performAction(model, action);
}
}
void LLAnimationBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
- }
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
*/
}
@@ -3694,25 +5330,21 @@ void LLAnimationBridge::openItem()
// static
LLUUID LLObjectBridge::sContextMenuItemID;
-LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
-LLItemBridge(inventory, uuid), mInvType(type)
+LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid,
+ LLInventoryType::EType type,
+ U32 flags) :
+ LLItemBridge(inventory, root, uuid)
{
mAttachPt = (flags & 0xff); // low bye of inventory flags
-
- mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
-}
-
-BOOL LLObjectBridge::isItemRemovable()
-{
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
- if(avatar->isWearingAttachment(mUUID, TRUE)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
+ mIsMultiObject = ( flags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
+ mInvType = type;
}
LLUIImagePtr LLObjectBridge::getIcon() const
{
- return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
+ return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject);
}
LLInventoryObject* LLObjectBridge::getObject() const
@@ -3727,21 +5359,21 @@ LLInventoryObject* LLObjectBridge::getObject() const
}
// virtual
-void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
{
- if ("attach" == action)
+ if (isAddAction(action))
{
LLUUID object_id = mUUID;
LLViewerInventoryItem* item;
item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
{
- rez_attachment(item, NULL);
+ rez_attachment(item, NULL, true); // Replace if "Wear"ing.
}
- else if(item && item->isComplete())
+ else if(item && item->isFinished())
{
// must be in library. copy it to our inventory and put it on.
- LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
+ LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0));
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
@@ -3752,91 +5384,69 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
}
gFocusMgr.setKeyboardFocus(NULL);
}
- else if ("detach" == action)
+ else if ("wear_add" == action)
{
- LLInventoryItem* item = gInventory.getItem(mUUID);
- if( item )
- {
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
-
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
- }
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj =
- gObjectList.findObject(item->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
- {
- llwarns << "object not found - ignoring" << llendl;
- }
+ LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding.
}
- else LLItemBridge::performAction(folder, model, action);
+ else if (isRemoveAction(action))
+ {
+ LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
+ }
+ else LLItemBridge::performAction(model, action);
}
void LLObjectBridge::openItem()
{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-
- /*
- LLFloaterReg::showInstance("properties", mUUID);
- */
+ // object double-click action is to wear/unwear object
+ performAction(getInventoryModel(),
+ get_is_item_worn(mUUID) ? "detach" : "attach");
}
-LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{
- U8 font = LLFontGL::NORMAL;
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
+std::string LLObjectBridge::getLabelSuffix() const
+{
+ if (get_is_item_worn(mUUID))
{
- font |= LLFontGL::BOLD;
- }
+ if (!isAgentAvatarValid()) // Error condition, can't figure out attach point
+ {
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
+ }
+ std::string attachment_point_name;
+ if (gAgentAvatarp->getAttachedPointName(mUUID, attachment_point_name))
+ {
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name);
- LLInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- font |= LLFontGL::ITALIC;
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
+ }
+ else
+ {
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_ERROR]"] = LLTrans::getString(attachment_point_name);
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("AttachmentErrorMessage", args);
+ }
}
-
- return (LLFontGL::StyleFlags)font;
+ return LLItemBridge::getLabelSuffix();
}
-std::string LLObjectBridge::getLabelSuffix() const
+void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace)
{
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
- {
- std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
- LLStringUtil::toLower(attachment_point_name);
- return LLItemBridge::getLabelSuffix() + std::string(" (worn on ") + attachment_point_name + std::string(")");
- }
- else
+ const LLUUID& item_id = item->getLinkedUUID();
+
+ // Check for duplicate request.
+ if (isAgentAvatarValid() &&
+ (gAgentAvatarp->attachmentWasRequested(item_id) ||
+ gAgentAvatarp->isWearingAttachment(item_id)))
{
- return LLItemBridge::getLabelSuffix();
+ LL_WARNS() << "duplicate attachment request, ignoring" << LL_ENDL;
+ return;
}
-}
-
-void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
-{
- LLSD payload;
- payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
+ gAgentAvatarp->addAttachmentRequest(item_id);
S32 attach_pt = 0;
- if (gAgent.getAvatarObject() && attachment)
+ if (isAgentAvatarValid() && attachment)
{
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
- iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
+ iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
{
if (iter->second == attachment)
{
@@ -3846,82 +5456,94 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
}
}
+ LLSD payload;
+ payload["item_id"] = item_id; // Wear the base object in case this is a link.
payload["attachment_point"] = attach_pt;
+ payload["is_add"] = !replace;
-#if !ENABLE_MULTIATTACHMENTS
- if (attachment && attachment->getNumObjects() > 0)
+ if (replace &&
+ (attachment && attachment->getNumObjects() > 0))
{
- LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
+ LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_attachment_rez);
}
else
-#endif
{
LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
}
}
-bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
+bool confirm_attachment_rez(const LLSD& notification, const LLSD& response)
{
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
-
- if (!avatarp->canAttachMoreObjects())
+ if (!gAgentAvatarp->canAttachMoreObjects())
{
LLSD args;
args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
- LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
+ LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args);
return false;
}
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0/*YES*/)
{
- LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-
+ LLUUID item_id = notification["payload"]["item_id"].asUUID();
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+
if (itemp)
{
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
- msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
+ /*
+ {
+ U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
+ msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
+ pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
+ msg->addStringFast(_PREHASH_Name, itemp->getName());
+ msg->addStringFast(_PREHASH_Description, itemp->getDescription());
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ return false;
+ }
+ */
+
+ // Queue up attachments to be sent in next idle tick, this way the
+ // attachments are batched up all into one message versus each attachment
+ // being sent in its own separate attachments message.
U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
-#if ENABLE_MULTIATTACHMENTS
- attachment_pt |= ATTACHMENT_ADD;
-#endif
- msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
- pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
- msg->addStringFast(_PREHASH_Name, itemp->getName());
- msg->addStringFast(_PREHASH_Description, itemp->getDescription());
- msg->sendReliable(gAgent.getRegion()->getHost());
+ BOOL is_add = notification["payload"]["is_add"].asBoolean();
+
+ LLAttachmentsMgr::instance().addAttachment(item_id,
+ attachment_pt,
+ is_add);
}
}
return false;
}
-static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
+static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_attachment_rez);
void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ if(isItemInTrash())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
}
else
{
- LLInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
+ items.push_back(std::string("Share"));
+ if (!canShare())
{
- items.push_back(std::string("Goto Link"));
+ disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Properties"));
@@ -3930,45 +5552,43 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
LLObjectBridge::sContextMenuItemID = mUUID;
+ LLInventoryItem *item = getItem();
if(item)
{
- LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
- if( !avatarp )
- {
- return;
- }
-
- if( avatarp->isWearingAttachment( mUUID ) )
+ if (!isAgentAvatarValid()) return;
+
+ if( get_is_item_worn( mUUID ) )
{
+ items.push_back(std::string("Wearable And Object Separator"));
items.push_back(std::string("Detach From Yourself"));
}
- else
- if( !isInTrash() && !isLinkedObjectInTrash() )
+ else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder())
{
- items.push_back(std::string("Attach Separator"));
- items.push_back(std::string("Object Wear"));
+ items.push_back(std::string("Wearable And Object Separator"));
+ items.push_back(std::string("Wearable And Object Wear"));
+ items.push_back(std::string("Wearable Add"));
items.push_back(std::string("Attach To"));
items.push_back(std::string("Attach To HUD"));
// commented out for DEV-32347
//items.push_back(std::string("Restore to Last Position"));
- if (!avatarp->canAttachMoreObjects())
+ if (!gAgentAvatarp->canAttachMoreObjects())
{
- disabled_items.push_back(std::string("Object Wear"));
+ disabled_items.push_back(std::string("Wearable And Object Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
disabled_items.push_back(std::string("Attach To"));
disabled_items.push_back(std::string("Attach To HUD"));
}
LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (attach_menu
- && (attach_menu->getChildCount() == 0)
- && attach_hud_menu
- && (attach_hud_menu->getChildCount() == 0)
- && avatarp)
+ if (attach_menu
+ && (attach_menu->getChildCount() == 0)
+ && attach_hud_menu
+ && (attach_hud_menu->getChildCount() == 0)
+ && isAgentAvatarValid())
{
- for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
- iter != avatarp->mAttachmentPoints.end(); )
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
+ iter != gAgentAvatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
@@ -3984,19 +5604,20 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
LLSD cbparams;
cbparams["index"] = curiter->first;
- cbparams["label"] = attachment->getName();
+ cbparams["label"] = p.name;
p.on_click.function_name = "Inventory.AttachObject";
p.on_click.parameter = LLSD(attachment->getName());
p.on_enable.function_name = "Attachment.Label";
p.on_enable.parameter = cbparams;
LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
+ items.push_back(p.name);
}
}
}
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
BOOL LLObjectBridge::renameItem(const std::string& new_name)
@@ -4012,18 +5633,15 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->rename(new_name);
- buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
- model->updateLinkedObjects(item->getUUID());
-
model->notifyObservers();
+ buildDisplayName();
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- 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 );
@@ -4041,204 +5659,48 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
// | LLLSLTextBridge |
// +=================================================+
-LLUIImagePtr LLLSLTextBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
-}
-
void LLLSLTextBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
- /*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
- }
- */
}
// +=================================================+
// | LLWearableBridge |
// +=================================================+
-// *NOTE: hack to get from avatar inventory to avatar
-void wear_inventory_item_on_avatar( LLInventoryItem* item )
+LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid,
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inv_type,
+ LLWearableType::EType wearable_type) :
+ LLItemBridge(inventory, root, uuid),
+ mAssetType( asset_type ),
+ mWearableType(wearable_type)
{
- if(item)
- {
- lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
- << " )" << llendl;
-
- LLAppearanceManager::wearItem(item);
- }
-}
-
-void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
-{
- if(item)
- {
- lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
- << " )" << llendl;
-
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onWearAddOnAvatarArrived,
- new LLUUID(item->getUUID()));
- }
-}
-
-void remove_inventory_category_from_avatar( LLInventoryCategory* category )
-{
- if(!category) return;
- lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
- << " )" << llendl;
-
-
- if( gFloaterCustomize )
- {
- gFloaterCustomize->askToSaveIfDirty(
- boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
- }
- else
- {
- remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
- }
-}
-
-struct OnRemoveStruct
-{
- LLUUID mUUID;
- LLFolderView *mFolderToDeleteSelected;
- OnRemoveStruct(const LLUUID& uuid, LLFolderView *fv = NULL):
- mUUID(uuid),
- mFolderToDeleteSelected(fv)
- {
- }
-};
-
-void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
-{
-
- // Find all the wearables that are in the category's subtree.
- lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
- if(proceed)
- {
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(category_id,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_wearable);
- S32 i;
- S32 wearable_count = item_array.count();
-
- LLInventoryModel::cat_array_t obj_cat_array;
- LLInventoryModel::item_array_t obj_item_array;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- gInventory.collectDescendentsIf(category_id,
- obj_cat_array,
- obj_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_object);
- S32 obj_count = obj_item_array.count();
-
- // Find all gestures in this folder
- LLInventoryModel::cat_array_t gest_cat_array;
- LLInventoryModel::item_array_t gest_item_array;
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
- gInventory.collectDescendentsIf(category_id,
- gest_cat_array,
- gest_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_gesture);
- S32 gest_count = gest_item_array.count();
-
- if (wearable_count > 0) //Loop through wearables. If worn, remove.
- {
- for(i = 0; i < wearable_count; ++i)
- {
- if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
- {
- LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(item_array.get(i)->getUUID()));
-
- }
- }
- }
-
-
- if (obj_count > 0)
- {
- for(i = 0; i < obj_count; ++i)
- {
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
-
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
-
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
- {
- llwarns << "object not found, ignoring" << llendl;
- }
- }
- }
-
- if (gest_count > 0)
- {
- for(i = 0; i < gest_count; ++i)
- {
- if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) )
- {
- LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() );
- gInventory.updateItem( gest_item_array.get(i) );
- gInventory.notifyObservers();
- }
-
- }
- }
- }
+ mInvType = inv_type;
}
BOOL LLWearableBridge::renameItem(const std::string& new_name)
{
- if( gAgentWearables.isWearingItem( mUUID ) )
+ if (get_is_item_worn(mUUID))
{
gAgentWearables.setWearableName( mUUID, new_name );
}
return LLItemBridge::renameItem(new_name);
}
-BOOL LLWearableBridge::isItemRemovable()
-{
- if (gAgentWearables.isWearingItem(mUUID, TRUE)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
-}
-
std::string LLWearableBridge::getLabelSuffix() const
{
- if( gAgentWearables.isWearingItem( mUUID ) )
+ if (get_is_item_worn(mUUID))
{
- return LLItemBridge::getLabelSuffix() + " (worn)";
+ // e.g. "(worn)"
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
}
else
{
@@ -4248,13 +5710,13 @@ std::string LLWearableBridge::getLabelSuffix() const
LLUIImagePtr LLWearableBridge::getIcon() const
{
- return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
+ return LLInventoryIcon::getIcon(mAssetType, mInvType, mWearableType, FALSE);
}
// virtual
-void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+void LLWearableBridge::performAction(LLInventoryModel* model, std::string action)
{
- if ("wear" == action)
+ if (isAddAction(action))
{
wearOnAvatar();
}
@@ -4267,147 +5729,125 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
editOnAvatar();
return;
}
- else if ("take_off" == action)
+ else if (isRemoveAction(action))
{
- if(gAgentWearables.isWearingItem(mUUID))
- {
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- if (item->getIsLinkType() &&
- model->isObjectDescendentOf(mUUID,LLAppearanceManager::getCOF()))
- {
- // Delete link after item has been taken off.
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(mUUID, folder));
- }
- else
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(mUUID));
- }
- }
- }
+ removeFromAvatar();
+ return;
}
- else LLItemBridge::performAction(folder, model, action);
+ else LLItemBridge::performAction(model, action);
}
void LLWearableBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
- /*
- if( isInTrash() )
- {
- LLNotifications::instance().add("CannotWearTrash");
- }
- else if(isAgentInventory())
- {
- if( !gAgentWearables.isWearingItem( mUUID ) )
- {
- wearOnAvatar();
- }
- }
- else
- {
- // must be in the inventory library. copy it to our inventory
- // and put it on right away.
- LLViewerInventoryItem* item = getItem();
- if(item && item->isComplete())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else if(item)
- {
- // *TODO: We should fetch the item details, and then do
- // the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
- }
- }
- */
}
void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
+ LL_DEBUGS() << "LLWearableBridge::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ if(isItemInTrash())
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
}
else
{ // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
- BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
+ BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM);
// If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
LLViewerInventoryItem* item = getItem();
- if( !no_open && item )
+ if (can_open && item)
{
- no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART);
+ can_open = (item->getType() != LLAssetType::AT_CLOTHING) &&
+ (item->getType() != LLAssetType::AT_BODYPART);
}
- if (!no_open)
+ if (isLinkedObjectMissing())
{
- items.push_back(std::string("Open"));
+ can_open = FALSE;
}
-
- if (item && item->getIsLinkType())
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
+
+ if (can_open)
+ {
+ addOpenRightClickMenuOption(items);
+ }
+ else
{
- items.push_back(std::string("Goto Link"));
+ disabled_items.push_back(std::string("Open"));
+ disabled_items.push_back(std::string("Open Original"));
}
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
- items.push_back(std::string("Wearable Separator"));
-
- items.push_back(std::string("Wearable Wear"));
- items.push_back(std::string("Wearable Add"));
+ items.push_back(std::string("Wearable And Object Separator"));
+
items.push_back(std::string("Wearable Edit"));
- if ((flags & FIRST_SELECTED_ITEM) == 0)
+ bool modifiable = !gAgentWearables.isWearableModifiable(item->getUUID());
+ if (((flags & FIRST_SELECTED_ITEM) == 0) || modifiable)
{
disabled_items.push_back(std::string("Wearable Edit"));
}
// Don't allow items to be worn if their baseobj is in the trash.
- if (isLinkedObjectInTrash())
+ if (isLinkedObjectInTrash() || isLinkedObjectMissing() || isCOFFolder())
{
- disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable And Object Wear"));
disabled_items.push_back(std::string("Wearable Add"));
disabled_items.push_back(std::string("Wearable Edit"));
}
- if( item && (item->getType() == LLAssetType::AT_CLOTHING) )
+ // Disable wear and take off based on whether the item is worn.
+ if(item)
{
- items.push_back(std::string("Take Off"));
+ switch (item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ items.push_back(std::string("Take Off"));
+ // Fallthrough since clothing and bodypart share wear options
+ case LLAssetType::AT_BODYPART:
+ if (get_is_item_worn(item->getUUID()))
+ {
+ disabled_items.push_back(std::string("Wearable And Object Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ else
+ {
+ items.push_back(std::string("Wearable And Object Wear"));
+ disabled_items.push_back(std::string("Take Off"));
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+
+ if (LLWearableType::getAllowMultiwear(mWearableType))
+ {
+ items.push_back(std::string("Wearable Add"));
+ if (!gAgentWearables.canAddWearable(mWearableType))
+ {
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// Called from menus
@@ -4419,9 +5859,9 @@ BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
if(!self->isAgentInventory())
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
- if(!item || !item->isComplete()) return FALSE;
+ if(!item || !item->isFinished()) return FALSE;
}
- return (!gAgentWearables.isWearingItem(self->mUUID));
+ return (!get_is_item_worn(self->mUUID));
}
// Called from menus
@@ -4435,68 +5875,28 @@ void LLWearableBridge::onWearOnAvatar(void* user_data)
void LLWearableBridge::wearOnAvatar()
{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
+ // TODO: investigate wearables may not be loaded at this point EXT-8231
LLViewerInventoryItem* item = getItem();
if(item)
{
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_inventory_item_on_avatar(item);
- }
+ LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true);
}
}
void LLWearableBridge::wearAddOnAvatar()
{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
+ // TODO: investigate wearables may not be loaded at this point EXT-8231
LLViewerInventoryItem* item = getItem();
if(item)
{
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_add_inventory_item_on_avatar(item);
- }
+ LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, false);
}
}
// static
-void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
+void LLWearableBridge::onWearOnAvatarArrived( LLViewerWearable* wearable, void* userdata )
{
LLUUID* item_id = (LLUUID*) userdata;
if(wearable)
@@ -4513,7 +5913,7 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda
}
else
{
- llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ LL_INFOS() << "By the time wearable asset arrived, its inv item already pointed to a different asset." << LL_ENDL;
}
}
}
@@ -4522,7 +5922,7 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda
// static
// BAP remove the "add" code path once everything is fully COF-ified.
-void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
+void LLWearableBridge::onWearAddOnAvatarArrived( LLViewerWearable* wearable, void* userdata )
{
LLUUID* item_id = (LLUUID*) userdata;
if(wearable)
@@ -4540,7 +5940,7 @@ void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* use
}
else
{
- llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ LL_INFOS() << "By the time wearable asset arrived, its inv item already pointed to a different asset." << LL_ENDL;
}
}
}
@@ -4553,10 +5953,10 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
LLWearableBridge* self = (LLWearableBridge*)user_data;
if(!self) return FALSE;
- return (gAgentWearables.isWearingItem(self->mUUID));
+ return (get_is_item_worn(self->mUUID));
}
-// static
+// static
void LLWearableBridge::onEditOnAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4568,19 +5968,7 @@ void LLWearableBridge::onEditOnAvatar(void* user_data)
void LLWearableBridge::editOnAvatar()
{
- const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
- if( wearable )
- {
- // Set the tab to the right wearable.
- if (gFloaterCustomize)
- gFloaterCustomize->setCurrentWearableType( wearable->getType() );
-
- if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
- {
- // Start Avatar Customization
- gAgent.changeCameraToCustomizeAvatar();
- }
- }
+ LLAgentWearables::editWearable(mUUID);
}
// static
@@ -4589,118 +5977,197 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
LLWearableBridge* self = (LLWearableBridge*)user_data;
if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
{
- return gAgentWearables.isWearingItem( self->mUUID );
+ return get_is_item_worn( self->mUUID );
}
return FALSE;
}
-// static
-void LLWearableBridge::onRemoveFromAvatar(void* user_data)
+void LLWearableBridge::removeFromAvatar()
{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return;
- if(gAgentWearables.isWearingItem(self->mUUID))
+ LL_WARNS() << "safe to remove?" << LL_ENDL;
+ if (get_is_item_worn(mUUID))
{
- LLViewerInventoryItem* item = self->getItem();
- if (item)
- {
- LLUUID parent_id = item->getParentUUID();
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- onRemoveFromAvatarArrived,
- new OnRemoveStruct(LLUUID(self->mUUID)));
- }
+ LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
}
}
-// static
-void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
- void* userdata)
+
+// +=================================================+
+// | LLLinkItemBridge |
+// +=================================================+
+// For broken item links
+
+std::string LLLinkItemBridge::sPrefix("Link: ");
+
+void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
- LLUUID item_id = on_remove_struct->mUUID;
- if(wearable)
- {
- if( gAgentWearables.isWearingItem( item_id ) )
- {
- EWearableType type = wearable->getType();
+ // *TODO: Translate
+ LL_DEBUGS() << "LLLink::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+
+ items.push_back(std::string("Find Original"));
+ disabled_items.push_back(std::string("Find Original"));
- if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
- //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
- {
- // MULTI_WEARABLE: FIXME HACK - always remove all
- bool do_remove_all = false;
- gAgentWearables.removeWearable( type, do_remove_all, 0 );
- }
- }
+ if(isItemInTrash())
+ {
+ addTrashContextMenuOptions(items, disabled_items);
}
- if (on_remove_struct->mFolderToDeleteSelected)
+ else
{
- on_remove_struct->mFolderToDeleteSelected->removeSelectedItems();
+ items.push_back(std::string("Properties"));
+ addDeleteContextMenuOptions(items, disabled_items);
}
- delete on_remove_struct;
+ hide_context_entries(menu, items, disabled_items);
}
-LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
- const LLUUID& uuid,LLInventoryModel* model)
+// +=================================================+
+// | LLMeshBridge |
+// +=================================================+
+
+LLUIImagePtr LLMeshBridge::getIcon() const
{
- LLInvFVBridgeAction* action = NULL;
- switch(asset_type)
- {
- case LLAssetType::AT_TEXTURE:
- action = new LLTextureBridgeAction(uuid,model);
- break;
+ return LLInventoryIcon::getIcon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
+}
- case LLAssetType::AT_SOUND:
- action = new LLSoundBridgeAction(uuid,model);
- break;
+void LLMeshBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ // open mesh
+ }
+}
- case LLAssetType::AT_LANDMARK:
- action = new LLLandmarkBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_CALLINGCARD:
- action = new LLCallingCardBridgeAction(uuid,model);
- break;
+void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LL_DEBUGS() << "LLMeshBridge::buildContextMenu()" << LL_ENDL;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
- case LLAssetType::AT_OBJECT:
- action = new LLObjectBridgeAction(uuid,model);
- break;
+ if(isItemInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
- case LLAssetType::AT_NOTECARD:
- action = new LLNotecardBridgeAction(uuid,model);
- break;
+ items.push_back(std::string("Restore Item"));
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
+ }
+ else
+ {
+ items.push_back(std::string("Properties"));
- case LLAssetType::AT_ANIMATION:
- action = new LLAnimationBridgeAction(uuid,model);
- break;
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
- case LLAssetType::AT_GESTURE:
- action = new LLGestureBridgeAction(uuid,model);
- break;
+ hide_context_entries(menu, items, disabled_items);
+}
- case LLAssetType::AT_LSL_TEXT:
- action = new LLLSLTextBridgeAction(uuid,model);
- break;
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- action = new LLWearableBridgeAction(uuid,model);
+// +=================================================+
+// | LLLinkBridge |
+// +=================================================+
+// For broken folder links.
+std::string LLLinkFolderBridge::sPrefix("Link: ");
+LLUIImagePtr LLLinkFolderBridge::getIcon() const
+{
+ LLFolderType::EType folder_type = LLFolderType::FT_NONE;
+ const LLInventoryObject *obj = getInventoryObject();
+ if (obj)
+ {
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ cat = (LLViewerInventoryCategory*)model->getCategory(obj->getLinkedUUID());
+ if (cat)
+ {
+ folder_type = cat->getPreferredType();
+ }
+ }
+ }
+ return LLFolderBridge::getIcon(folder_type);
+}
- break;
+void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ LL_DEBUGS() << "LLLink::buildContextMenu()" << LL_ENDL;
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
- default:
- break;
+ if (isItemInTrash())
+ {
+ addTrashContextMenuOptions(items, disabled_items);
}
- return action;
+ else
+ {
+ items.push_back(std::string("Find Original"));
+ addDeleteContextMenuOptions(items, disabled_items);
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem();
+ return;
+ }
+ LLItemBridge::performAction(model,action);
}
+void LLLinkFolderBridge::gotoItem()
+{
+ const LLUUID &cat_uuid = getFolderID();
+ if (!cat_uuid.isNull())
+ {
+ LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid);
+ if (base_folder)
+ {
+ if (LLInventoryModel* model = getInventoryModel())
+ {
+ model->fetchDescendentsOf(cat_uuid);
+ }
+ base_folder->setOpen(TRUE);
+ mRoot->setSelection(base_folder,TRUE);
+ mRoot->scrollToShowSelection();
+ }
+ }
+}
+const LLUUID &LLLinkFolderBridge::getFolderID() const
+{
+ if (LLViewerInventoryItem *link_item = getItem())
+ {
+ if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
+ {
+ const LLUUID& cat_uuid = cat->getUUID();
+ return cat_uuid;
+ }
+ }
+ return LLUUID::null;
+}
+
+/********************************************************************************
+ **
+ ** BRIDGE ACTIONS
+ **/
-//static
+// static
void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
- const LLUUID& uuid,LLInventoryModel* model)
+ const LLUUID& uuid,
+ LLInventoryModel* model)
{
- LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ // Perform indirection in case of link.
+ const LLUUID& linked_uuid = gInventory.getLinkedItemID(uuid);
+
+ LLInvFVBridgeAction* action = createAction(asset_type,linked_uuid,model);
if(action)
{
action->doIt();
@@ -4708,143 +6175,224 @@ void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
}
}
-//static
+// static
void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
{
- LLAssetType::EType asset_type = model->getItem(uuid)->getType();
- LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
- if(action)
+ llassert(model);
+ LLViewerInventoryItem* item = model->getItem(uuid);
+ llassert(item);
+ if (item)
{
- action->doIt();
- delete action;
+ LLAssetType::EType asset_type = item->getType();
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
}
}
LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
{
- if(mModel)
+ if (mModel)
return (LLViewerInventoryItem*)mModel->getItem(mUUID);
return NULL;
}
-//virtual
-void LLTextureBridgeAction::doIt()
+class LLTextureBridgeAction: public LLInvFVBridgeAction
{
- if (getItem())
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ if (getItem())
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLTextureBridgeAction(){}
+protected:
+ LLTextureBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLSoundBridgeAction::doIt()
+class LLSoundBridgeAction: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if(item)
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
+ }
+ LLInvFVBridgeAction::doIt();
}
-
- LLInvFVBridgeAction::doIt();
-}
-
+ virtual ~LLSoundBridgeAction(){}
+protected:
+ LLSoundBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
-//virtual
-void LLLandmarkBridgeAction::doIt()
+class LLLandmarkBridgeAction: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if( item )
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- // Opening (double-clicking) a landmark immediately teleports,
- // but warns you the first time.
- LLSD payload;
- payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+
+ LLSD args;
+ args["LOCATION"] = item->getName();
+
+ LLNotificationsUtil::add("TeleportFromLandmark", args, payload);
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLLandmarkBridgeAction(){}
+protected:
+ LLLandmarkBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLCallingCardBridgeAction::doIt()
+class LLCallingCardBridgeAction: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if(item && item->getCreatorUUID().notNull())
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLAvatarActions::showProfile(item->getCreatorUUID());
+ LLViewerInventoryItem* item = getItem();
+ if (item && item->getCreatorUUID().notNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLCallingCardBridgeAction(){}
+protected:
+ LLCallingCardBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
- LLInvFVBridgeAction::doIt();
-}
+};
-//virtual
-void
-LLNotecardBridgeAction::doIt()
+class LLNotecardBridgeAction
+: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if (item)
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLNotecardBridgeAction(){}
+protected:
+ LLNotecardBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLGestureBridgeAction::doIt()
+class LLGestureBridgeAction: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if (item)
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
- preview->setFocus(TRUE);
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLGestureBridgeAction(){}
+protected:
+ LLGestureBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLAnimationBridgeAction::doIt()
+class LLAnimationBridgeAction: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if (item)
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLAnimationBridgeAction(){}
+protected:
+ LLAnimationBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLObjectBridgeAction::doIt()
+class LLObjectBridgeAction: public LLInvFVBridgeAction
{
- LLFloaterReg::showInstance("properties", mUUID);
-
- LLInvFVBridgeAction::doIt();
-}
-
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
+ {
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+ LLInvFVBridgeAction::doIt();
+ }
+ virtual ~LLObjectBridgeAction(){}
+protected:
+ LLObjectBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
-//virtual
-void LLLSLTextBridgeAction::doIt()
+class LLLSLTextBridgeAction: public LLInvFVBridgeAction
{
- LLViewerInventoryItem* item = getItem();
- if (item)
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
{
- LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+ LLInvFVBridgeAction::doIt();
}
+ virtual ~LLLSLTextBridgeAction(){}
+protected:
+ LLLSLTextBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
- LLInvFVBridgeAction::doIt();
-}
+class LLWearableBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt()
+ {
+ wearOnAvatar();
+ }
+ virtual ~LLWearableBridgeAction(){}
+protected:
+ LLWearableBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+ BOOL isItemInTrash() const;
+ // return true if the item is in agent inventory. if false, it
+ // must be lost or in the inventory library.
+ BOOL isAgentInventory() const;
+ void wearOnAvatar();
+};
-BOOL LLWearableBridgeAction::isInTrash() const
+BOOL LLWearableBridgeAction::isItemInTrash() const
{
if(!mModel) return FALSE;
- LLUUID trash_id = mModel->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return mModel->isObjectDescendentOf(mUUID, trash_id);
}
@@ -4857,209 +6405,122 @@ BOOL LLWearableBridgeAction::isAgentInventory() const
void LLWearableBridgeAction::wearOnAvatar()
{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
+ // TODO: investigate wearables may not be loaded at this point EXT-8231
LLViewerInventoryItem* item = getItem();
if(item)
{
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_inventory_item_on_avatar(item);
- }
+ LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true);
}
}
-//virtual
-void LLWearableBridgeAction::doIt()
+LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,
+ LLInventoryModel* model)
{
- if(isInTrash())
- {
- LLNotifications::instance().add("CannotWearTrash");
- }
- else if(isAgentInventory())
- {
- if(!gAgentWearables.isWearingItem(mUUID))
- {
- wearOnAvatar();
- }
- }
- else
+ LLInvFVBridgeAction* action = NULL;
+ switch(asset_type)
{
- // must be in the inventory library. copy it to our inventory
- // and put it on right away.
- LLViewerInventoryItem* item = getItem();
- if(item && item->isComplete())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else if(item)
- {
- // *TODO: We should fetch the item details, and then do
- // the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
- }
+ case LLAssetType::AT_TEXTURE:
+ action = new LLTextureBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_SOUND:
+ action = new LLSoundBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_LANDMARK:
+ action = new LLLandmarkBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_CALLINGCARD:
+ action = new LLCallingCardBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_OBJECT:
+ action = new LLObjectBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_NOTECARD:
+ action = new LLNotecardBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_ANIMATION:
+ action = new LLAnimationBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_GESTURE:
+ action = new LLGestureBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_LSL_TEXT:
+ action = new LLLSLTextBridgeAction(uuid,model);
+ break;
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ action = new LLWearableBridgeAction(uuid,model);
+ break;
+ default:
+ break;
}
-
- LLInvFVBridgeAction::doIt();
+ return action;
}
-// +=================================================+
-// | LLLinkItemBridge |
-// +=================================================+
-// For broken links
-
-std::string LLLinkItemBridge::sPrefix("Link: ");
+/** Bridge Actions
+ **
+ ********************************************************************************/
-
-LLUIImagePtr LLLinkItemBridge::getIcon() const
+/************************************************************************/
+/* Recent Inventory Panel related classes */
+/************************************************************************/
+void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- if (LLViewerInventoryItem *item = getItem())
- {
- return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
- }
- return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
-}
-
-void LLLinkItemBridge::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("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
- }
- hideContextEntries(menu, items, disabled_items);
-}
-
+ menuentry_vec_t disabled_items, items;
+ buildContextMenuOptions(flags, items, disabled_items);
-// +=================================================+
-// | LLLinkBridge |
-// +=================================================+
-// For broken links.
-
-std::string LLLinkFolderBridge::sPrefix("Link: ");
+ items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
-
-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);
+ hide_context_entries(menu, items, disabled_items);
}
-void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
+ LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ LLFolderViewModelInventory* view_model,
+ LLFolderView* root,
+ const LLUUID& uuid,
+ U32 flags /*= 0x00*/ ) const
{
- // *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
+ LLInvFVBridge* new_listener = NULL;
+ if (asset_type == LLAssetType::AT_CATEGORY
+ && actual_asset_type != LLAssetType::AT_LINK_FOLDER)
{
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
+ new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid);
}
else
- {
- items.push_back(std::string("Goto Link"));
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
{
- disabled_items.push_back(std::string("Delete"));
+ new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ view_model,
+ root,
+ uuid,
+ flags);
}
- }
- hideContextEntries(menu, items, disabled_items);
+ return new_listener;
}
-void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge()
{
- if ("goto" == action)
- {
- gotoItem(folder);
- return;
- }
- LLItemBridge::performAction(folder,model,action);
}
-void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
+void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu)
{
- 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);
- folder->scrollToShowSelection();
- }
- }
+ uuid_vec_t ids;
+ menuentry_vec_t disabled_items;
+ if (get_selection_item_uuids(selected_items, ids))
+ {
+ if (!LLAppearanceMgr::instance().canAddWearables(ids))
+ {
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ }
+ disable_context_entries_if_present(menu, disabled_items);
}
-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;
-}
+// EOF