DD-24 : Add FT_MARKETPLACE_STOCK as a new type for folders, implement the promotion code for Drag and Drop, display of stock folders and embryonic marketplace validation

master
Merov Linden 2014-03-28 15:54:36 -07:00
parent 2f1bef16dc
commit 0ec8fbec6d
9 changed files with 210 additions and 12 deletions

View File

@ -98,6 +98,7 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE));
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
};

View File

@ -88,6 +88,7 @@ public:
FT_BASIC_ROOT = 52,
FT_MARKETPLACE_LISTINGS = 53,
FT_MARKETPLACE_STOCK = 54,
FT_COUNT,

View File

@ -1958,7 +1958,7 @@ std::string LLFolderBridge::getLabelSuffix() const
{
if (LLMarketplaceData::instance().isListed(getUUID()))
{
llinfos << "Merov : in merchant folder and listed : id = " << getUUID() << llendl;
//llinfos << "Merov : in merchant folder and listed : id = " << getUUID() << llendl;
std::string suffix = LLMarketplaceData::instance().getListingID(getUUID());
if (suffix.empty())
{
@ -1971,9 +1971,15 @@ std::string LLFolderBridge::getLabelSuffix() const
}
return LLInvFVBridge::getLabelSuffix() + suffix;
}
else if (getCategory()->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)
{
//llinfos << "Merov : in merchant folder and is a stock folder : id = " << getUUID() << llendl;
std::string suffix = " (" + LLTrans::getString("MarketplaceStock") + ")";
return LLInvFVBridge::getLabelSuffix() + suffix;
}
else
{
llinfos << "Merov : in merchant folder but not listed : id = " << getUUID() << llendl;
//llinfos << "Merov : in merchant folder but not listed : id = " << getUUID() << llendl;
return LLInvFVBridge::getLabelSuffix();
}
}
@ -2316,10 +2322,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const LLUUID &cat_id = inv_cat->getUUID();
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id);
// check to make sure source is agent inventory, and is represented there.
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
@ -2499,6 +2508,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
if (is_movable && move_is_into_marketplacelistings)
{
// *TODO : Merov : Add here the logic to prevent huge nesting in marketplace listings
// For the moment, we just take in anything
is_movable = TRUE;
}
if (is_movable)
{
@ -2601,6 +2616,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
{
copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId());
}
else if (move_is_into_marketplacelistings && !move_is_from_marketplacelistings)
{
move_folder_to_marketplacelistings(inv_cat, mUUID);
}
else
{
if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))
@ -2620,7 +2639,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else if (LLToolDragAndDrop::SOURCE_WORLD == source)
{
if (move_is_into_outbox)
if (move_is_into_outbox || move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@ -2632,7 +2651,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
{
if (move_is_into_outbox)
if (move_is_into_outbox || move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@ -3248,6 +3267,9 @@ void LLFolderBridge::pasteFromClipboard()
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
// *TODO : Add marketplace listings case
//const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
//const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
LLDynamicArray<LLUUID> objects;
LLClipboard::instance().pasteFromClipboard(objects);
@ -3372,12 +3394,14 @@ void LLFolderBridge::pasteLinkFromClipboard()
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
if (move_is_into_outbox)
if (move_is_into_outbox || move_is_into_marketplacelistings)
{
// Notify user of failure somehow -- play error sound? modal dialog?
return;
@ -4047,6 +4071,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_favorites = (mUUID == favorites_id);
@ -4054,6 +4079,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
BOOL accept = FALSE;
@ -4150,6 +4176,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
}
}
else if (move_is_into_marketplacelistings)
{
// *TODO : Add here any logic that may prevent an item to be copied into the marketplace listings
// For the moment, we let anything go
accept = TRUE;
}
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
@ -4208,6 +4240,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
dropToOutfit(inv_item, move_is_into_current_outfit);
}
// MERCHANT OUTBOX folder
// Move the item
else if (move_is_into_outbox)
{
if (move_is_from_outbox)
@ -4219,6 +4253,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId());
}
}
// MARKETPLACE LISTINGS folder
// Move the item
else if (move_is_into_marketplacelistings)
{
move_item_to_marketplacelistings(inv_item, mUUID);
}
// NORMAL or TRASH folder
// (move the item, restamp if into trash)
else
@ -4285,7 +4325,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = FALSE;
}
else if (move_is_into_outbox)
else if (move_is_into_outbox || move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@ -4323,7 +4363,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
if (move_is_into_outbox)
if (move_is_into_outbox || move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@ -4357,7 +4397,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = TRUE;
if (move_is_into_outbox)
if (move_is_into_outbox || move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;

View File

@ -686,6 +686,155 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold
open_outbox();
}
void move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder)
{
// 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);
}
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 copy permission on the item: this is required as a resident cannot
// put on sale items she has no right about. Proceed with move if we have permission.
// *TODO : Check that this is adequate (copied from the Merchant Outbox permission check so should be OK...)
if (viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, 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 == gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false))
{
// *TODO : This method is not specific to the outbox folder so make it more generic
dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, 0);
}
// Reparent the item
gInventory.changeItemParent(viewer_inv_item, dest_folder, false);
// Check the item for no copy permission and promote the destination folder if necessary
if (!(viewer_inv_item->getPermissions().getMaskEveryone() & PERM_COPY))
{
llinfos << "Merov : item is no copy -> change the destination folder type!" << llendl;
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (gInventory.getCategory(dest_folder));
viewer_cat->changeType(LLFolderType::FT_MARKETPLACE_STOCK);
}
}
else
{
// *TODO : signal an error to the user (UI for this TBD)
llinfos << "Merov : 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)
{
// Check that we have adequate permission on all items being moved. Proceed if we do.
if (has_correct_permissions_for_sale(inv_cat))
{
// Reparent the folder
LLViewerInventoryCategory * viewer_inv_cat = (LLViewerInventoryCategory *) inv_cat;
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(inv_cat);
}
}
// 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;
}
// *TODO : Check that this is adequate (copied from the Merchant Outbox permission check so should be OK...)
if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, 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 or move but a mere audit and raises issues to the user
// The only thing that's done is to modify the type of folders containing no-copy items to stock folders
// *TODO : Signal the errors to the user somewhat (UI still TBD)
// *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)
{
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();
if (linked_category || linked_item)
{
llinfos << "Merov : Validation error: there are linked items in this listing!" << llendl;
}
if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
{
llinfos << "Merov : Validation error: there are items with incorrect permissions in this listing!" << llendl;
}
if (!(viewer_inv_item->getPermissions().getMaskEveryone() & PERM_COPY))
{
llinfos << "Merov : Validation warning : item is no copy -> change the folder type to stock!" << llendl;
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat);
viewer_cat->changeType(LLFolderType::FT_MARKETPLACE_STOCK);
}
}
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);
}
}
///----------------------------------------------------------------------------
/// LLInventoryCollectFunctor implementations
///----------------------------------------------------------------------------

View File

@ -70,9 +70,13 @@ void append_path(const LLUUID& id, std::string& path);
void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id);
void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id);
void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id);
void move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder);
void move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder);
bool has_correct_permissions_for_sale(LLInventoryCategory* cat);
void validate_marketplacelistings(LLInventoryCategory* inv_cat);
/** Miscellaneous global functions
** **
*******************************************************************************/

View File

@ -2160,12 +2160,12 @@ void LLInventoryModel::buildParentChildMap()
// implement it, we would need a set or map of uuid pairs
// which would be (folder_id, new_parent_id) to be sent up
// to the server.
llinfos << "Lost categroy: " << cat->getUUID() << " - "
llinfos << "Lost category: " << cat->getUUID() << " - "
<< cat->getName() << llendl;
++lost;
// plop it into the lost & found.
LLFolderType::EType pref = cat->getPreferredType();
if(LLFolderType::FT_NONE == pref)
if ((LLFolderType::FT_NONE == pref) || (LLFolderType::FT_MARKETPLACE_STOCK == pref))
{
cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
}

View File

@ -1491,5 +1491,6 @@ namespace LLInitParam
declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX) , LLFolderType::FT_OUTBOX);
declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT) , LLFolderType::FT_BASIC_ROOT);
declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_LISTINGS) , LLFolderType::FT_MARKETPLACE_LISTINGS);
declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_STOCK), LLFolderType::FT_MARKETPLACE_STOCK);
}
}

View File

@ -142,7 +142,8 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new ViewerFolderEntry("Marketplace listings", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new ViewerFolderEntry("New Stock", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false, "default"));
addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false, "default"));
#if SUPPORT_ENSEMBLES

View File

@ -2273,6 +2273,7 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors.
<string name="MarketplaceNoID">no Mkt ID</string>
<string name="MarketplaceActive">live</string>
<string name="MarketplaceStock">stock</string>
<string name="Open landmarks">Open landmarks</string>