summaryrefslogtreecommitdiff
path: root/indra/newview/llinventoryfunctions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llinventoryfunctions.cpp')
-rwxr-xr-xindra/newview/llinventoryfunctions.cpp573
1 files changed, 566 insertions, 7 deletions
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f1a4889f5a..10a5ac4bc7 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -59,6 +59,7 @@
#include "llinventorypanel.h"
#include "lllineeditor.h"
#include "llmarketplacenotifications.h"
+#include "llmarketplacefunctions.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
#include "llpanelmaininventory.h"
@@ -90,6 +91,14 @@
BOOL LLInventoryState::sWearNewClothing = FALSE;
LLUUID LLInventoryState::sWearNewClothingTransactionID;
+// Helper function : callback to update a folder after inventory action happened in the background
+void update_folder_cb(const LLUUID& dest_folder)
+{
+ LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder);
+ gInventory.updateCategory(dest_cat);
+ gInventory.notifyObservers();
+}
+
// Generates a string containing the path to the item specified by
// item_id.
void append_path(const LLUUID& id, std::string& path)
@@ -111,6 +120,80 @@ void append_path(const LLUUID& id, std::string& path)
path.append(temp);
}
+void update_marketplace_folder_hierarchy(const LLUUID cat_id)
+{
+ // When changing the marketplace status of a folder, the only thing that needs to happen is
+ // for all observers of the folder to, possibly, change the display label of the folder
+ // so that's the only thing we change on the update mask.
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, cat_id);
+ gInventory.notifyObservers();
+
+ // Update all descendent folders down
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
+
+ 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++)
+ {
+ LLInventoryCategory* category = *iter;
+ update_marketplace_folder_hierarchy(category->getUUID());
+ }
+ return;
+}
+
+void update_marketplace_category(const LLUUID& cat_id)
+{
+ // When changing the marketplace status of a folder, we usually have to change the status of all
+ // folders in the same listing. This is because the display of each folder is affected by the
+ // overall status of the whole listing.
+ // Consequently, the only way to correctly update a folder anywhere in the marketplace is to
+ // update the whole listing from its listing root.
+ // This is not as bad as it seems as we only update folders, not items, and the folder nesting depth
+ // is limited to 4.
+ // We also take care of degenerated cases so we don't update all folders in the inventory by mistake.
+
+ const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ // No marketplace -> likely called too early... or
+ // Not a descendent of the marketplace listings root -> likely called in error then...
+ if (marketplace_listings_uuid.isNull() || !gInventory.isObjectDescendentOf(cat_id, marketplace_listings_uuid))
+ {
+ // In those cases, just do the regular category update
+ LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+ gInventory.updateCategory(cat);
+ gInventory.notifyObservers();
+ return;
+ }
+
+ // Grab marketplace listing data for this folder
+ S32 depth = depth_nesting_in_marketplace(cat_id);
+ LLUUID listing_uuid = nested_parent_id(cat_id, depth);
+
+ // Verify marketplace data consistency for this listing
+ if (LLMarketplaceData::instance().isListed(listing_uuid))
+ {
+ LLUUID version_folder_uuid = LLMarketplaceData::instance().getVersionFolderID(listing_uuid);
+ if (version_folder_uuid.notNull() && !gInventory.isObjectDescendentOf(version_folder_uuid, listing_uuid))
+ {
+ // *TODO : Confirm with Producer that this is what we want to happen in that case!
+ llinfos << "Merov : Unlist as the version folder is not under the listing folder anymore!!" << llendl;
+ LLMarketplaceData::instance().setVersionFolderID(listing_uuid, LLUUID::null);
+ LLMarketplaceData::instance().setActivation(listing_uuid, false);
+ }
+ if (!gInventory.isObjectDescendentOf(listing_uuid, marketplace_listings_uuid))
+ {
+ // *TODO : Confirm with Producer that this is what we want to happen in that case!
+ llinfos << "Merov : Disassociate as the listing folder is not under the marketplace folder anymore!!" << llendl;
+ LLMarketplaceData::instance().deleteListing(listing_uuid);
+ }
+ }
+
+ // Update all descendents starting from the listing root
+ update_marketplace_folder_hierarchy(listing_uuid);
+
+ return;
+}
+
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
{
LLViewerInventoryCategory* cat;
@@ -153,13 +236,14 @@ void copy_inventory_category(LLInventoryModel* model,
for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
{
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(),
- LLPointer<LLInventoryCallback>(NULL));
+ cb);
}
// Copy all the folders
@@ -511,14 +595,17 @@ void open_outbox()
LLFloaterReg::showInstance("outbox");
}
-LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id)
+// Create a new folder in destFolderId with the same name as the item name and return the uuid of the new folder
+// Note: this is used locally in various situation where we need to wrap an item into a special folder
+LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId)
{
llassert(item);
llassert(destFolderId.notNull());
LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName());
gInventory.notifyObservers();
-
+
+ // *TODO : Create different notifications for the various cases
LLNotificationsUtil::add("OutboxFolderCreated");
return created_folder_id;
@@ -534,8 +621,7 @@ void move_to_outbox_cb_action(const LLSD& payload)
// when moving item directly into outbox create folder with that name
if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
{
- S32 operation_id = payload["operation_id"].asInteger();
- dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id);
+ dest_folder_id = create_folder_for_item(viitem, dest_folder_id);
}
LLUUID parent = viitem->getParentUUID();
@@ -606,7 +692,7 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL
// when moving item directly into outbox create folder with that name
if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
{
- dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
+ dest_folder = create_folder_for_item(inv_item, dest_folder);
}
copy_inventory_item(gAgent.getID(),
@@ -636,7 +722,7 @@ void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32
// when moving item directly into outbox create folder with that name
if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
{
- dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
+ dest_folder = create_folder_for_item(inv_item, dest_folder);
}
LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
@@ -677,6 +763,479 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold
}
///----------------------------------------------------------------------------
+// Marketplace functions
+//
+// Handles Copy and Move to or within the Marketplace listings folder.
+// Handles creation of stock folders, nesting of listings and version folders,
+// permission checking and listings validation.
+///----------------------------------------------------------------------------
+
+S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
+{
+ // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none
+ const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ if (marketplace_listings_uuid.isNull())
+ {
+ return -1;
+ }
+ // If not a descendent of the marketplace listings root, then the nesting depth is -1 by definition
+ if (!gInventory.isObjectDescendentOf(cur_uuid, marketplace_listings_uuid))
+ {
+ return -1;
+ }
+
+ // Iterate through the parents till we hit the marketplace listings root
+ // Note that the marketplace listings root itself will return 0
+ S32 depth = 0;
+ LLInventoryObject* cur_object = gInventory.getObject(cur_uuid);
+ while (cur_uuid != marketplace_listings_uuid)
+ {
+ depth++;
+ cur_uuid = cur_object->getParentUUID();
+ cur_object = gInventory.getCategory(cur_uuid);
+ }
+ return depth;
+}
+
+// Returns the UUID of the marketplace listing this object is in
+LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth)
+{
+ LLInventoryObject* cur_object = gInventory.getObject(cur_uuid);
+ cur_uuid = (depth < 1 ? LLUUID::null : cur_uuid);
+ while (depth > 1)
+ {
+ depth--;
+ cur_uuid = cur_object->getParentUUID();
+ cur_object = gInventory.getCategory(cur_uuid);
+ }
+ return cur_uuid;
+}
+
+S32 compute_stock_count(LLUUID cat_uuid)
+{
+ // Handle the case of the folder being a stock folder immediately
+ LLViewerInventoryCategory* cat = gInventory.getCategory(cat_uuid);
+ if (!cat)
+ {
+ // Not a category so no stock count to speak of
+ return -1;
+ }
+ if (cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)
+ {
+ // Note: stock folders are *not* supposed to have nested subfolders so we stop recursion here
+ // Note: we *always* give a stock count for stock folders, it's useful even if the listing is unassociated
+ return cat->getDescendentCount();
+ }
+
+ // Grab marketplace data for this folder
+ S32 depth = depth_nesting_in_marketplace(cat_uuid);
+ LLUUID listing_uuid = nested_parent_id(cat_uuid, depth);
+ if (!LLMarketplaceData::instance().isListed(listing_uuid))
+ {
+ // If not listed, the notion of stock is meaningless so it won't be computed for any level
+ return -1;
+ }
+
+ LLUUID version_folder_uuid = LLMarketplaceData::instance().getVersionFolderID(listing_uuid);
+ // Handle the case of the first 2 levels : listing and version folders
+ if (depth == 1)
+ {
+ if (version_folder_uuid.notNull())
+ {
+ // If there is a version folder, the stock value for the listing is the version folder stock
+ return compute_stock_count(version_folder_uuid);
+ }
+ else
+ {
+ // If there's no version folder associated, the notion of stock count has no meaning
+ return -1;
+ }
+ }
+ else if (depth == 2)
+ {
+ if (version_folder_uuid.notNull() && (version_folder_uuid != cat_uuid))
+ {
+ // If there is a version folder but we're not it, our stock count is meaningless
+ return -1;
+ }
+ }
+
+ // In all other cases, the stock count is the min of stock folders count found in the descendents
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array);
+
+ // "-1" denotes a folder that doesn't countain any stock folders in its descendents
+ S32 curr_count = -1;
+
+ // Note: marketplace listings have a maximum depth nesting of 4
+ 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++)
+ {
+ LLInventoryCategory* category = *iter;
+ S32 count = compute_stock_count(category->getUUID());
+ if ((curr_count == -1) || ((count != -1) && (count < curr_count)))
+ {
+ curr_count = count;
+ }
+ }
+
+ return curr_count;
+}
+
+void move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy)
+{
+ // Get the marketplace listings, exit with error if none
+ const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ if (marketplace_listings_uuid.isNull())
+ {
+ llinfos << "Merov : Marketplace error : There is no marketplace listings folder -> move aborted!" << llendl;
+ return;
+ }
+
+ // We will collapse links into items/folders
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+ LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
+
+ if (linked_category != NULL)
+ {
+ // Move the linked folder directly
+ move_folder_to_marketplacelistings(linked_category, dest_folder, copy);
+ }
+ else
+ {
+ // Grab the linked item if any
+ LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+ viewer_inv_item = (linked_item != NULL ? linked_item : viewer_inv_item);
+
+ // 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.
+ if (viewer_inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()))
+ {
+ // When moving an isolated item directly under the marketplace listings root, we create a new folder with that name
+ if (dest_folder == marketplace_listings_uuid)
+ {
+ dest_folder = create_folder_for_item(inv_item, dest_folder);
+ }
+ LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder);
+
+ // Verify we can have this item in that destination category
+ if (!dest_cat->acceptItem(viewer_inv_item))
+ {
+ llinfos << "Merov : Marketplace error : Cannot move item in that stock folder -> move aborted!" << llendl;
+ return;
+ }
+
+ // When moving a no copy item into a first level listing folder, we create a stock folder for it
+ if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && (dest_cat->getParentUUID() == marketplace_listings_uuid))
+ {
+ dest_folder = create_folder_for_item(inv_item, dest_folder);
+ }
+
+ // Get the parent folder of the moved item : we may have to update it
+ LLUUID src_folder = viewer_inv_item->getParentUUID();
+
+ if (copy)
+ {
+ // Copy the item
+ LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder));
+ copy_inventory_item(
+ gAgent.getID(),
+ viewer_inv_item->getPermissions().getOwner(),
+ viewer_inv_item->getUUID(),
+ dest_folder,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ // Reparent the item
+ gInventory.changeItemParent(viewer_inv_item, dest_folder, false);
+ }
+
+ // Validate the destination : note that this will run the validation code only on one listing folder at most...
+ validate_marketplacelistings(dest_cat);
+
+ // Update the modified folders
+ update_marketplace_category(src_folder);
+ update_marketplace_category(dest_folder);
+ }
+ else
+ {
+ // *TODO : signal an error to the user (UI for this TBD)
+ llinfos << "Merov : Marketplace error : User doesn't have the correct permission to put this item on sale -> move aborted!" << llendl;
+ }
+ }
+}
+
+void move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy)
+{
+ // Check that we have adequate permission on all items being moved. Proceed if we do.
+ if (has_correct_permissions_for_sale(inv_cat))
+ {
+ // Get the destination folder
+ LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder);
+
+ // Check it's not a stock folder
+ if (dest_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)
+ {
+ llinfos << "Merov : Marketplace error : Cannot move folder in stock folder -> move aborted!" << llendl;
+ return;
+ }
+
+ // Get the parent folder of the moved item : we may have to update it
+ LLUUID src_folder = inv_cat->getParentUUID();
+
+ LLViewerInventoryCategory * viewer_inv_cat = (LLViewerInventoryCategory *) inv_cat;
+ if (copy)
+ {
+ // Copy the folder
+ copy_inventory_category(&gInventory, viewer_inv_cat, dest_folder);
+ }
+ else
+ {
+ // Reparent the folder
+ gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false);
+ }
+
+ // Check the destination folder recursively for no copy items and promote the including folders if any
+ validate_marketplacelistings(dest_cat);
+
+ // Update the modified folders
+ update_marketplace_category(src_folder);
+ update_marketplace_category(dest_folder);
+ }
+}
+
+// Returns true if all items within the argument folder are fit for sale, false otherwise
+bool has_correct_permissions_for_sale(LLInventoryCategory* cat)
+{
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
+
+ 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;
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item;
+ LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
+ LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+ // Linked items and folders cannot be put for sale
+ if (linked_category || linked_item)
+ {
+ llinfos << "Merov : linked items in this folder -> not allowed to sell!" << llendl;
+ 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.
+ if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()))
+ {
+ llinfos << "Merov : wrong permissions on items in this folder -> not allowed to sell!" << llendl;
+ return false;
+ }
+ }
+
+ 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++)
+ {
+ LLInventoryCategory* category = *iter;
+ if (!has_correct_permissions_for_sale(category))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Make all relevant business logic checks on the marketplace listings starting with the folder as argument
+// This function does no deletion of listings but a mere audit and raises issues to the user
+// The only thing that's done is to move and sort folders containing no-copy items to stock folders
+// *TODO : Add the rest of the SLM/AIS business logic (limit of nesting depth, stock folder consistency, overall limit on listings, etc...)
+void validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_t cb)
+{
+ // Special case a stock folder depth issue
+ LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat);
+ const LLFolderType::EType folder_type = cat->getPreferredType();
+ S32 depth = depth_nesting_in_marketplace(cat->getUUID());
+ if (depth == 1)
+ {
+ std::string message = "Validating listing : " + cat->getName();
+ llinfos << "Merov : Validation log : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ }
+ if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth <= 2))
+ {
+ // Nest the stock folder one level deeper in a normal folder and restart from there
+ //LLUUID parent_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ LLUUID parent_uuid = cat->getParentUUID();
+ LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName());
+ std::string message = " Warning : creating wrapping folder for stock folder : " + cat->getName();
+ llinfos << "Merov : Validation warning : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid);
+ gInventory.changeCategoryParent(viewer_cat, folder_uuid, false);
+ validate_marketplacelistings(new_cat, cb);
+ return;
+ }
+
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
+
+ // Stock items : sorting and moving the various stock items is complicated as the set of constraints is high
+ // For each folder, we need to:
+ // * separate non stock items, stock items per types in different folders
+ // * have stock items nested at depth 2 at least
+ // * never ever move the non-stock items
+
+ std::vector<std::vector<LLViewerInventoryItem*> > items_vector;
+ items_vector.resize(LLInventoryType::IT_COUNT+1);
+
+ // Parse the items and create vectors of items to sort copyable items and stock items of various types
+ 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;
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item;
+ LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
+ LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+ // Skip items that shouldn't be there to start with, raise an error message for those
+ if (linked_category || linked_item)
+ {
+ std::string message = " Error : linked item are not allowed in listings : " + viewer_inv_item->getName();
+ llinfos << "Merov : Validation error : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ continue;
+ }
+ if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()))
+ {
+ std::string message = " Error : item with incorrect permissions in listing : " + viewer_inv_item->getName();
+ llinfos << "Merov : Validation error : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ continue;
+ }
+ // Update the appropriate vector item for that type
+ LLInventoryType::EType type = LLInventoryType::IT_COUNT; // Default value for non stock items
+ if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+ {
+ // Get the item type for stock items
+ type = viewer_inv_item->getInventoryType();
+ }
+ items_vector[type].push_back(viewer_inv_item);
+ }
+ // How many types of folders? Which type is it if only one?
+ S32 count = 0;
+ LLInventoryType::EType type = LLInventoryType::IT_COUNT;
+ for (S32 i = 0; i <= LLInventoryType::IT_COUNT; i++)
+ {
+ if (!items_vector[i].empty())
+ {
+ count++;
+ type = (LLInventoryType::EType)(i);
+ }
+ }
+ // If we have no items in there (only folders) -> all OK
+ if (count == 0)
+ {
+ std::string message = " Log : folder validates: doesn't contain any item";
+ llinfos << "Merov : Validation log : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ }
+ // If we have one kind only, in the correct folder type at the right depth -> all OK
+ else if ((count == 1) && (((type == LLInventoryType::IT_COUNT) && (depth > 1)) || ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2))))
+ {
+ // Done with that folder!
+ std::string message = " Log : folder validates: all items of compatible types";
+ llinfos << "Merov : Validation log : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ }
+ else
+ {
+ // Create one folder per vector at the right depth and of the right type
+ for (S32 i = 0; i <= LLInventoryType::IT_COUNT; i++)
+ {
+ if (!items_vector[i].empty())
+ {
+ // Create a new folder
+ std::string message = " Warning : creating stock folder : " + viewer_cat->getName();
+ llinfos << "Merov : Validation warning : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID());
+ LLFolderType::EType new_folder_type = (i == LLInventoryType::IT_COUNT ? LLFolderType::FT_NONE : LLFolderType::FT_MARKETPLACE_STOCK);
+ LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, new_folder_type, viewer_cat->getName());
+ // Move each item to the new folder
+ while (!items_vector[i].empty())
+ {
+ LLViewerInventoryItem* viewer_inv_item = items_vector[i].back();
+ std::string message = " Warning : moving item : " + viewer_inv_item->getName();
+ llinfos << "Merov : Validation warning : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ gInventory.changeItemParent(viewer_inv_item, folder_uuid, false);
+ items_vector[i].pop_back();
+ }
+ update_marketplace_category(folder_uuid);
+ }
+ }
+ // Clean up
+ if (viewer_cat->getDescendentCount() == 0)
+ {
+ // Remove the current folder if it ends up empty
+ llinfos << "Merov : Validation warning : " << llendl;
+ std::string message = " Warning : folder content completely moved to stock folder -> removing empty folder";
+ llinfos << "Merov : Validation warning : " << message << llendl;
+ if (cb)
+ {
+ cb(message);
+ }
+ gInventory.removeCategory(cat->getUUID());
+ gInventory.notifyObservers();
+ return;
+ }
+ else
+ {
+ // Update the current folder
+ update_marketplace_category(cat->getUUID());
+ }
+ }
+
+ // Recursion : Perform the same validation on each nested folder
+ 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++)
+ {
+ LLInventoryCategory* category = *iter;
+ validate_marketplacelistings(category, cb);
+ }
+}
+
+///----------------------------------------------------------------------------
/// LLInventoryCollectFunctor implementations
///----------------------------------------------------------------------------