From f1c9536401016052bbee84c6ff178fa0d466bc78 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 27 Jan 2015 23:19:51 -0800
Subject: [PATCH] DD-296 : Add options to move or leave behind no copy items
 when copying a folder to the marketplace

---
 indra/newview/llinventorybridge.cpp           |  7 ++-
 indra/newview/llinventoryfunctions.cpp        | 60 +++++++++++++++----
 indra/newview/llinventoryfunctions.h          |  5 +-
 .../skins/default/xui/en/notifications.xml    |  9 +--
 4 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 61889d3c5ec..f5f494c7896 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1636,11 +1636,12 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
 		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 		copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());
 	}
-	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action))
+	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))
 	{
 		LLInventoryItem* itemp = model->getItem(mUUID);
 		if (!itemp) return;
         const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+        // Note: For a single item, if it's not a copy, then it's a move
         move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action));
     }
 	else if ("copy_slurl" == action)
@@ -3185,12 +3186,12 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 		copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());
 	}
-	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action))
+	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))
 	{
 		LLInventoryCategory * cat = gInventory.getCategory(mUUID);
 		if (!cat) return;
         const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
-        move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("copy_to_marketplace_listings" == action));
+        move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action)));
     }
 }
 
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 40eeb01d544..97d6bf004ba 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -346,7 +346,8 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
 void copy_inventory_category(LLInventoryModel* model,
 							 LLViewerInventoryCategory* cat,
 							 const LLUUID& parent_id,
-							 const LLUUID& root_copy_id)
+							 const LLUUID& root_copy_id,
+                             bool move_no_copy_items )
 {
 	// Create the initial folder
 	LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName());
@@ -366,13 +367,27 @@ void copy_inventory_category(LLInventoryModel* model,
 	{
 		LLInventoryItem* item = *iter;
         LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, new_cat_uuid));
-		copy_inventory_item(
-							gAgent.getID(),
-							item->getPermissions().getOwner(),
-							item->getUUID(),
-							new_cat_uuid,
-							std::string(),
-							cb);
+
+        if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+        {
+            // If the item is nocopy, we do nothing or, optionally, move it
+            if (move_no_copy_items)
+            {
+                // Reparent the item
+                LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item;
+                gInventory.changeItemParent(viewer_inv_item, new_cat_uuid, true);
+            }
+        }
+        else
+        {
+            copy_inventory_item(
+                                gAgent.getID(),
+                                item->getPermissions().getOwner(),
+                                item->getUUID(),
+                                new_cat_uuid,
+                                std::string(),
+                                cb);
+        }
 	}
 	
 	// Copy all the folders
@@ -382,7 +397,7 @@ void copy_inventory_category(LLInventoryModel* model,
 		LLViewerInventoryCategory* category = *iter;
 		if (category->getUUID() != root_id)
 		{
-			copy_inventory_category(model, category, new_cat_uuid, root_id);
+			copy_inventory_category(model, category, new_cat_uuid, root_id, move_no_copy_items);
 		}
 	}
 }
@@ -1351,6 +1366,12 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
 		LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
         viewer_inv_item = (linked_item != NULL ? linked_item : viewer_inv_item);
     
+        // If we want to copy but the item is no copy, fail silently (this is a common case that doesn't warrant notification)
+        if (copy && !viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+        {
+            return false;
+        }
+        
         // Check that the agent has transfer permission on the item: this is required as a resident cannot
         // put on sale items she cannot transfer. Proceed with move if we have permission.
         std::string error_msg;
@@ -1373,7 +1394,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
             if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) &&
                 (dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK))
             {
-                // We need a stock folder
+                // We need to create a stock folder to move a no copy item
                 dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName());
                 dest_cat = gInventory.getCategory(dest_folder);
                 depth++;
@@ -1425,7 +1446,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
     return true;
 }
 
-bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy)
+bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy, bool move_no_copy_items)
 {
     // Check that we have adequate permission on all items being moved. Proceed if we do.
     std::string error_msg;
@@ -1450,7 +1471,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
         if (copy)
         {
             // Copy the folder
-            copy_inventory_category(&gInventory, viewer_inv_cat, dest_folder);
+            copy_inventory_category(&gInventory, viewer_inv_cat, dest_folder, LLUUID::null, move_no_copy_items);
         }
         else
         {
@@ -2211,6 +2232,19 @@ void LLInventoryAction::callback_doToSelected(const LLSD& notification, const LL
     }
 }
 
+void LLInventoryAction::callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+    if (option == 0) // YES, Move no copy item(s)
+    {
+        doToSelected(model, root, "copy_or_move_to_marketplace_listings", FALSE);
+    }
+    else if (option == 1) // NO, Don't move no copy item(s) (leave them behind)
+    {
+        doToSelected(model, root, "copy_to_marketplace_listings", FALSE);
+    }
+}
+
 void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action, BOOL user_confirm)
 {
 	std::set<LLFolderViewItem*> selected_items = root->getSelectionList();
@@ -2269,7 +2303,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
         LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem());
         if (contains_nocopy_items(viewModel->getUUID()))
         {
-            LLNotificationsUtil::add("ConfirmCopyToMarketplace", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, model, root, action));
+            LLNotificationsUtil::add("ConfirmCopyToMarketplace", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_copySelected, _1, _2, model, root, action));
             return;
         }
     }
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index c7384877f4c..86124e1dad9 100755
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -65,7 +65,7 @@ void update_all_marketplace_count();
 
 void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
 
-void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null);
+void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null, bool move_no_copy_items = false);
 
 // Generates a string containing the path to the item specified by item_id.
 void append_path(const LLUUID& id, std::string& path);
@@ -79,7 +79,7 @@ typedef boost::function<void(std::string& validation_message, S32 depth, LLError
 bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);
 bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false);
 bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false);
-bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false);
+bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false);
 bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1);
 S32  depth_nesting_in_marketplace(LLUUID cur_uuid);
 LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
@@ -454,6 +454,7 @@ struct LLInventoryAction
 {
 	static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action, BOOL user_confirm = TRUE);
     static void callback_doToSelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
+    static void callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
 
 	static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root);
     static void removeItemFromDND(LLFolderView* root);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 89aa69cfb42..4c6a61adfd3 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -399,13 +399,14 @@ Initialization with the Marketplace failed because of a system or network error.
         icon="alertmodal.tga"
         name="ConfirmCopyToMarketplace"
         type="alertmodal">
-        No copy items contained in that selection will not be copied to the Marketplace. Do you want to continue?
+        You don't have permission to copy one or more of these items to the Marketplace. You can move them or leave them behind.
         <tag>confirm</tag>
         <usetemplate
         ignoretext="Confirm before I try to copy a selection containing no copy items to the marketplace"
-        name="okcancelignore"
-        notext="Cancel"
-        yestext="OK"/>
+        name="yesnocancelbuttons"
+        yestext="Move item(s)"
+        notext="Don't move item(s)"
+        canceltext="Cancel"/>
     </notification>
     
     <notification
-- 
GitLab