[MAINT-2287] The rest of the updates so far to outbox.

This commit is contained in:
Inusaito Sayori
2014-02-06 14:53:13 -05:00
parent b6225d1d9a
commit eb4b0d630f
7 changed files with 156 additions and 31 deletions

View File

@@ -164,6 +164,17 @@ BOOL LLFloaterOutbox::postBuild()
return TRUE;
}
void LLFloaterOutbox::cleanOutbox()
{
// Note: we cannot delete the mOutboxInventoryPanel as that point
// as this is called through callback observers of the panel itself.
// Doing so would crash rapidly.
// Invalidate the outbox data
mOutboxId.setNull();
mOutboxItemCount = 0;
}
void LLFloaterOutbox::onClose(bool app_quitting)
{
/*
@@ -226,14 +237,26 @@ void LLFloaterOutbox::setupOutbox()
}
// We are a merchant. Get the outbox, create it if needs be.
mOutboxId = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true, false);
if (mOutboxId.isNull())
LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true);
if (outbox_id.isNull())
{
// We should never get there unles inventory fails badly
// We should never get there unless inventory fails badly
llerrs << "Inventory problem: failure to create the outbox for a merchant!" << llendl;
return;
}
// Consolidate Merchant Outbox
// We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, things get messy and conventions get broken down eventually
gInventory.consolidateForType(outbox_id, LLFolderType::FT_OUTBOX);
if (outbox_id == mOutboxId)
{
llwarns << "Inventory warning: Merchant outbox already set" << llendl;
return;
}
mOutboxId = outbox_id;
// No longer need to observe new category creation
if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
{
@@ -243,13 +266,15 @@ void LLFloaterOutbox::setupOutbox()
}
llassert(!mCategoryAddedObserver);
// Create observer for outbox modifications
if (mCategoriesObserver == NULL)
// Create observer for outbox modifications : clear the old one and create a new one
if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
gInventory.addObserver(mCategoriesObserver);
mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
gInventory.removeObserver(mCategoriesObserver);
delete mCategoriesObserver;
}
mCategoriesObserver = new LLInventoryCategoriesObserver();
gInventory.addObserver(mCategoriesObserver);
mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
llassert(mCategoriesObserver);
// Set up the outbox inventory view
@@ -273,13 +298,15 @@ void LLFloaterOutbox::initializeMarketPlace()
//
// Initialize the marketplace import API
//
LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2));
importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
importer.initialize();
if (!importer.isInitialized())
{
importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2));
importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
importer.initialize();
}
}
void LLFloaterOutbox::setStatusString(const std::string& statusString)
@@ -306,6 +333,11 @@ void LLFloaterOutbox::updateFolderCount()
mOutboxItemCount = item_count;
}
else
{
// If there's no outbox, the number of items in it should be set to 0 for consistency
mOutboxItemCount = 0;
}
if (!mImportBusy)
{
@@ -375,6 +407,11 @@ void LLFloaterOutbox::updateView()
if (mOutboxId.notNull())
{
// Does the outbox needs recreation?
if ((mOutboxInventoryPanel.get() == NULL) || !gInventory.getCategory(mOutboxId))
{
setupOutbox();
}
// "Outbox is empty!" message strings
outbox_text = LLTrans::getString("InventoryOutboxNoItems");
subs_link = "[MARKETPLACE_DASHBOARD_URL]";
@@ -441,7 +478,8 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
{
if ((mOutboxInventoryPanel.get() == NULL) ||
//(mWindowShade && mWindowShade->isShown()) ||
LLMarketplaceInventoryImporter::getInstance()->isImportInProgress())
LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() ||
mOutboxId.isNull())
{
return FALSE;
}
@@ -511,16 +549,16 @@ void LLFloaterOutbox::onImportButtonClicked()
void LLFloaterOutbox::onOutboxChanged()
{
llassert(!mOutboxId.isNull());
if (mOutboxInventoryPanel)
LLViewerInventoryCategory* category = gInventory.getCategory(mOutboxId);
if (mOutboxId.notNull() && category)
{
mOutboxInventoryPanel->requestSort();
fetchOutboxContents();
updateView();
}
else
{
cleanOutbox();
}
fetchOutboxContents();
updateView();
}
void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)

View File

@@ -72,6 +72,7 @@ public:
protected:
void setupOutbox();
void cleanOutbox();
void fetchOutboxContents();
void importReportResults(U32 status, const LLSD& content);

View File

@@ -405,6 +405,66 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
mItemLock[cat_id] = false;
}
void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::EType type)
{
// Make a list of folders that are not "main_id" and are of "type"
std::vector<LLUUID> folder_ids;
for (cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
{
LLViewerInventoryCategory* cat = cit->second;
if ((cat->getPreferredType() == type) && (cat->getUUID() != main_id))
{
folder_ids.push_back(cat->getUUID());
}
}
// Iterate through those folders
for (std::vector<LLUUID>::iterator folder_ids_it = folder_ids.begin(); folder_ids_it != folder_ids.end(); ++folder_ids_it)
{
LLUUID folder_id = (*folder_ids_it);
// Get the content of this folder
cat_array_t* cats;
item_array_t* items;
getDirectDescendentsOf(folder_id, cats, items);
// Move all items to the main folder
// Note : we get the list of UUIDs and iterate on them instead of iterating directly on item_array_t
// elements. This is because moving elements modify the maps and, consequently, invalidate iterators on them.
// This "gather and iterate" method is verbose but resilient.
std::vector<LLUUID> list_uuids;
for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it)
{
list_uuids.push_back((*it)->getUUID());
}
for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
{
LLViewerInventoryItem* item = getItem(*it);
changeItemParent(item, main_id, TRUE);
}
// Move all folders to the main folder
list_uuids.clear();
for (cat_array_t::const_iterator it = cats->begin(); it != cats->end(); ++it)
{
list_uuids.push_back((*it)->getUUID());
}
for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it)
{
LLViewerInventoryCategory* cat = getCategory(*it);
changeCategoryParent(cat, main_id, TRUE);
}
// Purge the emptied folder
// Note: we'd like to use purgeObject() but it doesn't cleanly eliminate the folder
// which leads to issues further down the road when the folder is found again
//purgeObject(folder_id);
// We remove the folder and empty the trash instead which seems to work
removeCategory(folder_id);
gInventory.emptyFolderType("", LLFolderType::FT_TRASH);
}
}
// findCategoryUUIDForType() returns the uuid of the category that
// specifies 'type' as what it defaults to containing. The category is
// not necessarily only for that type. *NOTE: This will create a new

View File

@@ -275,6 +275,11 @@ public:
LLViewerInventoryItem* getLinkedItem(const LLUUID& object_id) const;
LLUUID findCategoryByName(std::string name);
// Copy content of all folders of type "type" into folder "id" and delete/purge the empty folders
// Note : This method has been designed for FT_OUTBOX (aka Merchant Outbox) but can be used for other categories
void consolidateForType(const LLUUID& id, LLFolderType::EType type);
private:
mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups

View File

@@ -690,15 +690,24 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
if (!mCategoryMap.size())
return;
std::vector<LLUUID> deleted_categories_ids;
for (category_map_t::iterator iter = mCategoryMap.begin();
iter != mCategoryMap.end();
++iter)
{
const LLUUID& cat_id = (*iter).first;
LLCategoryData& cat_data = (*iter).second;
LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);
if (!category)
{
llwarns << "Category : Category id = " << cat_id << " disappeared" << llendl;
cat_data.mCallback();
// Keep track of those deleted categories so we can remove them
deleted_categories_ids.push_back(cat_id);
continue;
}
const S32 version = category->getVersion();
const S32 expected_num_descendents = category->getDescendentCount();
@@ -726,8 +735,6 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
const S32 current_num_known_descendents = cats->count() + items->count();
LLCategoryData& cat_data = (*iter).second;
bool cat_changed = false;
// If category version or descendents count has changed
@@ -757,6 +764,12 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
if (cat_changed)
cat_data.mCallback();
}
// Remove deleed categories from the list
for (std::vector<LLUUID>::iterator deleted_id = deleted_categories_ids.begin(); deleted_id != deleted_categories_ids.end(); ++deleted_id)
{
removeCategory(*deleted_id);
}
}
bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb)

View File

@@ -231,9 +231,11 @@ namespace LLMarketplaceImport
llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl;
}
// MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS
// MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS : Happens when trying to import objects with wrong permissions
// ACME-1221 : Do not clear the cookie on IMPORT_NOT_FOUND : Happens for newly created Merchant accounts that are initially empty
if ((status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) &&
(status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS))
(status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) &&
(status != MarketplaceErrorCodes::IMPORT_NOT_FOUND))
{
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
@@ -241,9 +243,9 @@ namespace LLMarketplaceImport
}
sMarketplaceCookie.clear();
}
else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS))
else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST))
{
llinfos << " SLM GET : Got IMPORT_DONE_WITH_ERRORS, marketplace cookie not cleared." << llendl;
llinfos << " SLM GET : Got error status = " << status << ", but marketplace cookie not cleared." << llendl;
}
sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
@@ -306,13 +308,15 @@ namespace LLMarketplaceImport
std::string url = getInventoryImportURL();
AIHTTPHeaders headers = LLViewerMedia::getHeaders();
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM GET: " << url << llendl;
llinfos << " SLM GET: establishMarketplaceSessionCookie, LLHTTPClient::get, url = " << url << llendl;
llinfos << " SLM GET: headers " << llendl;
llinfos << headers << llendl;
}
slmGetTimer.start();
AIHTTPHeaders headers = LLViewerMedia::getHeaders();
LLHTTPClient::get(url, new LLImportGetResponder(), headers);
return true;
@@ -453,7 +457,10 @@ boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallb
void LLMarketplaceInventoryImporter::initialize()
{
llassert(!mInitialized);
if (mInitialized)
{
return;
}
if (!LLMarketplaceImport::hasSessionCookie())
{

View File

@@ -92,6 +92,7 @@ public:
void initialize();
bool triggerImport();
bool isImportInProgress() const { return mImportInProgress; }
bool isInitialized() const { return mInitialized; }
U32 getMarketPlaceStatus() const { return mMarketPlaceStatus; }
protected: