From ed02d0c1fccbfd25ed54f6be5b051736834d2e27 Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Fri, 29 Jul 2011 17:01:24 -0700 Subject: EXP-843 Enable drag and drop to and from the outbox, with conditional warnings based on permissions EXP-1034 Add confirmation dialog for moving no-copy items to outbox --- indra/newview/llinventorybridge.cpp | 158 +++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ff328fd071..8eacb5a719 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -573,7 +573,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } // Don't allow items to be pasted directly into the COF or the inbox - if (!isCOFFolder() && !isInboxFolder()) + if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) { items.push_back(std::string("Paste")); } @@ -794,6 +794,20 @@ BOOL LLInvFVBridge::isInboxFolder() const return gInventory.isObjectDescendentOf(mUUID, inbox_id); } + +BOOL LLInvFVBridge::isOutboxFolder() const +{ + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + + if (outbox_id.isNull()) + { + return FALSE; + } + + return gInventory.isObjectDescendentOf(mUUID, outbox_id); +} + + BOOL LLInvFVBridge::isItemPermissive() const { return FALSE; @@ -1648,6 +1662,55 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const } +static BOOL can_move_to_outbox(LLInventoryItem* inv_item) +{ + return inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); +} + + +void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) +{ + LLUUID dest_folder_id = gInventory.createNewCategory(mUUID, LLFolderType::FT_NONE, inv_cat->getName()); + + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array); + + for (LLInventoryModel::item_array_t::iterator iter = item_array->begin(); iter != item_array->end(); iter++) + { + LLInventoryItem* item = *iter; + if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + //LLPointer cb = new OutboxMoveCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + dest_folder_id, + item->getName(), + LLPointer(NULL)); + + } + else + { + LLSD args; + args["ITEM_NAME"] = item->getName(); + LLSD payload; + payload["item_id"] = item->getUUID(); + payload["dest_folder_id"] = dest_folder_id; + LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&LLFolderBridge::moveToOutbox, this, _1, _2)); + } + + } + /* + // we need to also drill down recursively + for (LLInventoryModel::cat_array_t::iterator iter = cat_array->begin(); iter != cat_array->end(); iter++) + { + LLViewerInventoryCategory* category = gInventory.getCategory(dest_folder_id); + } + */ +} + BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, BOOL drop) { @@ -1674,10 +1737,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, 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 &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, 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_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); //-------------------------------------------------------------------------------- // Determine if folder can be moved. @@ -1730,6 +1795,18 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } + if (move_is_into_outbox) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (!can_move_to_outbox(item)) + { + is_movable = FALSE; + break; + } + } + } // //-------------------------------------------------------------------------------- @@ -1797,6 +1874,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, #endif } } + if (move_is_into_outbox) + { + dropFolderToOutbox(inv_cat); + } else { if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) @@ -2635,7 +2716,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { - if (!isInboxFolder()) // don't allow creation in inbox + if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) @@ -3003,6 +3084,67 @@ static BOOL can_move_to_landmarks(LLInventoryItem* inv_item) return LLAssetType::AT_LANDMARK == inv_item->getType(); } +void LLFolderBridge::dropToOutbox(LLInventoryItem* inv_item) +{ + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + LLUUID dest_folder_id = mUUID; + + // when moving item directly into outbox create folder with that name + if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder_id = gInventory.createNewCategory(mUUID, LLFolderType::FT_NONE, inv_item->getName()); + } + + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + dest_folder_id, + inv_item->getName(), + LLPointer(NULL)); + + } + else + { + LLSD args; + args["ITEM_NAME"] = inv_item->getName(); + LLSD payload; + payload["item_id"] = inv_item->getUUID(); + payload["dest_folder_id"] = mUUID; + LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&LLFolderBridge::moveToOutbox, this, _1, _2)); + } +} + + +void LLFolderBridge::moveToOutbox(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryItem * viitem = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + LLUUID dest_folder_id = notification["payload"]["dest_folder_id"].asUUID(); + + if (viitem) + { + + // when moving item directly into outbox create folder with that name + if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder_id = gInventory.createNewCategory(mUUID, LLFolderType::FT_NONE, viitem->getName()); + } + + LLInvFVBridge::changeItemParent( + model, + viitem, + dest_folder_id, + false); + } + +} + void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) { // use callback to rearrange favorite landmarks after adding @@ -3060,11 +3202,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const LLUUID ¤t_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 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_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); //(mUUID == outbox_id); LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); BOOL accept = FALSE; @@ -3130,6 +3274,10 @@ 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); + } if(accept && drop) { @@ -3180,6 +3328,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } + else if (move_is_into_outbox) + { + dropToOutbox(inv_item); + } // NORMAL or TRASH folder // (move the item, restamp if into trash) else -- cgit v1.3 From e69efc8369a65008d41155717761fbaec0e309c5 Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Fri, 12 Aug 2011 10:39:35 -0700 Subject: EXP-843 Enable drag and drop from the outbox EXP-1036 Disable most inventory functionality for the outbox view --- indra/newview/llinventorybridge.cpp | 186 +++++++++++++-------------------- indra/newview/llinventorybridge.h | 1 - indra/newview/llinventoryfunctions.cpp | 97 +++++++++++++++++ indra/newview/llinventoryfunctions.h | 4 + 4 files changed, 175 insertions(+), 113 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8eacb5a719..a6a8bc662f 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -610,6 +610,10 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -1664,51 +1668,17 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const static BOOL can_move_to_outbox(LLInventoryItem* inv_item) { - return inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + bool worn = get_is_item_worn(inv_item->getUUID()); + bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + + return !worn && allow_transfer; } + void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) { - LLUUID dest_folder_id = gInventory.createNewCategory(mUUID, LLFolderType::FT_NONE, inv_cat->getName()); - - LLInventoryModel::cat_array_t* cat_array; - LLInventoryModel::item_array_t* item_array; - gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array); - - for (LLInventoryModel::item_array_t::iterator iter = item_array->begin(); iter != item_array->end(); iter++) - { - LLInventoryItem* item = *iter; - if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) - { - //LLPointer cb = new OutboxMoveCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - dest_folder_id, - item->getName(), - LLPointer(NULL)); - - } - else - { - LLSD args; - args["ITEM_NAME"] = item->getName(); - LLSD payload; - payload["item_id"] = item->getUUID(); - payload["dest_folder_id"] = dest_folder_id; - LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&LLFolderBridge::moveToOutbox, this, _1, _2)); - } - - } - /* - // we need to also drill down recursively - for (LLInventoryModel::cat_array_t::iterator iter = cat_array->begin(); iter != cat_array->end(); iter++) - { - LLViewerInventoryCategory* category = gInventory.getCategory(dest_folder_id); - } - */ + copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)); } BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, @@ -2574,6 +2544,7 @@ void LLFolderBridge::folderOptionsMenu() 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); @@ -2709,6 +2680,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mItems.clear(); // clear any items that used to exist addTrashContextMenuOptions(mItems, mDisabledItems); } + else if(isOutboxFolder()) + { + mItems.push_back(std::string("Delete")); + } else if(isAgentInventory()) // do not allow creating in library { LLViewerInventoryCategory *cat = getCategory(); @@ -2783,10 +2758,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.push_back(std::string("Delete System Folder")); } - mItems.push_back(std::string("Share")); - if (!canShare()) + if (!isOutboxFolder()) { - mDisabledItems.push_back(std::string("Share")); + mItems.push_back(std::string("Share")); + if (!canShare()) + { + mDisabledItems.push_back(std::string("Share")); + } } hide_context_entries(menu, mItems, mDisabledItems); @@ -3084,67 +3062,6 @@ static BOOL can_move_to_landmarks(LLInventoryItem* inv_item) return LLAssetType::AT_LANDMARK == inv_item->getType(); } -void LLFolderBridge::dropToOutbox(LLInventoryItem* inv_item) -{ - if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) - { - LLUUID dest_folder_id = mUUID; - - // when moving item directly into outbox create folder with that name - if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) - { - dest_folder_id = gInventory.createNewCategory(mUUID, LLFolderType::FT_NONE, inv_item->getName()); - } - - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - dest_folder_id, - inv_item->getName(), - LLPointer(NULL)); - - } - else - { - LLSD args; - args["ITEM_NAME"] = inv_item->getName(); - LLSD payload; - payload["item_id"] = inv_item->getUUID(); - payload["dest_folder_id"] = mUUID; - LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&LLFolderBridge::moveToOutbox, this, _1, _2)); - } -} - - -void LLFolderBridge::moveToOutbox(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; // canceled - - - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryItem * viitem = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - LLUUID dest_folder_id = notification["payload"]["dest_folder_id"].asUUID(); - - if (viitem) - { - - // when moving item directly into outbox create folder with that name - if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) - { - dest_folder_id = gInventory.createNewCategory(mUUID, LLFolderType::FT_NONE, viitem->getName()); - } - - LLInvFVBridge::changeItemParent( - model, - viitem, - dest_folder_id, - false); - } - -} - void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) { // use callback to rearrange favorite landmarks after adding @@ -3330,7 +3247,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if (move_is_into_outbox) { - dropToOutbox(inv_item); + copy_item_to_outbox(inv_item, outbox_id); } // NORMAL or TRASH folder // (move the item, restamp if into trash) @@ -3532,6 +3449,10 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3608,6 +3529,10 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3622,8 +3547,11 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - items.push_back(std::string("Sound Separator")); - items.push_back(std::string("Sound Play")); + if (!isOutboxFolder()) + { + items.push_back(std::string("Sound Separator")); + items.push_back(std::string("Sound Play")); + } hide_context_entries(menu, items, disabled_items); } @@ -3659,6 +3587,10 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3673,8 +3605,11 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - items.push_back(std::string("Landmark Separator")); - items.push_back(std::string("About Landmark")); + if (!isOutboxFolder()) + { + 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 @@ -3888,6 +3823,10 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -4145,6 +4084,10 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addTrashContextMenuOptions(items, disabled_items); } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); + } else { items.push_back(std::string("Share")); @@ -4198,6 +4141,10 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -4212,9 +4159,12 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) 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")); + if (!isOutboxFolder()) + { + 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); @@ -4471,6 +4421,10 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -4804,6 +4758,10 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { 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); @@ -5201,6 +5159,10 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Restore Item")); } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); + } else { items.push_back(std::string("Properties")); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 262f4ffdcf..b557e128a7 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -301,7 +301,6 @@ protected: void dropToFavorites(LLInventoryItem* inv_item); void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); void dropToOutbox(LLInventoryItem* inv_item); - void moveToOutbox(const LLSD& notification, const LLSD& response); void dropFolderToOutbox(LLInventoryCategory* inv_cat); //-------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index db3b968730..91026367c7 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -58,6 +58,7 @@ #include "llinventorypanel.h" #include "lllineeditor.h" #include "llmenugl.h" +#include "llnotificationsutil.h" #include "llpanelmaininventory.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" @@ -471,6 +472,102 @@ void show_item_original(const LLUUID& item_uuid) } } +void move_to_outbox_cb(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + LLViewerInventoryItem * viitem = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + LLUUID dest_folder_id = notification["payload"]["dest_folder_id"].asUUID(); + + if (viitem) + { + // when moving item directly into outbox create folder with that name + if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder_id = gInventory.createNewCategory(dest_folder_id, LLFolderType::FT_NONE, viitem->getName()); + } + + //LLUUID old_parent = viitem->getParentUUID(); + + change_item_parent( + &gInventory, + viitem, + dest_folder_id, + false); + + //LLInventoryModel::cat_array_t* cat_array; + //LLInventoryModel::item_array_t* item_array; + //gInventory.getDirectDescendentsOf(old_parent,cat_array,item_array); + + //if (cat_array->empty() && item_array->empty()) + //{ + // remove_category(&gInventory, old_parent); + //} + } +} + +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder) +{ + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // when moving item directly into outbox create folder with that name + if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName()); + } + + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + dest_folder, + inv_item->getName(), + LLPointer(NULL)); + } + else + { + LLSD args; + args["ITEM_NAME"] = inv_item->getName(); + LLSD payload; + payload["item_id"] = inv_item->getUUID(); + payload["dest_folder_id"] = dest_folder; + LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2)); + } +} + +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder) +{ + LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName()); + + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array); + + // copy the vector because otherwise the iterator won't be happy if we delete from it + 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; + copy_item_to_outbox(item, new_folder_id); + } + + 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++) + { + LLViewerInventoryCategory* category = *iter; + copy_folder_to_outbox(category, new_folder_id); + } + + // delete the folder if we have emptied it + //if (cat_array->empty() && item_array->empty()) + //{ + // remove_category(inventory_model, inv_cat->getUUID()); + //} +} + ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 2016b92666..940f5a2c98 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -71,6 +71,10 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder); + +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder); + /** Miscellaneous global functions ** ** *******************************************************************************/ -- cgit v1.3 From 6f7132ca77d0507f2744bea5050a2ab1135cd88a Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Mon, 15 Aug 2011 09:53:26 -0700 Subject: deleting folders after no-copy move to outbox --- indra/newview/llinventorybridge.cpp | 4 +-- indra/newview/llinventoryfunctions.cpp | 52 ++++++++++++++++++++++++++-------- indra/newview/llinventoryfunctions.h | 4 +-- 3 files changed, 44 insertions(+), 16 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a6a8bc662f..ac53532e32 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1678,7 +1678,7 @@ static BOOL can_move_to_outbox(LLInventoryItem* inv_item) void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) { - copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)); + copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false), inv_cat->getUUID()); } BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, @@ -3247,7 +3247,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if (move_is_into_outbox) { - copy_item_to_outbox(inv_item, outbox_id); + copy_item_to_outbox(inv_item, outbox_id, LLUUID::null); } // NORMAL or TRASH folder // (move the item, restamp if into trash) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 91026367c7..b5be0a971d 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -488,7 +488,7 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response) dest_folder_id = gInventory.createNewCategory(dest_folder_id, LLFolderType::FT_NONE, viitem->getName()); } - //LLUUID old_parent = viitem->getParentUUID(); + LLUUID parent = viitem->getParentUUID(); change_item_parent( &gInventory, @@ -496,18 +496,45 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response) dest_folder_id, false); - //LLInventoryModel::cat_array_t* cat_array; - //LLInventoryModel::item_array_t* item_array; - //gInventory.getDirectDescendentsOf(old_parent,cat_array,item_array); + LLUUID top_level_folder = notification["payload"]["top_level_folder"].asUUID(); + + if (top_level_folder != LLUUID::null) + { + LLViewerInventoryCategory* category; + + while (parent.notNull()) + { + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(parent,cat_array,item_array); + + LLUUID next_parent; + + category = gInventory.getCategory(parent); + + if (!category) break; + + next_parent = category->getParentUUID(); + + if (cat_array->empty() && item_array->empty()) + { + remove_category(&gInventory, parent); + } + + if (parent == top_level_folder) + { + break; + } + + parent = next_parent; + } + } - //if (cat_array->empty() && item_array->empty()) - //{ - // remove_category(&gInventory, old_parent); - //} } } -void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder) + +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder) { if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) { @@ -532,11 +559,12 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder) LLSD payload; payload["item_id"] = inv_item->getUUID(); payload["dest_folder_id"] = dest_folder; + payload["top_level_folder"] = top_level_folder; LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2)); } } -void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder) +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder) { LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName()); @@ -550,7 +578,7 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) { LLInventoryItem* item = *iter; - copy_item_to_outbox(item, new_folder_id); + copy_item_to_outbox(item, new_folder_id, top_level_folder); } LLInventoryModel::cat_array_t cat_array_copy = *cat_array; @@ -558,7 +586,7 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) { LLViewerInventoryCategory* category = *iter; - copy_folder_to_outbox(category, new_folder_id); + copy_folder_to_outbox(category, new_folder_id, top_level_folder); } // delete the folder if we have emptied it diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 940f5a2c98..3e80fe322c 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -71,9 +71,9 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); -void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder); +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder); -void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder); +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder); /** Miscellaneous global functions ** ** -- cgit v1.3 From 8baafe6613e62a76c6a0b85842cc7d542d615e71 Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Thu, 18 Aug 2011 14:33:54 -0700 Subject: EXP-1098 User can drag folders into Outbox with more than 3 levels of nested folders EXP-1100 Show tooltips when drag and drop operations are not allowed --- indra/newview/llfoldervieweventlistener.h | 3 +- indra/newview/llfolderviewitem.cpp | 6 +- indra/newview/llinventorybridge.cpp | 88 ++++++++++++++++++++++---- indra/newview/llinventorybridge.h | 14 ++-- indra/newview/llpanelobjectinventory.cpp | 12 ++-- indra/newview/skins/default/xui/en/strings.xml | 7 +- 6 files changed, 105 insertions(+), 25 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index 3bfbf36110..aee31ca033 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -96,7 +96,8 @@ public: // otherwise FALSE. virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) = 0; + void* cargo_data, + std::string& tooltip_msg) = 0; }; #endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index e2b7c45eab..2f07e084ab 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -840,7 +840,7 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, BOOL handled = FALSE; if(mListener) { - accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data); + accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); handled = accepted; if (accepted) { @@ -2162,7 +2162,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data); + BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { mDragAndDropTarget = TRUE; @@ -2254,7 +2254,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, if (!handled) { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data); + BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ac53532e32..01d4153d3f 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1666,10 +1666,19 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const } -static BOOL can_move_to_outbox(LLInventoryItem* inv_item) +static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg) { bool worn = get_is_item_worn(inv_item->getUUID()); bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + + if (!allow_transfer) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); + } + else if(worn) + { + tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); + } return !worn && allow_transfer; } @@ -1681,8 +1690,53 @@ void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false), inv_cat->getUUID()); } + + +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->count(); ++i) + { + LLInventoryCategory* category = cats->get(i); + max_child_levels = max(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); + } + + llwarns << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << llendl; + return -1; +} + BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) + BOOL drop, + std::string& tooltip_msg) { LLInventoryModel* model = getInventoryModel(); @@ -1770,12 +1824,21 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, for (S32 i=0; i < descendent_items.count(); ++i) { LLInventoryItem* item = descendent_items[i]; - if (!can_move_to_outbox(item)) + if (!can_move_to_outbox(item, tooltip_msg)) { is_movable = FALSE; break; } } + + int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); + + if (nested_folder_levels > 4) + { + tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); + is_movable = FALSE; + } + } // @@ -2805,7 +2868,8 @@ 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; @@ -2825,7 +2889,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_MESH: - accept = dragItemIntoFolder(inv_item, drop); + 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. @@ -2836,12 +2900,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: @@ -2851,7 +2915,7 @@ 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: @@ -3108,7 +3172,8 @@ 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(); @@ -3193,7 +3258,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if (move_is_into_outbox) { - accept = can_move_to_outbox(inv_item); + accept = can_move_to_outbox(inv_item, tooltip_msg); } if(accept && drop) @@ -3869,7 +3934,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; diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b557e128a7..4a64df1371 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -115,7 +115,8 @@ public: virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) { return FALSE; } + void* cargo_data, + std::string& tooltip_msg) { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return mInvType; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } @@ -229,8 +230,9 @@ public: mCallingCards(FALSE), mWearables(FALSE) {} - BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop); - BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop); + + BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); + BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); @@ -256,7 +258,8 @@ public: virtual BOOL hasChildren() const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); virtual BOOL isItemRemovable() const; virtual BOOL isItemMovable() const ; @@ -381,7 +384,8 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); void refreshFolderViewItem(); protected: LLCallingCardObserver* mObserver; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 83ba8afbfc..44364b5831 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -140,7 +140,8 @@ public: virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); }; LLTaskInvFVBridge::LLTaskInvFVBridge( @@ -581,7 +582,8 @@ BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) + void* cargo_data, + std::string& tooltip_msg) { //llinfos << "LLTaskInvFVBridge::dragOrDrop()" << llendl; return FALSE; @@ -711,7 +713,8 @@ public: virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); virtual BOOL canOpenItem() const { return TRUE; } virtual void openItem(); }; @@ -805,7 +808,8 @@ BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) + void* cargo_data, + std::string& tooltip_msg) { //llinfos << "LLTaskCategoryBridge::dragOrDrop()" << llendl; BOOL accept = FALSE; diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f049f857f0..ced1826a03 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -165,7 +165,12 @@ Please try logging in again in a minute. Only a single item can be dragged here - + One or more of these objects cannot be sold or transferred to another user. + ou are wearing one or more of these objects. Remove them from your avatar and try moving them again. + This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C). + This folder contains more than 200 objects. Box some of the items to reduce the object count. + + Click to view this web page Click to view this location's information Click to view this Resident's profile -- cgit v1.3 From 504fabba1d8d2ffd1d3c43368cbd1a8522ca2ebc Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Thu, 18 Aug 2011 18:04:44 -0700 Subject: fixing inner inbox drag and drop --- indra/newview/llinventorybridge.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 01d4153d3f..5c13a46f56 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1767,6 +1767,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const BOOL move_is_into_outfit = 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_cat->getUUID(), outbox_id); //-------------------------------------------------------------------------------- // Determine if folder can be moved. @@ -1907,7 +1908,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, #endif } } - if (move_is_into_outbox) + if (move_is_into_outbox && !move_is_from_outbox) { dropFolderToOutbox(inv_cat); } @@ -3191,6 +3192,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const BOOL move_is_into_outfit = (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); //(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; @@ -3310,7 +3312,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } - else if (move_is_into_outbox) + else if (move_is_into_outbox && !move_is_from_outbox) { copy_item_to_outbox(inv_item, outbox_id, LLUUID::null); } -- cgit v1.3 From 38aa19614e1242e02c23a5dd2fbf5fae49783ed9 Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Fri, 19 Aug 2011 11:52:33 -0700 Subject: Mac build fix: changed "max" to "llmax" --- indra/newview/llinventorybridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5c13a46f56..0959a08359 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1703,7 +1703,7 @@ int get_folder_levels(LLInventoryCategory* inv_cat) for (S32 i=0; i < cats->count(); ++i) { LLInventoryCategory* category = cats->get(i); - max_child_levels = max(max_child_levels, get_folder_levels(category)); + max_child_levels = llmax(max_child_levels, get_folder_levels(category)); } return 1 + max_child_levels; -- cgit v1.3 From c2443b95d3cd9f0f26e5e8f5c2dbeb5f6c307447 Mon Sep 17 00:00:00 2001 From: "leslie@leslie-HPz600.lindenlab.com" Date: Fri, 26 Aug 2011 16:33:47 -0700 Subject: EXP-1126 FIX -- Cannot use arrow keys to scroll up and down in Inbox and Outbox EXP-1003 FIX -- Renaming a folder in Received Items panel resets the New flag for that folder EXP-1001 FIX -- Newness is removed on next login if you log out or crash before opening inventory panel EXP-857 FIX -- Add context menu entries as alternate path to populate outbox EXP-858 FIX -- Outbox sync failure error handling EXP-1158 FIX -- Viewer crash when deleting items from Outbox when some folders are open * Made inbox, outbox and inventory panels all legit tab stops for keyboard focus * Added mouse over indication on inventory panel primarily for increased clarity on outbox error messages * Disabled "Rename" option on inbox items * Added context menu option to copy/move an item to the merchant outbox * Context menu option to copy/move to outbox is visible and/or enabled/disabled when appropriate * "LastInventoryInboxCollapse" no longer written out as a setting when the panel is not visible * Fixed up collapse time check to not try to parse empty string on first load (deminishes text spam in log greatly) * Disabled double-click as a way to equip items in the inbox or outbox * Viewer code no longer removes items from the outbox after sync. We rely on the sim to do this now. * Basic outbox sync error handling now displays error messages as tooltips along with badge over item in outbox * Moved some scroll container default values out of code and into xml --- indra/llui/llscrollcontainer.cpp | 3 - indra/newview/llfolderviewitem.cpp | 21 ++- indra/newview/llfolderviewitem.h | 3 + indra/newview/llinventorybridge.cpp | 144 ++++++++++++++++++--- indra/newview/llinventorybridge.h | 11 +- indra/newview/llpanelmarketplaceinbox.cpp | 2 +- indra/newview/llpanelmarketplaceinboxinventory.cpp | 37 +++++- indra/newview/llpanelmarketplaceinboxinventory.h | 14 +- indra/newview/llpanelmarketplaceoutbox.cpp | 46 +++++-- .../newview/llpanelmarketplaceoutboxinventory.cpp | 108 +++++++++++++++- indra/newview/llpanelmarketplaceoutboxinventory.h | 25 +++- indra/newview/llsidepanelinventory.cpp | 26 ++-- indra/newview/skins/default/colors.xml | 8 +- .../skins/default/xui/en/menu_inventory.xml | 21 ++- indra/newview/skins/default/xui/en/strings.xml | 12 +- .../default/xui/en/widgets/scroll_container.xml | 5 +- 16 files changed, 426 insertions(+), 60 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 380c477eb2..112622d3f7 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -75,9 +75,6 @@ LLScrollContainer::Params::Params() max_auto_scroll_rate("max_auto_scroll_rate", 1000), reserve_scroll_corner("reserve_scroll_corner", false) { - name = "scroll_container"; - mouse_opaque(true); - tab_stop(false); } diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 2f07e084ab..72e2294196 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -132,7 +132,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mIconOpen(p.icon_open), mIconOverlay(p.icon_overlay), mListener(p.listener), - mShowLoadStatus(false) + mShowLoadStatus(false), + mIsMouseOverTitle(false) { } @@ -724,6 +725,8 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + if( hasMouseCapture() && isMovable() ) { S32 screen_x; @@ -830,6 +833,11 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) return TRUE; } +void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = false; +} + BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -879,6 +887,7 @@ void LLFolderViewItem::draw() static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); const Params& default_params = LLUICtrlFactory::getDefaultParams(); const S32 TOP_PAD = default_params.item_top_pad; @@ -960,6 +969,14 @@ void LLFolderViewItem::draw() } } } + else if (mIsMouseOverTitle) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sMouseOverColor, FALSE); + } //--------------------------------------------------------------------------------// // Draw DragNDrop highlight @@ -2299,6 +2316,8 @@ BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) { + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + BOOL handled = LLView::handleHover(x, y, mask); if (!handled) diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index dac0c3032c..ce936b4991 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -159,6 +159,7 @@ protected: BOOL mIsLoading; LLTimer mTimeSinceRequestStart; bool mShowLoadStatus; + bool mIsMouseOverTitle; // helper function to change the selection from the root. void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); @@ -328,6 +329,8 @@ public: virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } // virtual void handleDropped(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0959a08359..f3429607e9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -107,6 +107,23 @@ 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); +// 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)); +} + // +=================================================+ // | LLInvFVBridge | // +=================================================+ @@ -538,10 +555,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) @@ -569,6 +590,26 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { disabled_items.push_back(std::string("Copy")); } + + if (canListOnMarketplace()) + { + items.push_back(std::string("Marketplace Separator")); + + bool copyable = true; + LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); + if (inv_item) + { + copyable = inv_item->getPermissions().allowCopyBy(gAgent.getID()); + } + + const std::string merchant_action = ((copyable == true) ? "Merchant Copy" : "Merchant Move"); + items.push_back(merchant_action); + + if (!canListOnMarketplaceNow()) + { + disabled_items.push_back(merchant_action); + } + } } } @@ -798,10 +839,9 @@ BOOL LLInvFVBridge::isInboxFolder() const return gInventory.isObjectDescendentOf(mUUID, inbox_id); } - BOOL LLInvFVBridge::isOutboxFolder() const { - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + const LLUUID outbox_id = getOutboxFolder(); if (outbox_id.isNull()) { @@ -811,6 +851,12 @@ BOOL LLInvFVBridge::isOutboxFolder() const return gInventory.isObjectDescendentOf(mUUID, outbox_id); } +const LLUUID LLInvFVBridge::getOutboxFolder() const +{ + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + + return outbox_id; +} BOOL LLInvFVBridge::isItemPermissive() const { @@ -956,9 +1002,14 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, new_listener = new LLMeshBridge(inventory, root, uuid); break; + case LLAssetType::AT_IMAGE_TGA: + case LLAssetType::AT_IMAGE_JPEG: + //llwarns << LLAssetType::lookup(asset_type) << " asset type is unhandled for uuid " << uuid << llendl; + break; + default: llinfos << "Unhandled asset type (llassetstorage.h): " - << (S32)asset_type << llendl; + << (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << llendl; break; } @@ -1007,6 +1058,50 @@ BOOL LLInvFVBridge::canShare() const return FALSE; } +BOOL LLInvFVBridge::canListOnMarketplace() const +{ + 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 && !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + return FALSE; + } + + return TRUE; +} + +BOOL LLInvFVBridge::canListOnMarketplaceNow() const +{ + if (get_is_item_worn(mUUID)) + { + return FALSE; + } + + return TRUE; +} + + // +=================================================+ // | InventoryFVBridgeBuilder | // +=================================================+ @@ -1104,6 +1199,16 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) folder_view_itemp->getListener()->pasteLinkFromClipboard(); return; } + else if (isMarketplaceCopyAction(action)) + { + llinfos << "Copy item to marketplace action!" << llendl; + + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + copy_item_to_outbox(itemp, outbox_id, LLUUID::null); + } } void LLItemBridge::selectItem() @@ -1244,7 +1349,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"); @@ -1312,6 +1417,11 @@ BOOL LLItemBridge::isItemRenameable() const return FALSE; } + if (isInboxFolder()) + { + return FALSE; + } + return (item->getPermissions().allowModifyBy(gAgent.getID())); } return FALSE; @@ -1475,16 +1585,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 | // +=================================================+ @@ -2324,6 +2424,16 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) removeSystemFolder(); } #endif + else if (isMarketplaceCopyAction(action)) + { + llinfos << "Copy folder to marketplace action!" << llendl; + + LLInventoryCategory * cat = gInventory.getCategory(mUUID); + if (!cat) return; + + const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + copy_folder_to_outbox(cat, outbox_id, cat->getUUID()); + } } void LLFolderBridge::openItem() diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 4a64df1371..2d625befb4 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -52,7 +52,7 @@ typedef std::vector menuentry_vec_t; // // You'll want to call LLInvItemFVELister::createBridge() to actually create // an instance of this class. This helps encapsulate the -// funcationality a bit. (except for folders, you can create those +// functionality a bit. (except for folders, you can create those // manually...) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInvFVBridge : public LLFolderViewEventListener @@ -70,6 +70,8 @@ public: virtual ~LLInvFVBridge() {} BOOL canShare() const; + BOOL canListOnMarketplace() const; + BOOL canListOnMarketplaceNow() const; //-------------------------------------------------------------------- // LLInvFVBridge functionality @@ -141,7 +143,9 @@ protected: BOOL isAgentInventory() const; // false if lost or in the inventory library BOOL isCOFFolder() const; // true if COF or descendent of BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox - BOOL isOutboxFolder() const; // true if COF or descendent of marketplace inbox + BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox + const LLUUID getOutboxFolder() const; + virtual BOOL isItemPermissive() const; static void changeItemParent(LLInventoryModel* model, LLViewerInventoryItem* item, @@ -210,8 +214,7 @@ public: /*virtual*/ void clearDisplayName() { mDisplayName.clear(); } LLViewerInventoryItem* getItem() const; - bool isAddAction(std::string action) const; - bool isRemoveAction(std::string action) const; + protected: BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response); virtual BOOL isItemPermissive() const; diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 3fc10eb176..5a835eadf1 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -53,7 +53,7 @@ LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p) LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox() { - if (getChild("inbox_btn")->getToggleState()) + if (getVisible() && getChild("inbox_btn")->getToggleState()) { gSavedPerAccountSettings.setString("LastInventoryInboxCollapse", LLDate::now().asString()); } diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index de4e4414c4..e2f8af1280 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -133,6 +133,27 @@ LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge return LLUICtrlFactory::create(params); } +LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) +{ + LLFolderViewItem::Params params; + + params.name = bridge->getDisplayName(); + params.icon = bridge->getIcon(); + params.icon_open = bridge->getOpenIcon(); + + if (mShowItemLinkOverlays) // if false, then links show up just like normal items + { + params.icon_overlay = LLUI::getUIImage("Inv_Link"); + } + + params.creation_date = bridge->getCreationDate(); + params.root = mFolderRoot; + params.listener = bridge; + params.rect = LLRect (0, 0, 0, 0); + params.tool_tip = params.name; + + return LLUICtrlFactory::create(params); +} // // LLInboxFolderViewFolder Implementation @@ -182,8 +203,12 @@ void LLInboxFolderViewFolder::draw() void LLInboxFolderViewFolder::updateFlag() const { - LLDate saved_freshness_date = LLDate(gSavedPerAccountSettings.getString("LastInventoryInboxCollapse")); - mFresh = (mCreationDate > saved_freshness_date.secondsSinceEpoch()); + const std::string& last_collapse = gSavedPerAccountSettings.getString("LastInventoryInboxCollapse"); + if (!last_collapse.empty()) + { + LLDate saved_freshness_date = LLDate(last_collapse); + mFresh = (mCreationDate > saved_freshness_date.secondsSinceEpoch()); + } } void LLInboxFolderViewFolder::selectItem() @@ -204,5 +229,13 @@ void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) const updateFlag(); } +// +// LLInboxFolderViewItem Implementation +// + +BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + return TRUE; +} // eof diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d2d42e11f4..6cb243dbd5 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -52,7 +52,8 @@ public: void buildFolderView(const LLInventoryPanel::Params& params); // virtual - class LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge); + LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge); + LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge); }; @@ -89,4 +90,15 @@ protected: }; +class LLInboxFolderViewItem : public LLFolderViewItem +{ +public: + LLInboxFolderViewItem(const Params& p) + : LLFolderViewItem(p) + { + } + + BOOL handleDoubleClick(S32 x, S32 y, MASK mask); +}; + #endif //LL_INBOXINVENTORYPANEL_H diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp index 221420985a..839369bffe 100644 --- a/indra/newview/llpanelmarketplaceoutbox.cpp +++ b/indra/newview/llpanelmarketplaceoutbox.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llpanelmarketplaceoutbox.h" +#include "llpanelmarketplaceoutboxinventory.h" #include "llappviewer.h" #include "llbutton.h" @@ -36,6 +37,7 @@ #include "llloadingindicator.h" #include "llnotificationsutil.h" #include "llpanelmarketplaceinbox.h" +#include "llsdutil.h" #include "llsidepanelinventory.h" #include "llsidetray.h" #include "lltimer.h" @@ -198,13 +200,6 @@ public: { // Complete success llinfos << "success" << llendl; - LLSD imported_list = content["imported"]; - LLSD::array_const_iterator it = imported_list.beginArray(); - for ( ; it != imported_list.endArray(); ++it) - { - LLUUID imported_folder = (*it).asUUID(); - remove_category(&gInventory, imported_folder); - } } else { @@ -252,7 +247,9 @@ void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& conte mSyncInProgress = false; updateSyncButtonStatus(); - if (goodStatus) + const LLSD& errors_list = content["errors"]; + + if (goodStatus && (errors_list.size() == 0)) { LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap()); } @@ -260,6 +257,39 @@ void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& conte { LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap()); } + + llinfos << "Marketplace upload llsd:" << llendl; + llinfos << ll_pretty_print_sd(content) << llendl; + llinfos << llendl; + + const LLSD& imported_list = content["imported"]; + LLSD::array_const_iterator it = imported_list.beginArray(); + for ( ; it != imported_list.endArray(); ++it) + { + LLUUID imported_folder = (*it).asUUID(); + llinfos << "Successfully uploaded folder " << imported_folder.asString() << " to marketplace." << llendl; + } + + for (it = errors_list.beginArray(); it != errors_list.endArray(); ++it) + { + const LLSD& item_error_map = (*it); + + LLUUID error_folder = item_error_map["folder_id"].asUUID(); + const std::string& error_string = item_error_map["identifier"].asString(); + LLUUID error_item = item_error_map["item_id"].asUUID(); + const std::string& error_item_name = item_error_map["item_name"].asString(); + const std::string& error_message = item_error_map["message"].asString(); + + llinfos << "Error item " << error_folder.asString() << ", " << error_string << ", " + << error_item.asString() << ", " << error_item_name << ", " << error_message << llendl; + + LLFolderViewFolder * item_folder = mInventoryPanel->getRootFolder()->getFolderByID(error_folder); + LLOutboxFolderViewFolder * outbox_item_folder = dynamic_cast(item_folder); + + llassert(outbox_item_folder); + + outbox_item_folder->setErrorString(error_string); + } } void LLPanelMarketplaceOutbox::updateSyncButtonStatus() diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index 638d3c5150..14b6ee9e0a 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -34,6 +34,7 @@ #include "llinventoryfunctions.h" #include "llpanellandmarks.h" #include "llplacesinventorybridge.h" +#include "lltrans.h" #include "llviewerfoldertype.h" @@ -45,6 +46,50 @@ static LLDefaultChildRegistry::Register r1("outbox_inven static LLDefaultChildRegistry::Register r2("outbox_folder_view_folder"); +// +// Marketplace errors +// + +enum +{ + MKTERR_NONE = 0, + + MKTERR_NOT_MERCHANT, + MKTERR_FOLDER_EMPTY, + MKTERR_UNASSOCIATED_PRODUCTS, + MKTERR_OBJECT_LIMIT, + MKTERR_FOLDER_DEPTH, + MKTERR_UNSELLABLE_ITEM, + MKTERR_INTERNAL_IMPORT, + + MKTERR_COUNT +}; + +static const std::string MARKETPLACE_ERROR_STRINGS[MKTERR_COUNT] = +{ + "NO_ERROR", + "NOT_MERCHANT_ERROR", + "FOLDER_EMPTY_ERROR", + "UNASSOCIATED_PRODUCTS_ERROR", + "OBJECT_LIMIT_ERROR", + "FOLDER_DEPTH_ERROR", + "UNSELLABLE_ITEM_FOUND", + "INTERNAL_IMPORT_ERROR", +}; + +static const std::string MARKETPLACE_ERROR_NAMES[MKTERR_COUNT] = +{ + "Marketplace Error None", + "Marketplace Error Not Merchant", + "Marketplace Error Empty Folder", + "Marketplace Error Unassociated Products", + "Marketplace Error Object Limit", + "Marketplace Error Folder Depth", + "Marketplace Error Unsellable Item", + "Marketplace Error Internal Import", +}; + + // // LLOutboxInventoryPanel Implementation // @@ -133,6 +178,27 @@ LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridg return LLUICtrlFactory::create(params); } +LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) +{ + LLFolderViewItem::Params params; + + params.name = bridge->getDisplayName(); + params.icon = bridge->getIcon(); + params.icon_open = bridge->getOpenIcon(); + + if (mShowItemLinkOverlays) // if false, then links show up just like normal items + { + params.icon_overlay = LLUI::getUIImage("Inv_Link"); + } + + params.creation_date = bridge->getCreationDate(); + params.root = mFolderRoot; + params.listener = bridge; + params.rect = LLRect (0, 0, 0, 0); + params.tool_tip = params.name; + + return LLUICtrlFactory::create(params); +} // // LLOutboxFolderViewFolder Implementation @@ -141,7 +207,7 @@ LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridg LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p) : LLFolderViewFolder(p) , LLBadgeOwner(getHandle()) - , mError(false) + , mError(0) { initBadgeParams(p.error_badge()); } @@ -158,15 +224,53 @@ void LLOutboxFolderViewFolder::draw() addBadgeToParentPanel(); } - setBadgeVisibility(mError); + setBadgeVisibility(hasError()); LLFolderViewFolder::draw(); } +void LLOutboxFolderViewFolder::setErrorString(const std::string& errorString) +{ + S32 error_code = MKTERR_NONE; + + for (S32 i = 1; i < MKTERR_COUNT; ++i) + { + if (MARKETPLACE_ERROR_STRINGS[i] == errorString) + { + error_code = i; + break; + } + } + + setError(error_code); +} + +void LLOutboxFolderViewFolder::setError(S32 errorCode) +{ + mError = errorCode; + + if (hasError()) + { + setToolTip(LLTrans::getString(MARKETPLACE_ERROR_NAMES[mError])); + } + else + { + setToolTip(LLStringExplicit("")); + } +} + void LLOutboxFolderViewFolder::setCreationDate(time_t creation_date_utc) const { mCreationDate = creation_date_utc; } +// +// LLOutboxFolderViewItem Implementation +// + +BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + return TRUE; +} // eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h index ba68654ad7..ec55b7eb2e 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.h +++ b/indra/newview/llpanelmarketplaceoutboxinventory.h @@ -48,7 +48,8 @@ public: void buildFolderView(const LLInventoryPanel::Params& params); // virtual - class LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge); + LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge); + LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge); }; @@ -60,7 +61,7 @@ public: Optional error_badge; Params() - : error_badge("error_badge") + : error_badge("error_badge") { } }; @@ -69,13 +70,29 @@ public: ~LLOutboxFolderViewFolder(); void draw(); + + void setErrorString(const std::string& errorString); + void setError(S32 errorCode); - bool hasError() const { return mError; } + bool hasError() const { return (mError != 0); } protected: void setCreationDate(time_t creation_date_utc) const; - bool mError; + S32 mError; +}; + + +class LLOutboxFolderViewItem : public LLFolderViewItem +{ +public: + LLOutboxFolderViewItem(const Params& p) + : LLFolderViewItem(p) + { + } + + // virtual + BOOL handleDoubleClick(S32 x, S32 y, MASK mask); }; diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 5ae3a30fd5..9290b7ebef 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -520,14 +520,14 @@ bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLL void LLSidepanelInventory::onToggleInboxBtn() { - LLButton* pressedButton = getChild(INBOX_BUTTON_NAME); - LLLayoutPanel* pressedPanel = getChild(INBOX_LAYOUT_PANEL_NAME); - LLButton* otherButton = getChild(OUTBOX_BUTTON_NAME); - LLLayoutPanel* otherPanel = getChild(OUTBOX_LAYOUT_PANEL_NAME); + LLButton* inboxButton = getChild(INBOX_BUTTON_NAME); + LLLayoutPanel* inboxPanel = getChild(INBOX_LAYOUT_PANEL_NAME); + LLButton* outboxButton = getChild(OUTBOX_BUTTON_NAME); + LLLayoutPanel* outboxPanel = getChild(OUTBOX_LAYOUT_PANEL_NAME); - bool inbox_expanded = manageInboxOutboxPanels(pressedButton, pressedPanel, otherButton, otherPanel); + bool inbox_expanded = manageInboxOutboxPanels(inboxButton, inboxPanel, outboxButton, outboxPanel); - if (!inbox_expanded) + if (!inbox_expanded && inboxPanel->getVisible()) { gSavedPerAccountSettings.setString("LastInventoryInboxCollapse", LLDate::now().asString()); } @@ -535,15 +535,15 @@ void LLSidepanelInventory::onToggleInboxBtn() void LLSidepanelInventory::onToggleOutboxBtn() { - LLButton* pressedButton = getChild(OUTBOX_BUTTON_NAME); - LLLayoutPanel* pressedPanel = getChild(OUTBOX_LAYOUT_PANEL_NAME); - LLButton* otherButton = getChild(INBOX_BUTTON_NAME); - LLLayoutPanel* otherPanel = getChild(INBOX_LAYOUT_PANEL_NAME); + LLButton* inboxButton = getChild(INBOX_BUTTON_NAME); + LLLayoutPanel* inboxPanel = getChild(INBOX_LAYOUT_PANEL_NAME); + LLButton* outboxButton = getChild(OUTBOX_BUTTON_NAME); + LLLayoutPanel* outboxPanel = getChild(OUTBOX_LAYOUT_PANEL_NAME); - bool inbox_was_expanded = otherButton->getToggleState(); - manageInboxOutboxPanels(pressedButton, pressedPanel, otherButton, otherPanel); + bool inbox_was_expanded = inboxButton->getToggleState(); + manageInboxOutboxPanels(outboxButton, outboxPanel, inboxButton, inboxPanel); - if (inbox_was_expanded) + if (inbox_was_expanded && inboxPanel->getVisible()) { gSavedPerAccountSettings.setString("LastInventoryInboxCollapse", LLDate::now().asString()); } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 6144c761b7..d19e56e9a0 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -29,6 +29,9 @@ + @@ -426,12 +429,15 @@ + + reference="White_25" /> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index e91f4458ae..fb85e5278a 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -674,7 +674,26 @@ function="Inventory.DoToSelected" parameter="take_off" /> - + + + + + + + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 5377b0ab05..1351ad6e52 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2041,7 +2041,17 @@ Returns a string with the requested data about the region A new way to send items to the Marketplace Drag and drop items here to prepare them for sale on the Marketplace Drag items or folders that you wish to sell into this area. A copy of the item will appear, leaving your inventory unchanged, unless you have dragged a no-copy item. When you are ready to send the items to the Marketplace, click the Upload button. Once your items have been moved to your Marketplace Inventory, they will disappear from this folder. - + + No errors + Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge). + Error: This folder has no contents. + Error: This item failed to upload because your merchant account has too many items unassociated with products. To fix this error, login to the marketplace website and reduce your unassociated item count. + Error: This item contains too many objects. Fix this error by placing objects together in boxes to reduce the total count to less than 200. + Error: This item contains too many levels of nested folders. Reorganize it to a maximum of 3 levels of nested folders. + Error: This item can not be sold on the marketplace. + Error: There was a problem with this item. Try again later. + + diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_container.xml b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml index 86356ff563..85fc64c8b4 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml @@ -2,4 +2,7 @@ + max_auto_scroll_rate="500" + tab_stop="false" + name="scroll_container" + mouse_opaque="true" /> -- cgit v1.3 From f1c01becf27ab92a39c90d725c5bc70c73286e65 Mon Sep 17 00:00:00 2001 From: "leslie@leslie-HPz600.lindenlab.com" Date: Tue, 30 Aug 2011 16:18:34 -0700 Subject: EXP-857 PROGRESS -- Add context menu entries as alternate path to populate outbox * Folders containing items being worn now have the "Copy to Marketplace" context menu item disabled. --- indra/newview/llinventorybridge.cpp | 7 +++++ indra/newview/llinventoryfunctions.cpp | 52 ++++++++++++++++++++++++++++++++++ indra/newview/llinventoryfunctions.h | 3 ++ 3 files changed, 62 insertions(+) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index f3429607e9..fb5d145637 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1098,6 +1098,13 @@ BOOL LLInvFVBridge::canListOnMarketplaceNow() const return FALSE; } + // Loop through all items worn by avatar and check to see if they are descendants + // of the item we are trying to list on the marketplace + if (get_is_parent_to_worn_item(mUUID)) + { + return FALSE; + } + return TRUE; } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 8632e40c54..0af013fde5 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -211,6 +211,58 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s model->notifyObservers(); } +class LLInventoryCollectAllItems : public LLInventoryCollectFunctor +{ +public: + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + return true; + } +}; + +BOOL get_is_parent_to_worn_item(const LLUUID& id) +{ + const LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (!cat) + { + return FALSE; + } + + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLInventoryCollectAllItems collect_all; + gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH, collect_all); + + for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) + { + const LLViewerInventoryItem * const item = *it; + + llassert(item->getIsLinkType()); + + LLUUID linked_id = item->getLinkedUUID(); + const LLViewerInventoryItem * const linked_item = gInventory.getItem(linked_id); + + if (linked_item) + { + LLUUID parent_id = linked_item->getParentUUID(); + + while (!parent_id.isNull()) + { + LLInventoryCategory * parent_cat = gInventory.getCategory(parent_id); + + if (cat == parent_cat) + { + return TRUE; + } + + parent_id = parent_cat->getParentUUID(); + } + } + } + + return FALSE; +} + BOOL get_is_item_worn(const LLUUID& id) { const LLViewerInventoryItem* item = gInventory.getItem(id); diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 3e80fe322c..7b452537f8 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -37,6 +37,9 @@ ** MISCELLANEOUS GLOBAL FUNCTIONS **/ +// Is this a parent folder to a worn item +BOOL get_is_parent_to_worn_item(const LLUUID& id); + // Is this item or its baseitem is worn, attached, etc... BOOL get_is_item_worn(const LLUUID& id); -- cgit v1.3 From 4ad3676985fa6abbb764136f1ec658ddcf296058 Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Thu, 8 Sep 2011 12:09:43 -0700 Subject: Disable merchant outbox context menu --- indra/newview/llinventorybridge.cpp | 11 +++++++++++ indra/newview/llsidepanelinventory.cpp | 2 +- indra/newview/llviewermedia.cpp | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorybridge.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b4dac28595..a36aa3dedf 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -70,6 +70,9 @@ #include "llvoavatarself.h" #include "llwearablelist.h" +// Marketplace outbox current disabled +#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL + typedef std::pair two_uuids_t; typedef std::list two_uuids_list_t; @@ -1060,6 +1063,7 @@ BOOL LLInvFVBridge::canShare() const 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())) @@ -1089,10 +1093,14 @@ BOOL LLInvFVBridge::canListOnMarketplace() const } return TRUE; +#else + return FALSE; +#endif } BOOL LLInvFVBridge::canListOnMarketplaceNow() const { +#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU if (get_is_item_worn(mUUID)) { return FALSE; @@ -1106,6 +1114,9 @@ BOOL LLInvFVBridge::canListOnMarketplaceNow() const } return TRUE; +#else + return FALSE; +#endif } diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 858639215c..9814e5b81a 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -68,7 +68,7 @@ static LLRegisterPanelClassWrapper t_inventory("sidepanel_ #define AUTO_EXPAND_INBOX 0 // Temporarily disabling the outbox until we straighten out the API -#define ENABLE_MERCHANT_OUTBOX_PANEL 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX +#define ENABLE_MERCHANT_OUTBOX_PANEL 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU static const char * const INBOX_BUTTON_NAME = "inbox_btn"; static const char * const OUTBOX_BUTTON_NAME = "outbox_btn"; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 56ef31fb0b..13dbc5e386 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1368,7 +1368,7 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom // This is defined in two files but I don't want to create a dependence between this and llsidepanelinventory // just to be able to temporarily disable the outbox. -#define ENABLE_INVENTORY_DISPLAY_OUTBOX 0 // keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL +#define ENABLE_INVENTORY_DISPLAY_OUTBOX 0 // keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU class LLInventoryUserStatusResponder : public LLHTTPClient::Responder { -- cgit v1.3