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.cpp3129
1 files changed, 2130 insertions, 999 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 5108f68592..a047ed6fee 100644..100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -37,20 +37,25 @@
#include "llappearancemgr.h"
#include "llattachmentsmgr.h"
#include "llavataractions.h"
+#include "llfavoritesbar.h" // management of favorites folder
#include "llfloateropenobject.h"
#include "llfloaterreg.h"
+#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
+#include "llfolderview.h"
#include "llfriendcard.h"
#include "llgesturemgr.h"
#include "llgiveinventory.h"
-#include "llimfloater.h"
+#include "llfloaterimcontainer.h"
#include "llimview.h"
-#include "llinventoryclipboard.h"
+#include "llclipboard.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
+#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
+#include "llmarketplacefunctions.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llpreviewanim.h"
@@ -58,20 +63,33 @@
#include "llpreviewtexture.h"
#include "llselectmgr.h"
#include "llsidepanelappearance.h"
-#include "llsidetray.h"
+#include "lltooldraganddrop.h"
#include "lltrans.h"
#include "llviewerassettype.h"
#include "llviewerfoldertype.h"
#include "llviewermenu.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llvoavatarself.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;
@@ -83,28 +101,76 @@ struct LLMoveInv
using namespace LLOldEvents;
-// Helpers
-// bug in busy count inc/dec right now, logic is complex... do we really need it?
-void inc_busy_count()
-{
-// gViewerWindow->getWindow()->incBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
-}
-void dec_busy_count()
-{
-// gViewerWindow->getWindow()->decBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
-}
-
// Function declarations
-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_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)
+{
+ return ("wear" == action || "attach" == action || "activate" == action);
+}
+
+bool isRemoveAction(const std::string& action)
+{
+ return ("take_off" == action || "detach" == action || "deactivate" == action);
+}
+
+bool isMarketplaceCopyAction(const std::string& action)
+{
+ return (("copy_to_outbox" == action) || ("move_to_outbox" == action));
+}
+
+bool isMarketplaceSendAction(const std::string& action)
+{
+ 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 |
@@ -116,9 +182,10 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,
mUUID(uuid),
mRoot(root),
mInvType(LLInventoryType::IT_NONE),
- mIsLink(FALSE)
+ mIsLink(FALSE),
+ LLFolderViewModelItemInventory(inventory->getRootViewModel())
{
- mInventoryPanel = inventory->getHandle();
+ mInventoryPanel = inventory->getInventoryPanelHandle();
const LLInventoryObject* obj = getInventoryObject();
mIsLink = obj && obj->getIsLinkType();
}
@@ -135,7 +202,12 @@ const std::string& LLInvFVBridge::getName() const
const std::string& LLInvFVBridge::getDisplayName() const
{
- return getName();
+ if(mDisplayName.empty())
+ {
+ buildDisplayName();
+ }
+
+ return mDisplayName;
}
// Folders have full perms
@@ -154,9 +226,24 @@ LLFolderType::EType LLInvFVBridge::getPreferredType() const
// 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;
+}
+
+void LLInvFVBridge::setCreationDate(time_t creation_date_utc)
+{
+ LLInventoryObject* objectp = getInventoryObject();
+ if (objectp)
+ {
+ objectp->setCreationDate(creation_date_utc);
+ }
}
+
// Can be destroyed (or moved to trash)
BOOL LLInvFVBridge::isItemRemovable() const
{
@@ -174,17 +261,36 @@ 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()
{
@@ -196,7 +302,7 @@ void LLInvFVBridge::showProperties()
*/
}
-void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
+void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)
{
// Deactivate gestures when moving them into Trash
LLInvFVBridge* bridge;
@@ -205,11 +311,11 @@ 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)
@@ -222,13 +328,13 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
}
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())
{
@@ -240,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
@@ -256,14 +362,14 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
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)
@@ -276,7 +382,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
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)
@@ -317,7 +423,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
for(i = 0; i < count; ++i)
{
- bridge = (LLInvFVBridge*)(batch.get(i));
+ bridge = (LLInvFVBridge*)(batch[i]);
if(!bridge || !bridge->isItemRemovable()) continue;
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
if(cat)
@@ -359,6 +465,11 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
for(; it != end; ++it)
{
gInventory.moveObject((*it), trash_id);
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if (item)
+ {
+ model->updateItem(item);
+ }
}
// notify inventory observers.
@@ -367,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;
}
@@ -377,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;
@@ -407,7 +526,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ if (!LLClipboard::instance().hasContents() || !isAgentInventory())
{
return FALSE;
}
@@ -417,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()))
@@ -430,7 +549,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return FALSE;
}
}
- const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.at(i));
if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
return FALSE;
@@ -439,16 +558,55 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return TRUE;
}
+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,
- BOOL append) // If append is TRUE, then new enabled entries
+ const menuentry_vec_t &disabled_entries)
{
const LLView::child_list_t *list = menu.getChildList();
// 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;
+ bool is_previous_entry_separator = true;
for (LLView::child_list_t::const_iterator itor = list->begin();
itor != list->end();
@@ -464,7 +622,6 @@ void hide_context_entries(LLMenuGL& menu,
hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
}
-
bool found = false;
menuentry_vec_t::const_iterator itor2;
for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
@@ -472,6 +629,7 @@ void hide_context_entries(LLMenuGL& menu,
if (*itor2 == name)
{
found = true;
+ break;
}
}
@@ -479,9 +637,8 @@ void hide_context_entries(LLMenuGL& menu,
// between two separators).
if (found)
{
- const BOOL is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL);
- if (is_entry_separator && is_previous_entry_separator)
- found = false;
+ 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;
}
@@ -491,6 +648,7 @@ void hide_context_entries(LLMenuGL& menu,
{
menu_item->setVisible(FALSE);
}
+
menu_item->setEnabled(FALSE);
}
else
@@ -499,17 +657,14 @@ void hide_context_entries(LLMenuGL& menu,
// 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);
- if (append)
- {
- menu_item->setEnabled(TRUE);
- }
- for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+
+ bool enabled = (menu_item->getEnabled() == TRUE);
+ for (itor2 = disabled_entries.begin(); enabled && (itor2 != disabled_entries.end()); ++itor2)
{
- if (*itor2 == name)
- {
- menu_item->setEnabled(FALSE);
- }
+ enabled &= (*itor2 != name);
}
+
+ menu_item->setEnabled(enabled);
}
}
}
@@ -537,10 +692,14 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
items.push_back(std::string("Find Links"));
}
- items.push_back(std::string("Rename"));
- if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+
+ if (!isInboxFolder())
{
- disabled_items.push_back(std::string("Rename"));
+ items.push_back(std::string("Rename"));
+ if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
+ }
}
if (show_asset_id)
@@ -568,11 +727,28 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
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"));
+ }
+ }
}
}
- // Don't allow items to be pasted directly into the COF.
- if (!isCOFFolder())
+ // 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"));
}
@@ -603,12 +779,16 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLInvFVBridge::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if(isItemInTrash())
{
addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else
{
@@ -626,6 +806,31 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 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)
{
@@ -685,6 +890,32 @@ void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items)
items.push_back(std::string("Open"));
}
+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"));
+ }
+
+#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
BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
@@ -701,7 +932,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
}
*id = obj->getUUID();
- //object_ids.put(obj->getUUID());
+ //object_ids.push_back(obj->getUUID());
if (*type == DAD_CATEGORY)
{
@@ -727,10 +958,16 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const
LLInventoryModel* LLInvFVBridge::getInventoryModel() const
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
return panel ? panel->getModel() : NULL;
}
+LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const
+{
+ LLInventoryPanel* panel = mInventoryPanel.get();
+ return panel ? &(panel->getFilter()) : NULL;
+}
+
BOOL LLInvFVBridge::isItemInTrash() const
{
LLInventoryModel* model = getInventoryModel();
@@ -781,6 +1018,53 @@ BOOL LLInvFVBridge::isCOFFolder() const
return LLAppearanceMgr::instance().getIsInCOF(mUUID);
}
+BOOL LLInvFVBridge::isInboxFolder() const
+{
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false);
+
+ if (inbox_id.isNull())
+ {
+ 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
{
return FALSE;
@@ -792,7 +1076,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp)
{
- change_item_parent(model, item, new_parent_id, restamp);
+ model->changeItemParent(item, new_parent_id, restamp);
}
// static
@@ -801,13 +1085,14 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp)
{
- change_category_parent(model, cat, new_parent_id, restamp);
+ 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)
@@ -818,7 +1103,7 @@ 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 " << LLInventoryType::lookupHumanReadable(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, root, uuid, inv_type);
break;
@@ -826,7 +1111,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_SOUND:
if(!(inv_type == LLInventoryType::IT_SOUND))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid);
break;
@@ -834,7 +1119,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_LANDMARK:
if(!(inv_type == LLInventoryType::IT_LANDMARK))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid, flags);
break;
@@ -842,7 +1127,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_CALLINGCARD:
if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid);
break;
@@ -850,7 +1135,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_SCRIPT:
if(!(inv_type == LLInventoryType::IT_LSL))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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 LLItemBridge(inventory, root, uuid);
break;
@@ -858,7 +1143,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_OBJECT:
if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid, inv_type, flags);
break;
@@ -866,7 +1151,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_NOTECARD:
if(!(inv_type == LLInventoryType::IT_NOTECARD))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid);
break;
@@ -874,7 +1159,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_ANIMATION:
if(!(inv_type == LLInventoryType::IT_ANIMATION))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid);
break;
@@ -882,7 +1167,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_GESTURE:
if(!(inv_type == LLInventoryType::IT_GESTURE))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid);
break;
@@ -890,7 +1175,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_LSL_TEXT:
if(!(inv_type == LLInventoryType::IT_LSL))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid);
break;
@@ -899,9 +1184,9 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
case LLAssetType::AT_BODYPART:
if(!(inv_type == LLInventoryType::IT_WEARABLE))
{
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(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, root, uuid, asset_type, inv_type, (LLWearableType::EType)flags);
+ new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, LLWearableType::inventoryFlagsToWearableType(flags));
break;
case LLAssetType::AT_CATEGORY:
if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
@@ -917,9 +1202,22 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
// Only should happen for broken links.
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;
}
@@ -933,48 +1231,168 @@ 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 LLInvFVBridge::canShare() const
{
- if (!isAgentInventory()) return FALSE;
+ bool can_share = false;
- const LLInventoryModel* model = getInventoryModel();
- if (!model) return 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);
+ }
+ }
+ }
- const LLViewerInventoryItem *item = model->getItem(mUUID);
+ 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 (!LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item))
- return FALSE;
- return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item);
+ if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+ {
+ return false;
+ }
+
+ if (LLAssetType::AT_CALLINGCARD == item->getType())
+ {
+ return false;
+ }
}
- // Categories can be given.
- if (model->getCategory(mUUID)) return TRUE;
+ return true;
- return FALSE;
+#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
@@ -983,6 +1401,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset
actual_asset_type,
inv_type,
inventory,
+ view_model,
root,
uuid,
flags);
@@ -1033,7 +1452,13 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
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)
@@ -1043,14 +1468,13 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
}
else if ("paste" == action)
{
- // Single item only
LLInventoryItem* itemp = model->getItem(mUUID);
if (!itemp) return;
- LLFolderViewItem* folder_view_itemp = mRoot->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)
@@ -1059,12 +1483,77 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
LLInventoryItem* itemp = model->getItem(mUUID);
if (!itemp) return;
- LLFolderViewItem* folder_view_itemp = mRoot->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()
@@ -1072,7 +1561,8 @@ void LLItemBridge::selectItem()
LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
if(item && !item->isFinished())
{
- item->fetchFromServer();
+ //item->fetchFromServer();
+ LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
}
}
@@ -1151,7 +1641,16 @@ LLUIImagePtr LLItemBridge::getIcon() const
mIsLink);
}
- return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT);
+ return LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT);
+}
+
+LLUIImagePtr LLItemBridge::getIconOverlay() const
+{
+ if (getItem() && getItem()->getIsLinkType())
+ {
+ return LLUI::getUIImage("Inv_Link");
+ }
+ return NULL;
}
PermissionMask LLItemBridge::getPermissionMask() const
@@ -1162,24 +1661,25 @@ PermissionMask LLItemBridge::getPermissionMask() const
return perm_mask;
}
-const std::string& LLItemBridge::getDisplayName() const
+void LLItemBridge::buildDisplayName() const
{
- if(mDisplayName.empty())
+ if(getItem())
{
- buildDisplayName(getItem(), mDisplayName);
+ mDisplayName.assign(getItem()->getName());
}
- return mDisplayName;
-}
-
-void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
-{
- if(item)
+ else
{
- name.assign(item->getName());
+ mDisplayName.assign(LLStringUtil::null);
}
- else
+
+ mSearchableName.assign(mDisplayName);
+ mSearchableName.append(getLabelSuffix());
+ LLStringUtil::toUpper(mSearchableName);
+
+ //Name set, so trigger a sort
+ if(mParent)
{
- name.assign(LLStringUtil::null);
+ mParent->requestSort();
}
}
@@ -1190,7 +1690,7 @@ LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
if (get_is_item_worn(mUUID))
{
- // llinfos << "BOLD" << llendl;
+ // LL_INFOS() << "BOLD" << LL_ENDL;
font |= LLFontGL::BOLD;
}
else if(item && item->getIsLinkType())
@@ -1205,7 +1705,7 @@ 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");
@@ -1214,16 +1714,17 @@ std::string LLItemBridge::getLabelSuffix() const
LLInventoryItem* item = getItem();
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)
{
@@ -1273,6 +1774,11 @@ BOOL LLItemBridge::isItemRenameable() const
return FALSE;
}
+ if (isInboxFolder())
+ {
+ return FALSE;
+ }
+
return (item->getPermissions().allowModifyBy(gAgent.getID()));
}
return FALSE;
@@ -1289,20 +1795,15 @@ 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->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())
@@ -1310,7 +1811,6 @@ BOOL LLItemBridge::removeItem()
return FALSE;
}
-
// move it to the trash
LLPreview::hide(mUUID, TRUE);
LLInventoryModel* model = getInventoryModel();
@@ -1333,16 +1833,8 @@ BOOL LLItemBridge::removeItem()
{
if (!item->getIsLinkType())
{
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLLinkedItemIDMatches is_linked_item_match(mUUID);
- gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
- cat_array,
- item_array,
- LLInventoryModel::INCLUDE_TRASH,
- is_linked_item_match);
-
- const U32 num_links = cat_array.size() + item_array.size();
+ 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.
@@ -1396,21 +1888,7 @@ BOOL LLItemBridge::isItemCopyable() const
return FALSE;
}
- // All items can be copied in god mode since you can
- // at least paste-as-link the item, though you
- // still may not be able paste the item.
- return TRUE;
- // return (item->getPermissions().allowCopyBy(gAgent.getID()));
- }
- 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;
}
@@ -1436,16 +1914,6 @@ BOOL LLItemBridge::isItemPermissive() const
return FALSE;
}
-bool LLItemBridge::isAddAction(std::string action) const
-{
- return ("wear" == action || "attach" == action || "activate" == action);
-}
-
-bool LLItemBridge::isRemoveAction(std::string action) const
-{
- return ("take_off" == action || "detach" == action || "deactivate" == action);
-}
-
// +=================================================+
// | LLFolderBridge |
// +=================================================+
@@ -1458,13 +1926,80 @@ BOOL LLFolderBridge::isItemMovable() const
LLInventoryObject* obj = getInventoryObject();
if(obj)
{
- return (!LLFolderType::lookupIsProtectedType(((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);
+}
+
+void LLFolderBridge::buildDisplayName() const
+{
+ 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")
+ {
+ //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());
+ }
+ }
+
+ //"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))
+ {
+ LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD());
+ }
+
+ 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)
+ {
+ if ( loading )
+ {
+ // Measure how long we've been in the loading state
+ mTimeSinceRequestStart.reset();
+ }
+ mIsLoading = loading;
+
+ mFolderViewItem->refresh();
+ }
}
@@ -1476,11 +2011,11 @@ public:
LLIsItemRemovable() : mPassed(TRUE) {}
virtual void doFolder(LLFolderViewFolder* folder)
{
- mPassed &= folder->getListener()->isItemRemovable();
+ mPassed &= folder->getViewModelItem()->isItemRemovable();
}
virtual void doItem(LLFolderViewItem* item)
{
- mPassed &= item->getListener()->isItemRemovable();
+ mPassed &= item->getViewModelItem()->isItemRemovable();
}
BOOL mPassed;
};
@@ -1493,8 +2028,8 @@ BOOL LLFolderBridge::isItemRemovable() const
return FALSE;
}
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL);
+ LLInventoryPanel* panel = mInventoryPanel.get();
+ LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL);
if (folderp)
{
LLIsItemRemovable folder_test;
@@ -1523,23 +2058,35 @@ BOOL LLFolderBridge::isUpToDate() const
BOOL LLFolderBridge::isItemCopyable() const
{
- if (gSavedSettings.getBOOL("InventoryLinking"))
- {
- // Can copy folders to paste-as-link, but not for straight paste.
- return TRUE;
- }
- return FALSE;
+ // 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
{
@@ -1555,15 +2102,15 @@ BOOL LLFolderBridge::isClipboardPasteable() const
return FALSE;
}
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ 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.count() - 1; i >= 0; --i)
+ for(S32 i = objects.size() - 1; i >= 0; --i)
{
- const LLUUID &obj_id = objects.get(i);
+ const LLUUID &obj_id = objects.at(i);
if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
{
return FALSE;
@@ -1593,12 +2140,12 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
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 LLUUID &obj_id = objects.get(i);
+ const LLUUID &obj_id = objects.at(i);
const LLInventoryCategory *cat = model->getCategory(obj_id);
if (cat)
{
@@ -1627,8 +2174,88 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
}
+static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg)
+{
+ // 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;
+ }
+
+#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);
+
+ int max_child_levels = 0;
+
+ for (S32 i=0; i < cats->size(); ++i)
+ {
+ 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)
+ BOOL drop,
+ std::string& tooltip_msg)
{
LLInventoryModel* model = getInventoryModel();
@@ -1638,24 +2265,38 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
if (!isAgentAvatarValid()) return FALSE;
if (!isAgentInventory()) return FALSE; // cannot drag categories into library
+ LLInventoryPanel* destination_panel = mInventoryPanel.get();
+ if (!destination_panel) return false;
- // check to make sure source is agent inventory, and is represented there.
- LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
- const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
- && (LLToolDragAndDrop::SOURCE_AGENT == source);
+ 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();
+ const BOOL is_agent_inventory = (model->getCategory(cat_id) != NULL)
+ && (LLToolDragAndDrop::SOURCE_AGENT == source);
BOOL accept = FALSE;
+ 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 &cat_id = inv_cat->getUUID();
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_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT);
+ 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);
//--------------------------------------------------------------------------------
@@ -1663,28 +2304,75 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
//
BOOL is_movable = TRUE;
- if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
+
+ if (is_movable && (mUUID == cat_id))
+ {
is_movable = FALSE;
- if (move_is_into_outfit)
+ tooltip_msg = LLTrans::getString("TooltipDragOntoSelf");
+ }
+ if (is_movable && (model->isObjectDescendentOf(mUUID, cat_id)))
+ {
is_movable = FALSE;
- if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+ 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;
- gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
- for (S32 i=0; i < descendent_categories.count(); ++i)
+ if (is_movable)
{
- LLInventoryCategory* category = descendent_categories[i];
- if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ model->collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
+ for (S32 i=0; i < descendent_categories.size(); ++i)
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ // 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 "special folders" (e.g. Textures Folder).
+ // Can't move 'large' folders into current outfit: MAINT-4086
is_movable = FALSE;
- break;
+ LLStringUtil::format_map_t args;
+ args["AMOUNT"] = llformat("%d", max_items_to_wear);
+ tooltip_msg = LLTrans::getString("TooltipTooManyWearables",args);
}
}
- if (move_is_into_trash)
+ if (is_movable && move_is_into_trash)
{
- for (S32 i=0; i < descendent_items.count(); ++i)
+ for (S32 i=0; i < descendent_items.size(); ++i)
{
LLInventoryItem* item = descendent_items[i];
if (get_is_item_worn(item->getUUID()))
@@ -1694,9 +2382,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
- if (move_is_into_landmarks)
+ if (is_movable && move_is_into_landmarks)
{
- for (S32 i=0; i < descendent_items.count(); ++i)
+ for (S32 i=0; i < descendent_items.size(); ++i)
{
LLViewerInventoryItem* item = descendent_items[i];
@@ -1709,20 +2397,139 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
+ 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 (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))
+ {
+ 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)
+ {
+ if (model->isObjectDescendentOf(cat_id, master_folder->getUUID()))
+ {
+ // 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)
+ {
+ dragged_folder_count += 1;
+ }
+ else
+ {
+ // 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;
+ }
+ }
+ }
+ }
+ }
+ 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
- && (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
+ accept = is_movable;
+
if (accept && drop)
{
// Look for any gestures and deactivate them
if (move_is_into_trash)
{
- for (S32 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
@@ -1732,52 +2539,24 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
- // 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 (inv_cat->getPreferredType() == LLFolderType::FT_NONE)
- {
- if (move_is_into_current_outfit)
- {
- // traverse category and add all contents to currently worn.
- BOOL append = true;
- LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
- }
- else
- {
- // Recursively create links in target outfit.
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
- LLAppearanceMgr::instance().linkAll(mUUID,items,NULL);
- }
- }
- else
- {
-#if SUPPORT_ENSEMBLES
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceMgr::instance().addEnsembleLink(inv_cat);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- const std::string empty_description = "";
- link_inventory_item(
- gAgent.getID(),
- inv_cat->getUUID(),
- mUUID,
- inv_cat->getName(),
- empty_description,
- 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.
@@ -1791,15 +2570,28 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else if (LLToolDragAndDrop::SOURCE_WORLD == 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 = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter);
+ }
}
else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
{
- // Accept folders that contain complete outfits.
- accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID());
+ 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)
{
@@ -1830,7 +2622,8 @@ 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
@@ -1839,7 +2632,7 @@ 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;
}
@@ -1850,12 +2643,18 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
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.
@@ -1863,9 +2662,16 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
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())
@@ -1880,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;
}
}
@@ -1890,7 +2701,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
if(drop && accept)
{
it = inventory_objects.begin();
- LLInventoryObject::object_list_t::iterator first_it = inventory_objects.begin();
LLMoveInv* move_inv = new LLMoveInv;
move_inv->mObjectID = object_id;
move_inv->mCategoryID = category_id;
@@ -1918,122 +2728,119 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
return accept;
}
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver
-{
-public:
- LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) :
- LLInventoryFetchItemsObserver(ids),
- mCopyItems(false)
- { };
- LLRightClickInventoryFetchObserver(const uuid_vec_t& ids,
- const LLUUID& cat_id,
- bool copy_items) :
- LLInventoryFetchItemsObserver(ids),
- mCatID(cat_id),
- mCopyItems(copy_items)
- { };
- virtual void done()
- {
- // 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(const uuid_vec_t& ids,
- bool copy_items) :
- LLInventoryFetchDescendentsObserver(ids),
- mCopyItems(copy_items)
- {}
- ~LLRightClickInventoryFetchDescendentsObserver() {}
- virtual void done();
-protected:
- bool mCopyItems;
-};
-
-void LLRightClickInventoryFetchDescendentsObserver::done()
+void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)
{
- // Avoid passing a NULL-ref as mCompleteFolders.front() down to
- // gInventory.collectDescendents()
+ // Bail out immediately if no descendents
if( mComplete.empty() )
{
- llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
- dec_busy_count();
+ LL_WARNS() << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << LL_ENDL;
+ if (clear_observer)
+ {
gInventory.removeObserver(this);
delete this;
+ }
return;
}
- // 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(mComplete.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();
+ // 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)
+ {
gInventory.removeObserver(this);
delete this;
- return;
}
-#endif
- uuid_vec_t ids;
- for(S32 i = 0; i < count; ++i)
+ for (uuid_vec_t::iterator current_folder = completed_folder.begin(); current_folder != completed_folder.end(); ++current_folder)
{
- ids.push_back(item_array.get(i)->getUUID());
- }
+ // 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);
- LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems);
+ S32 item_count(0);
+ if( item_array )
+ {
+ item_count = item_array->size();
+ }
+
+ S32 cat_count(0);
+ if( cat_array )
+ {
+ cat_count = cat_array->size();
+ }
- // 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;
+ // Move to next if current folder empty
+ if ((item_count == 0) && (cat_count == 0))
+ {
+ continue;
+ }
- // increment busy count and either tell the inventory to check &
- // call done, or add this object to the inventory for observation.
- inc_busy_count();
+ uuid_vec_t ids;
+ LLRightClickInventoryFetchObserver* outfit = NULL;
+ LLRightClickInventoryFetchDescendentsObserver* categories = NULL;
- // do the fetch
+ // 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);
+ }
+
+ // Perform the item fetch
+ if (outfit)
+ {
outfit->startFetch();
- outfit->done(); //Not interested in waiting and this will be right 99% of the time.
+ 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->isFinished())
+ /*
+ if (outfit->isFinished())
{
// everything is already here - call done.
- outfit->done();
+ outfit->execute();
+ delete outfit;
}
else
{
- // it's all on it's way - add an observer, and the inventory
+ // 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);
+ }
+ }
+ }
}
@@ -2046,15 +2853,16 @@ void LLRightClickInventoryFetchDescendentsObserver::done()
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;
};
@@ -2082,11 +2890,10 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
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
{
@@ -2094,7 +2901,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
mContentsCount)
{
gInventory.removeObserver(this);
- LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, FALSE);
+ LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, !mReplace);
delete this;
}
}
@@ -2109,10 +2916,10 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
{
if ("open" == action)
{
- LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mRoot->getItemByID(mUUID));
+ LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mInventoryPanel.get()->getItemByID(mUUID));
if (f)
{
- f->setOpen(TRUE);
+ f->toggleOpen();
}
return;
@@ -2137,20 +2944,15 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
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;
- LLAppearanceMgr::instance().addEnsembleLink(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)
@@ -2165,7 +2967,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
- remove_inventory_category_from_avatar ( cat );
+ LLAppearanceMgr::instance().takeOffOutfit( cat->getLinkedUUID() );
return;
}
else if ("purge" == action)
@@ -2184,11 +2986,32 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string 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;
@@ -2268,14 +3091,35 @@ LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE));
}
-LLUIImagePtr LLFolderBridge::getOpenIcon() const
+LLUIImagePtr LLFolderBridge::getIconOpen() const
{
return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));
}
+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
@@ -2331,51 +3175,146 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re
{
// move it to the trash
LLPreview::hide(mUUID);
- remove_category(getInventoryModel(), 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())
{
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_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ 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);
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
+ for (std::vector<LLUUID>::const_iterator iter = objects.begin();
iter != objects.end();
++iter)
{
const LLUUID& item_id = (*iter);
+
LLInventoryItem *item = model->getItem(item_id);
- if (item)
+ LLInventoryObject *obj = model->getObject(item_id);
+ if (obj)
{
if (move_is_into_current_outfit || move_is_into_outfit)
{
- if (can_move_to_outfit(item, move_is_into_current_outfit))
+ if (item && can_move_to_outfit(item, move_is_into_current_outfit))
{
dropToOutfit(item, move_is_into_current_outfit);
}
}
- else if(LLInventoryClipboard::instance().isCutMode())
+ 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
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(
@@ -2389,6 +3328,9 @@ void LLFolderBridge::pasteFromClipboard()
}
}
}
+ // Change mode to paste for next paste
+ LLClipboard::instance().setCutMode(false);
+ }
}
void LLFolderBridge::pasteLinkFromClipboard()
@@ -2397,14 +3339,25 @@ void LLFolderBridge::pasteLinkFromClipboard()
if(model)
{
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_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ 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);
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
+ std::vector<LLUUID> objects;
+ LLClipboard::instance().pasteFromClipboard(objects);
+ for (std::vector<LLUUID>::const_iterator iter = objects.begin();
iter != objects.end();
++iter)
{
@@ -2417,128 +3370,23 @@ void LLFolderBridge::pasteLinkFromClipboard()
dropToOutfit(item, move_is_into_current_outfit);
}
}
- else if (LLInventoryCategory *cat = model->getCategory(object_id))
- {
- const std::string empty_description = "";
- link_inventory_item(
- gAgent.getID(),
- cat->getUUID(),
- parent_id,
- cat->getName(),
- empty_description,
- LLAssetType::AT_LINK_FOLDER,
- LLPointer<LLInventoryCallback>(NULL));
- }
- else if (LLInventoryItem *item = model->getItem(object_id))
+ else if (LLConstPointer<LLInventoryObject> obj = model->getObject(object_id))
{
- link_inventory_item(
- gAgent.getID(),
- item->getLinkedUUID(),
- parent_id,
- item->getName(),
- item->getDescription(),
- 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()
{
LLFolderBridge* selfp = sSelf.get();
- if (selfp)
- {
- selfp->folderOptionsMenu();
- }
-}
-void LLFolderBridge::folderOptionsMenu()
-{
- menuentry_vec_t disabled_items;
-
- 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;
-
- 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))
- {
- 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"));
- }
- }
-
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- if (LLFolderType::lookupIsProtectedType(type))
- {
- mItems.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("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)
- {
- 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("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"));
- }
- mItems.push_back(std::string("Outfit Separator"));
- }
- LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
- if (menup)
+ if (selfp && selfp->mRoot)
{
- hide_context_entries(*menup, mItems, disabled_items, TRUE);
-
- // Reposition the menu, in case we're adding items to an existing menu.
- menup->needsArrange();
- menup->arrangeAndClear();
+ selfp->mRoot->updateMenu();
}
}
@@ -2551,97 +3399,90 @@ 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;
-
-// menuentry_vec_t disabled_items;
LLInventoryModel* model = getInventoryModel();
- if(!model) return;
+ 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);
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"));
- mDisabledItems.push_back(std::string("New Folder"));
- mDisabledItems.push_back(std::string("New Script"));
- mDisabledItems.push_back(std::string("New Note"));
- mDisabledItems.push_back(std::string("New Gesture"));
- mDisabledItems.push_back(std::string("New Clothes"));
- mDisabledItems.push_back(std::string("New Body Parts"));
+ 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"));
}
-
- // clear out old menu and folder pointers
- mMenu.markDead();
- sSelf.markDead();
-
if(trash_id == mUUID)
{
// This is the trash.
- mItems.push_back(std::string("Empty Trash"));
+ items.push_back(std::string("Empty Trash"));
}
else if(isItemInTrash())
{
// This is a folder in the trash.
- mItems.clear(); // clear any items that used to exist
- addTrashContextMenuOptions(mItems, mDisabledItems);
+ 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 && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
{
- // 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"));
-
-#if SUPPORT_ENSEMBLES
- // Changing folder types is an unfinished unsupported feature
- // and can lead to unexpected behavior if enabled.
- mItems.push_back(std::string("Change Type"));
- const LLViewerInventoryCategory *cat = getCategory();
- if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ 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"));
}
-#endif
- 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() == LLFolderType::FT_OUTFIT))
{
- mItems.push_back(std::string("Rename"));
+ items.push_back(std::string("Rename"));
- addDeleteContextMenuOptions(mItems, mDisabledItems);
+ 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()))
{
- mDisabledItems.push_back(std::string("Delete"));
+ 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);
@@ -2665,43 +3506,159 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// Preemptively disable system folder removal if more than one item selected.
if ((flags & FIRST_SELECTED_ITEM) == 0)
{
- mDisabledItems.push_back(std::string("Delete System Folder"));
+ disabled_items.push_back(std::string("Delete System Folder"));
}
- mItems.push_back(std::string("Share"));
- if (!canShare())
+ if (!isOutboxFolder())
{
- mDisabledItems.push_back(std::string("Share"));
+ items.push_back(std::string("Share"));
+ if (!canShare())
+ {
+ disabled_items.push_back(std::string("Share"));
+ }
}
-
- hide_context_entries(menu, mItems, mDisabledItems);
-
// Add menu items that are dependent on the contents of the folder.
- uuid_vec_t folders;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ 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())
+ {
+ // 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 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;
- mMenu = menu.getHandle();
- sSelf = getHandle();
- LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
- fetch->startFetch();
- inc_busy_count();
- if(fetch->isFinished())
+ 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)
{
- // everything is already here - call done.
- fetch->done();
+ 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())
{
- // it's all on its way - add an observer, and the inventory will call done for us when everything is here.
- gInventory.addObserver(fetch);
+ 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) )
+ {
+ 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"));
}
}
-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;
@@ -2712,11 +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)
{
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
- //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
+ //LL_INFOS() << "LLFolderBridge::dragOrDrop()" << LL_ENDL;
BOOL accept = FALSE;
switch(cargo_type)
{
@@ -2725,13 +3683,14 @@ 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:
- accept = dragItemIntoFolder(inv_item, drop);
+ case DAD_MESH:
+ accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
break;
case DAD_LINK:
// DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER.
@@ -2742,12 +3701,12 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID());
if (linked_category)
{
- accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop);
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg);
}
}
else
{
- accept = dragItemIntoFolder(inv_item, drop);
+ accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
}
break;
case DAD_CATEGORY:
@@ -2757,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;
@@ -2785,25 +3748,6 @@ 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(),
- LLFolderType::FT_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, LLWearableType::WT_SHIRT);
@@ -2869,6 +3813,24 @@ void LLFolderBridge::createNewEyes(void* user_data)
LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES);
}
+EInventorySortGroup LLFolderBridge::getSortGroup() const
+{
+ 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;
+}
+
+
// static
void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type)
{
@@ -2884,6 +3846,25 @@ void LLFolderBridge::modifyOutfit(BOOL append)
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
+ // 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 );
}
@@ -2896,13 +3877,14 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& 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)
{
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);
}
@@ -2938,6 +3920,12 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr
return FALSE;
}
+ U32 flags = inv_item->getFlags();
+ if(flags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
+ {
+ return FALSE;
+ }
+
if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID()))
{
return FALSE;
@@ -2969,11 +3957,12 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
// 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 = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
- if (drag_over_item && drag_over_item->getListener())
+ LLFolderViewModelItemInventory* view_model = drag_over_item ? static_cast<LLFolderViewModelItemInventory*>(drag_over_item->getViewModelItem()) : NULL;
+ if (view_model)
{
- cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID());
+ cb.get()->setTargetLandmarkId(view_model->getUUID());
}
copy_inventory_item(
@@ -2995,14 +3984,7 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
else
{
LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_item->getLinkedUUID(),
- mUUID,
- inv_item->getName(),
- inv_item->getDescription(),
- LLAssetType::AT_LINK,
- cb);
+ link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
}
}
@@ -3010,25 +3992,41 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
// 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 || !inv_item) return FALSE;
- if(!isAgentInventory()) return FALSE; // cannot drag into library
+ 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;
+
+ 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_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ 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)
{
@@ -3080,10 +4078,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
accept = TRUE;
if (!is_movable)
+ {
accept = FALSE;
- if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites)
+ }
+ else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites)
+ {
accept = FALSE;
- if (move_is_into_current_outfit || move_is_into_outfit)
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
{
accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
}
@@ -3091,8 +4093,47 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = can_move_to_landmarks(inv_item);
}
+ else if (move_is_into_outbox)
+ {
+ accept = can_move_to_outbox(inv_item, tooltip_msg);
+
+ if (accept)
+ {
+ 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;
+ }
+ }
+ }
+
+ 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;
- if(accept && drop)
+ accept = filter->check(fv_item->getViewModelItem());
+ }
+
+ if (accept && drop)
{
if (inv_item->getType() == LLAssetType::AT_GESTURE
&& LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
@@ -3101,15 +4142,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
// 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).
- LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
- if (active_panel)
- {
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- if (active_panel && (panel != active_panel))
+ // 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();
}
- }
//--------------------------------------------------------------------------------
// Destination folder logic
@@ -3119,13 +4157,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// (only reorder the item in Favorites folder)
if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites)
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem();
if (itemp)
{
LLUUID srcItemId = inv_item->getUUID();
- LLUUID destItemId = itemp->getListener()->getUUID();
- gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId);
+ LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID();
+ LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId);
}
}
@@ -3141,10 +4178,27 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
dropToOutfit(inv_item, move_is_into_current_outfit);
}
+ else if (move_is_into_outbox)
+ {
+ if (move_is_from_outbox)
+ {
+ move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId());
+ }
+ else
+ {
+ copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId());
+ }
+ }
// NORMAL or TRASH folder
// (move the item, restamp if into trash)
else
{
+ // 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,
@@ -3154,7 +4208,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
//
//--------------------------------------------------------------------------------
-
}
}
else if (LLToolDragAndDrop::SOURCE_WORLD == source)
@@ -3163,9 +4216,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// 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;
}
@@ -3173,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())
-
{
accept = TRUE;
}
@@ -3192,7 +4244,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// 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)
+ if (move_is_into_current_outfit || move_is_into_outfit)
{
accept = FALSE;
}
@@ -3203,8 +4255,20 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* 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(drop && accept)
+ if (accept && drop)
{
LLMoveInv* move_inv = new LLMoveInv;
move_inv->mObjectID = inv_item->getParentUUID();
@@ -3226,15 +4290,34 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
LLNotifications::instance().forceResponse(params, 0);
}
}
-
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
- accept = TRUE;
- if(drop)
+ if (move_is_into_outbox)
+ {
+ 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)
{
- copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
- LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
+ 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)
@@ -3244,7 +4327,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = TRUE;
- if (move_is_into_current_outfit || move_is_into_outfit)
+ if (move_is_into_outbox)
+ {
+ 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);
}
@@ -3255,6 +4343,18 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
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
@@ -3284,11 +4384,74 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else
{
- llwarns << "unhandled drag source" << llendl;
+ LL_WARNS() << "unhandled drag source" << LL_ENDL;
}
return accept;
}
+// 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);
+
+ 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)
+{
+ 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());
+}
+
// +=================================================+
// | LLTextureBridge |
// +=================================================+
@@ -3326,12 +4489,16 @@ bool LLTextureBridge::canSaveTexture(void)
void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLTextureBridge::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if(isItemInTrash())
{
addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else
{
@@ -3361,11 +4528,11 @@ void LLTextureBridge::performAction(LLInventoryModel* model, std::string action)
{
if ("save_as" == action)
{
- LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
- LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
if (preview_texture)
{
preview_texture->openToSave();
+ preview_texture->saveAs();
}
}
else LLItemBridge::performAction(model, action);
@@ -3384,15 +4551,6 @@ void LLSoundBridge::openItem()
}
}
-void LLSoundBridge::previewItem()
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- send_sound_trigger(item->getAssetUUID(), 1.0);
- }
-}
-
void LLSoundBridge::openSoundPreview(void* which)
{
LLSoundBridge *me = (LLSoundBridge *)which;
@@ -3401,33 +4559,57 @@ void LLSoundBridge::openSoundPreview(void* which)
void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLSoundBridge::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLSoundBridge::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
- if(isItemInTrash())
+ if (isOutboxFolder())
{
- addTrashContextMenuOptions(items, disabled_items);
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else
{
- items.push_back(std::string("Share"));
- if (!canShare())
+ if (isItemInTrash())
{
- disabled_items.push_back(std::string("Share"));
+ 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);
}
- items.push_back(std::string("Sound Open"));
- items.push_back(std::string("Properties"));
- 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);
}
+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 |
// +=================================================+
@@ -3455,32 +4637,42 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t items;
menuentry_vec_t disabled_items;
- lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
- if(isItemInTrash())
+ LL_DEBUGS() << "LLLandmarkBridge::buildContextMenu()" << LL_ENDL;
+ if(isOutboxFolder())
{
- addTrashContextMenuOptions(items, disabled_items);
+ addOutboxContextMenuOptions(flags, items, disabled_items);
}
else
{
- items.push_back(std::string("Share"));
- if (!canShare())
+ if(isItemInTrash())
{
- disabled_items.push_back(std::string("Share"));
+ 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);
}
- items.push_back(std::string("Landmark Open"));
- items.push_back(std::string("Properties"));
- getClipboardEntries(true, items, disabled_items, flags);
+ 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"));
}
- items.push_back(std::string("Landmark Separator"));
- items.push_back(std::string("About Landmark"));
-
// 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"));
}
@@ -3521,7 +4713,7 @@ void LLLandmarkBridge::performAction(LLInventoryModel* model, std::string action
key["type"] = "landmark";
key["id"] = item->getUUID();
- LLSideTray::getInstance()->showPanel("panel_places", key);
+ LLFloaterSidePanelContainer::showPanel("places", key);
}
}
else
@@ -3567,6 +4759,10 @@ public:
virtual void changed(U32 mask)
{
mBridgep->refreshFolderViewItem();
+ if (mask & LLFriendObserver::ONLINE)
+ {
+ mBridgep->checkSearchBySuffixChanges();
+ }
}
protected:
LLCallingCardBridge* mBridgep;
@@ -3593,14 +4789,52 @@ 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(LLInventoryModel* model, std::string action)
{
@@ -3610,19 +4844,16 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act
if (item && (item->getCreatorUUID() != gAgent.getID()) &&
(!item->getCreatorUUID().isNull()))
{
- std::string callingcard_name;
- gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
- // IDEVO
+ std::string callingcard_name = LLCacheName::getDefaultName();
LLAvatarName av_name;
- if (LLAvatarNameCache::useDisplayNames()
- && LLAvatarNameCache::get(item->getCreatorUUID(), &av_name))
+ if (LLAvatarNameCache::get(item->getCreatorUUID(), &av_name))
{
- callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
+ callingcard_name = av_name.getCompleteName();
}
LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
if (session_id != LLUUID::null)
{
- LLIMFloater::show(session_id);
+ LLFloaterIMContainer::getInstance()->showConversation(session_id);
}
}
}
@@ -3635,6 +4866,16 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act
LLAvatarActions::offerTeleport(item->getCreatorUUID());
}
}
+ 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);
}
@@ -3681,13 +4922,17 @@ void LLCallingCardBridge::openItem()
void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLCallingCardBridge::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if(isItemInTrash())
{
addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
}
else
{
@@ -3696,6 +4941,10 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
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"));
@@ -3713,6 +4962,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
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)
@@ -3722,6 +4972,7 @@ 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"));
}
}
@@ -3730,7 +4981,8 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
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;
@@ -3749,6 +5001,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
+ case DAD_MESH:
{
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
const LLPermissions& perm = inv_item->getPermissions();
@@ -3937,13 +5190,17 @@ BOOL LLGestureBridge::removeItem()
void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLGestureBridge::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if(isItemInTrash())
{
addTrashContextMenuOptions(items, disabled_items);
}
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
+ }
else
{
items.push_back(std::string("Share"));
@@ -3993,30 +5250,36 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t items;
menuentry_vec_t disabled_items;
- lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
- if(isItemInTrash())
+ LL_DEBUGS() << "LLAnimationBridge::buildContextMenu()" << LL_ENDL;
+ if(isOutboxFolder())
{
- addTrashContextMenuOptions(items, disabled_items);
+ items.push_back(std::string("Delete"));
}
else
{
- items.push_back(std::string("Share"));
- if (!canShare())
+ if(isItemInTrash())
{
- disabled_items.push_back(std::string("Share"));
+ 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"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
}
- items.push_back(std::string("Animation Open"));
- items.push_back(std::string("Properties"));
- getClipboardEntries(true, items, disabled_items, flags);
+ items.push_back(std::string("Animation Separator"));
+ items.push_back(std::string("Animation Play"));
+ items.push_back(std::string("Animation Audition"));
}
- 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
@@ -4026,14 +5289,14 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio
{
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);
}
}
}
@@ -4110,7 +5373,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
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(),
@@ -4127,11 +5390,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
}
else if (isRemoveAction(action))
{
- LLInventoryItem* item = gInventory.getItem(mUUID);
- if(item)
- {
- LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID());
- }
+ LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
}
else LLItemBridge::performAction(model, action);
}
@@ -4151,16 +5410,20 @@ std::string LLObjectBridge::getLabelSuffix() const
{
return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
}
- std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID);
- if (attachment_point_name == LLStringUtil::null) // Error condition, invalid attach point
+ std::string attachment_point_name;
+ if (gAgentAvatarp->getAttachedPointName(mUUID, attachment_point_name))
{
- attachment_point_name = "Invalid Attachment";
- }
- // e.g. "(worn on ...)" / "(attached to ...)"
- LLStringUtil::format_map_t args;
- args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name);
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name);
- return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
+ 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 LLItemBridge::getLabelSuffix();
}
@@ -4174,7 +5437,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
(gAgentAvatarp->attachmentWasRequested(item_id) ||
gAgentAvatarp->isWearingAttachment(item_id)))
{
- llwarns << "duplicate attachment request, ignoring" << llendl;
+ LL_WARNS() << "duplicate attachment request, ignoring" << LL_ENDL;
return;
}
gAgentAvatarp->addAttachmentRequest(item_id);
@@ -4270,6 +5533,10 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
if(isItemInTrash())
{
addTrashContextMenuOptions(items, disabled_items);
+ }
+ else if(isOutboxFolder())
+ {
+ items.push_back(std::string("Delete"));
}
else
{
@@ -4344,6 +5611,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
p.on_enable.parameter = cbparams;
LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
+ items.push_back(p.name);
}
}
}
@@ -4365,11 +5633,10 @@ 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->notifyObservers();
+ buildDisplayName();
if (isAgentAvatarValid())
{
@@ -4419,120 +5686,6 @@ LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory,
mInvType = inv_type;
}
-void remove_inventory_category_from_avatar( LLInventoryCategory* category )
-{
- if(!category) return;
- lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
- << " )" << llendl;
-
-
- if (gAgentCamera.cameraCustomizeAvatar())
- {
- // switching to outfit editor should automagically save any currently edited wearable
- LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit"));
- }
-
- remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
-}
-
-struct OnRemoveStruct
-{
- LLUUID mUUID;
- OnRemoveStruct(const LLUUID& uuid):
- mUUID(uuid)
- {
- }
-};
-
-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)
- {
- LLViewerInventoryItem *item = item_array.get(i);
- if (item->getType() == LLAssetType::AT_BODYPART)
- continue;
- if (gAgent.isTeen() && item->isWearableType() &&
- (item->getWearableType() == LLWearableType::WT_UNDERPANTS || item->getWearableType() == LLWearableType::WT_UNDERSHIRT))
- continue;
- if (get_is_item_worn(item->getUUID()))
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(item->getLinkedUUID()));
- }
- }
- }
-
- if (obj_count > 0)
- {
- for(i = 0; i < obj_count; ++i)
- {
- LLViewerInventoryItem *obj_item = obj_item_array.get(i);
- if (get_is_item_worn(obj_item->getUUID()))
- {
- LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID());
- }
- }
- }
-
- if (gest_count > 0)
- {
- for(i = 0; i < gest_count; ++i)
- {
- LLViewerInventoryItem *gest_item = gest_item_array.get(i);
- if (get_is_item_worn(gest_item->getUUID()))
- {
- LLGestureMgr::instance().deactivateGesture( gest_item->getLinkedUUID() );
- gInventory.updateItem( gest_item );
- gInventory.notifyObservers();
- }
-
- }
- }
- }
-}
-
BOOL LLWearableBridge::renameItem(const std::string& new_name)
{
if (get_is_item_worn(mUUID))
@@ -4596,13 +5749,17 @@ void LLWearableBridge::openItem()
void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLWearableBridge::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if(isItemInTrash())
{
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 can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM);
@@ -4642,7 +5799,8 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
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"));
}
@@ -4671,10 +5829,18 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
else
{
items.push_back(std::string("Wearable And Object Wear"));
- items.push_back(std::string("Wearable Add"));
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;
@@ -4730,7 +5896,7 @@ void LLWearableBridge::wearAddOnAvatar()
}
// static
-void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
+void LLWearableBridge::onWearOnAvatarArrived( LLViewerWearable* wearable, void* userdata )
{
LLUUID* item_id = (LLUUID*) userdata;
if(wearable)
@@ -4747,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;
}
}
}
@@ -4756,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)
@@ -4774,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;
}
}
}
@@ -4816,107 +5982,16 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
return FALSE;
}
-// static
-void LLWearableBridge::onRemoveFromAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return;
- if(get_is_item_worn(self->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)));
- }
- }
-}
-
-// static
-void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
- void* userdata)
-{
- OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
- const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
- if(wearable)
- {
- if( get_is_item_worn( item_id ) )
- {
- LLWearableType::EType type = wearable->getType();
-
- if( !(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES ) ) //&&
- //!((!gAgent.isTeen()) && ( type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT )) )
- {
- bool do_remove_all = false;
- U32 index = gAgentWearables.getWearableIndex(wearable);
- gAgentWearables.removeWearable( type, do_remove_all, index );
- }
- }
- }
-
- // Find and remove this item from the COF.
- LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false);
- gInventory.notifyObservers();
-
- delete on_remove_struct;
-}
-
-// static
-void LLWearableBridge::removeAllClothesFromAvatar()
-{
- // Remove COF links.
- for (S32 itype = LLWearableType::WT_SHAPE; itype < LLWearableType::WT_COUNT; ++itype)
- {
- if (itype == LLWearableType::WT_SHAPE || itype == LLWearableType::WT_SKIN || itype == LLWearableType::WT_HAIR || itype == LLWearableType::WT_EYES)
- continue;
-
- for (S32 index = gAgentWearables.getWearableCount(itype)-1; index >= 0 ; --index)
- {
- LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(
- gAgentWearables.getWearableInventoryItem((LLWearableType::EType)itype, index));
- if (!item)
- continue;
- const LLUUID &item_id = item->getUUID();
- const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id);
- if (!wearable)
- continue;
-
- // Find and remove this item from the COF.
- LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false);
- }
- }
- gInventory.notifyObservers();
-
- // Remove wearables from gAgentWearables
- LLAgentWearables::userRemoveAllClothes();
-}
-
-// static
-void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item)
-{
- if (item)
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(item->getUUID()));
- }
-}
-
void LLWearableBridge::removeFromAvatar()
{
+ LL_WARNS() << "safe to remove?" << LL_ENDL;
if (get_is_item_worn(mUUID))
{
- LLViewerInventoryItem* item = getItem();
- removeItemFromAvatar(item);
+ LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
}
}
+
// +=================================================+
// | LLLinkItemBridge |
// +=================================================+
@@ -4927,7 +6002,7 @@ std::string LLLinkItemBridge::sPrefix("Link: ");
void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
// *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLLink::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
@@ -4947,6 +6022,56 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
// +=================================================+
+// | LLMeshBridge |
+// +=================================================+
+
+LLUIImagePtr LLMeshBridge::getIcon() const
+{
+ return LLInventoryIcon::getIcon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
+}
+
+void LLMeshBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ // open mesh
+ }
+}
+
+void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LL_DEBUGS() << "LLMeshBridge::buildContextMenu()" << LL_ENDL;
+ std::vector<std::string> items;
+ std::vector<std::string> 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"));
+ }
+ else if(isOutboxFolder())
+ {
+ addOutboxContextMenuOptions(flags, items, disabled_items);
+ }
+ else
+ {
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+// +=================================================+
// | LLLinkBridge |
// +=================================================+
// For broken folder links.
@@ -4974,7 +6099,7 @@ LLUIImagePtr LLLinkFolderBridge::getIcon() const
void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
// *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
+ LL_DEBUGS() << "LLLink::buildContextMenu()" << LL_ENDL;
menuentry_vec_t items;
menuentry_vec_t disabled_items;
@@ -5003,14 +6128,15 @@ void LLLinkFolderBridge::gotoItem()
const LLUUID &cat_uuid = getFolderID();
if (!cat_uuid.isNull())
{
- if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid))
+ LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid);
+ if (base_folder)
{
if (LLInventoryModel* model = getInventoryModel())
{
model->fetchDescendentsOf(cat_uuid);
}
base_folder->setOpen(TRUE);
- mRoot->setSelectionFromRoot(base_folder,TRUE);
+ mRoot->setSelection(base_folder,TRUE);
mRoot->scrollToShowSelection();
}
}
@@ -5100,7 +6226,7 @@ public:
LLViewerInventoryItem* item = getItem();
if (item)
{
- LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
+ send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
}
LLInvFVBridgeAction::doIt();
}
@@ -5252,6 +6378,7 @@ public:
{
wearOnAvatar();
}
+
virtual ~LLWearableBridgeAction(){}
protected:
LLWearableBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
@@ -5340,9 +6467,8 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
/************************************************************************/
void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- LLFolderBridge::buildContextMenu(menu, flags);
-
- menuentry_vec_t disabled_items, items = getMenuItems();
+ menuentry_vec_t disabled_items, items;
+ buildContextMenuOptions(flags, items, disabled_items);
items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
@@ -5354,42 +6480,47 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
+ LLFolderViewModelInventory* view_model,
LLFolderView* root,
const LLUUID& uuid,
U32 flags /*= 0x00*/ ) const
{
LLInvFVBridge* new_listener = NULL;
- switch(asset_type)
+ if (asset_type == LLAssetType::AT_CATEGORY
+ && actual_asset_type != LLAssetType::AT_LINK_FOLDER)
{
- case LLAssetType::AT_CATEGORY:
- if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid);
+ }
+ else
{
- // *TODO: Create a link folder handler instead if it is necessary
- new_listener = LLInventoryFVBridgeBuilder::createBridge(
- asset_type,
+ new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type,
actual_asset_type,
inv_type,
inventory,
+ view_model,
root,
uuid,
flags);
- break;
}
- new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid);
- break;
- default:
- new_listener = LLInventoryFVBridgeBuilder::createBridge(
- asset_type,
- actual_asset_type,
- inv_type,
- inventory,
- root,
- uuid,
- flags);
- }
return new_listener;
+}
+LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge()
+{
}
+void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu)
+{
+ 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);
+}
// EOF