diff options
author | Merov Linden <merov@lindenlab.com> | 2014-03-04 14:28:34 -0800 |
---|---|---|
committer | Merov Linden <merov@lindenlab.com> | 2014-03-04 14:28:34 -0800 |
commit | c7e2f81bbf299cf884d9e687fc4a7e7f7096c877 (patch) | |
tree | 1436dbf2dfac1deecee4a2ded9a891b7bf68bfb5 /indra/newview | |
parent | de8fea13627cc5978b8a6135802a52864a11c39a (diff) | |
parent | d2b604c61181a03bb16f2b951b6f86c582860759 (diff) |
Pull merge from viewer-maint-2287 aka Merchant Outbox
Diffstat (limited to 'indra/newview')
20 files changed, 532 insertions, 255 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4c7b192ae5..e6bcb04cb9 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4655,6 +4655,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>InventoryOutboxMakeVisible</key> + <map> + <key>Comment</key> + <string>Enable making the Merchant Outbox and Inbox visible in the inventory for debug purposes.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>InventoryOutboxMaxFolderCount</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl index c98e7d1cd3..bc63d07d72 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl @@ -33,8 +33,8 @@ mat4 getSkinnedTransform() mat4 ret; int i = int(floor(weight.x)); float x = fract(weight.x); - - ret[0] = mix(matrixPalette[i+0], matrixPalette[i+1], x); + + ret[0] = mix(matrixPalette[i+0], matrixPalette[i+1], x); ret[1] = mix(matrixPalette[i+15],matrixPalette[i+16], x); ret[2] = mix(matrixPalette[i+30],matrixPalette[i+31], x); ret[3] = vec4(0,0,0,1); diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 70cc48f12b..307e72fe18 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -868,6 +868,10 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL // check selection in the panel LLFolderView* root_folder = inv_panel->getRootFolder(); + if (!root_folder) + { + return false; + } const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); if (inventory_selected.empty()) return false; // nothing selected diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 29a3e6ac3a..de96f75602 100755 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -95,7 +95,7 @@ public: if (added_category_type == LLFolderType::FT_OUTBOX) { - mOutboxFloater->setupOutbox(added_category->getUUID()); + mOutboxFloater->initializeMarketPlace(); } } } @@ -120,7 +120,6 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key) , mInventoryText(NULL) , mInventoryTitle(NULL) , mOutboxId(LLUUID::null) - , mOutboxInventoryPanel(NULL) , mOutboxItemCount(0) , mOutboxTopLevelDropZone(NULL) , mWindowShade(NULL) @@ -157,9 +156,24 @@ BOOL LLFloaterOutbox::postBuild() LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this)); + // Observe category creation to catch outbox creation (moot if already existing) + mCategoryAddedObserver = new LLOutboxAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + 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) { if (mWindowShade) @@ -173,33 +187,25 @@ void LLFloaterOutbox::onClose(bool app_quitting) void LLFloaterOutbox::onOpen(const LLSD& key) { // - // Look for an outbox and set up the inventory API + // Initialize the Market Place or go update the outbox // - - if (mOutboxId.isNull()) + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) { - const bool do_not_create_folder = false; - - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder); - - if (outbox_id.isNull()) - { - // Observe category creation to catch outbox creation - mCategoryAddedObserver = new LLOutboxAddedObserver(this); - gInventory.addObserver(mCategoryAddedObserver); - } - else - { - setupOutbox(outbox_id); - } + initializeMarketPlace(); + } + else + { + setupOutbox(); } + // + // Update the floater view + // updateView(); // // Trigger fetch of outbox contents // - fetchOutboxContents(); } @@ -216,14 +222,34 @@ void LLFloaterOutbox::fetchOutboxContents() } } -void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) +void LLFloaterOutbox::setupOutbox() { - llassert(outboxId.notNull()); - llassert(mOutboxId.isNull()); - llassert(mCategoriesObserver == NULL); - - mOutboxId = outboxId; - + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) + { + // If we are *not* a merchant or we have no market place connection established yet, do nothing + return; + } + + // We are a merchant. Get the outbox, create it if needs be. + LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true); + if (outbox_id.isNull()) + { + // We should never get there unless the 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)) { @@ -231,45 +257,55 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) delete mCategoryAddedObserver; mCategoryAddedObserver = NULL; } + llassert(!mCategoryAddedObserver); - // Create observer for outbox modifications - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); - - mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); + // Create observer for outbox modifications : clear the old one and create a new one + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + 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 - // - - mOutboxInventoryPanel = - LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", - mInventoryPlaceholder->getParent(), - LLInventoryPanel::child_registry_t::instance()); - - llassert(mOutboxInventoryPanel); + LLInventoryPanel* inventory_panel = mOutboxInventoryPanel.get(); + if (inventory_panel) + { + delete inventory_panel; + } + inventory_panel = LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", mInventoryPlaceholder->getParent(), LLInventoryPanel::child_registry_t::instance()); + mOutboxInventoryPanel = inventory_panel->getInventoryPanelHandle(); + llassert(mOutboxInventoryPanel.get() != NULL); // Reshape the inventory to the proper size LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); - mOutboxInventoryPanel->setShape(inventory_placeholder_rect); + inventory_panel->setShape(inventory_placeholder_rect); // Set the sort order newest to oldest - - mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); - mOutboxInventoryPanel->getFilter().markDefault(); - + inventory_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + inventory_panel->getFilter().markDefault(); + + // Get the content of the outbox fetchOutboxContents(); - +} + +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) @@ -281,18 +317,26 @@ void LLFloaterOutbox::setStatusString(const std::string& statusString) void LLFloaterOutbox::updateFolderCount() { - S32 item_count = 0; - - if (mOutboxId.notNull()) + if (mOutboxInventoryPanel.get() && mOutboxId.notNull()) { - LLInventoryModel::cat_array_t * cats; - LLInventoryModel::item_array_t * items; - gInventory.getDirectDescendentsOf(mOutboxId, cats, items); + S32 item_count = 0; - item_count = cats->count() + items->count(); - } + if (mOutboxId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mOutboxId, cats, items); + + item_count = cats->count() + items->count(); + } - mOutboxItemCount = item_count; + 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) { @@ -302,7 +346,7 @@ void LLFloaterOutbox::updateFolderCount() void LLFloaterOutbox::updateFolderCountStatus() { - if (mOutboxInventoryPanel) + if (mOutboxInventoryPanel.get() && mOutboxId.notNull()) { switch (mOutboxItemCount) { @@ -327,18 +371,23 @@ void LLFloaterOutbox::updateFolderCountStatus() void LLFloaterOutbox::updateView() { updateFolderCount(); + LLInventoryPanel* panel = mOutboxInventoryPanel.get(); if (mOutboxItemCount > 0) { - mOutboxInventoryPanel->setVisible(TRUE); + panel->setVisible(TRUE); mInventoryPlaceholder->setVisible(FALSE); + mOutboxTopLevelDropZone->setVisible(TRUE); } else { - if (mOutboxInventoryPanel) + if (panel) { - mOutboxInventoryPanel->setVisible(FALSE); + panel->setVisible(FALSE); } + + // Show the drop zone if there is an outbox folder + mOutboxTopLevelDropZone->setVisible(mOutboxId.notNull()); mInventoryPlaceholder->setVisible(TRUE); @@ -347,19 +396,41 @@ void LLFloaterOutbox::updateView() std::string outbox_tooltip; const LLSD& subs = getMarketplaceStringSubstitutions(); + U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus(); 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); outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); } - else + else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) + { + // "Initializing!" message strings + outbox_text = LLTrans::getString("InventoryOutboxInitializing", subs); + outbox_title = LLTrans::getString("InventoryOutboxInitializingTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); + } + else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) { + // "Not a merchant!" message strings outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", subs); outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); } + else + { + // "Errors!" message strings + outbox_text = LLTrans::getString("InventoryOutboxError", subs); + outbox_title = LLTrans::getString("InventoryOutboxErrorTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + } mInventoryText->setValue(outbox_text); mInventoryTitle->setValue(outbox_title); @@ -378,9 +449,10 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - if ((mOutboxInventoryPanel == NULL) || + if ((mOutboxInventoryPanel.get() == NULL) || (mWindowShade && mWindowShade->isShown()) || - LLMarketplaceInventoryImporter::getInstance()->isImportInProgress()) + LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() || + mOutboxId.isNull()) { return FALSE; } @@ -391,15 +463,16 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // Determine if the mouse is inside the inventory panel itself or just within the floater bool pointInInventoryPanel = false; bool pointInInventoryPanelChild = false; - LLFolderView* root_folder = mOutboxInventoryPanel->getRootFolder(); - if (mOutboxInventoryPanel->getVisible()) + LLInventoryPanel* panel = mOutboxInventoryPanel.get(); + LLFolderView* root_folder = panel->getRootFolder(); + if (panel->getVisible()) { S32 inv_x, inv_y; - localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel); + localPointToOtherView(x, y, &inv_x, &inv_y, panel); - pointInInventoryPanel = mOutboxInventoryPanel->getRect().pointInRect(inv_x, inv_y); + pointInInventoryPanel = panel->getRect().pointInRect(inv_x, inv_y); - LLView * inventory_panel_child_at_point = mOutboxInventoryPanel->childFromPoint(inv_x, inv_y, true); + LLView * inventory_panel_child_at_point = panel->childFromPoint(inv_x, inv_y, true); pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder); } @@ -439,23 +512,26 @@ void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask) void LLFloaterOutbox::onImportButtonClicked() { - mOutboxInventoryPanel->clearSelection(); + if (mOutboxInventoryPanel.get()) + { + mOutboxInventoryPanel.get()->clearSelection(); + } mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport(); } void LLFloaterOutbox::onOutboxChanged() { - llassert(!mOutboxId.isNull()); - - //if (mOutboxInventoryPanel) - //{ - // mOutboxInventoryPanel->requestSort(); - //} - - fetchOutboxContents(); - - updateView(); + LLViewerInventoryCategory* category = gInventory.getCategory(mOutboxId); + if (mOutboxId.notNull() && category) + { + fetchOutboxContents(); + updateView(); + } + else + { + cleanOutbox(); + } } void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content) @@ -486,6 +562,11 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content) void LLFloaterOutbox::importStatusChanged(bool inProgress) { + if (mOutboxId.isNull() && (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT)) + { + setupOutbox(); + } + if (inProgress) { if (mImportBusy) @@ -503,6 +584,7 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress) } else { + setStatusString(""); mImportBusy = false; mImportButton->setEnabled(mOutboxItemCount > 0); mInventoryImportInProgress->setVisible(false); @@ -513,7 +595,7 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress) void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) { - if (status != MarketplaceErrorCodes::IMPORT_DONE) + if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) { char status_string[16]; sprintf(status_string, "%d", status); diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index a91d8c1139..40519c8fd2 100755 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -54,7 +54,7 @@ public: LLFloaterOutbox(const LLSD& key); ~LLFloaterOutbox(); - void setupOutbox(const LLUUID& outboxId); + void initializeMarketPlace(); // virtuals BOOL postBuild(); @@ -70,6 +70,8 @@ public: void onMouseLeave(S32 x, S32 y, MASK mask); protected: + void setupOutbox(); + void cleanOutbox(); void fetchOutboxContents(); void importReportResults(U32 status, const LLSD& content); @@ -104,7 +106,7 @@ private: LLTextBox * mInventoryTitle; LLUUID mOutboxId; - LLInventoryPanel * mOutboxInventoryPanel; + LLHandle<LLInventoryPanel> mOutboxInventoryPanel; U32 mOutboxItemCount; LLPanel * mOutboxTopLevelDropZone; diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index c28657dbcd..aac3a41b9e 100755 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -232,16 +232,16 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) return continue_filtering; } -LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() -{ - return &mInventoryViewModel; -} - - -const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const -{ - return &mInventoryViewModel; -} +//LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +//{ +// return &mInventoryViewModel; +//} +// +// +//const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +//{ +// return &mInventoryViewModel; +//} bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 935fe2b4d0..ed7fd3cd34 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -369,15 +369,74 @@ 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 // inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*, +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*, bool find_in_library*/) { LLUUID rv = LLUUID::null; - const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID(); if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) { @@ -392,9 +451,9 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe S32 count = cats->count(); for(S32 i = 0; i < count; ++i) { - if(cats->get(i)->getPreferredType() == preferred_type) + if (cats->get(i)->getPreferredType() == preferred_type) { - rv = cats->get(i)->getUUID(); + rv = cats->get(i)->getUUID(); break; } } @@ -587,7 +646,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, return id; } -// Starting with the object specified, add it's descendents to the +// Starting with the object specified, add its descendents to the // array provided, but do not add the inventory object specified by // id. There is no guaranteed order. Neither array will be erased // before adding objects to it. Do not store a copy of the pointers @@ -1003,7 +1062,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat) new_cat->copyViewerCategory(cat); addCategory(new_cat); - // make sure this category is correctly referenced by it's parent. + // make sure this category is correctly referenced by its parent. cat_array_t* cat_array; cat_array = getUnlockedCatArray(cat->getParentUUID()); if(cat_array) @@ -1209,12 +1268,6 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // folders, items, etc in a fairly efficient manner. void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) { - EHasChildren children = categoryHasChildren(id); - if(children == CHILDREN_NO) - { - llinfos << "Not purging descendents of " << id << llendl; - return; - } LLPointer<LLViewerInventoryCategory> cat = getCategory(id); if (cat.notNull()) { @@ -1225,7 +1278,7 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) << " iterate and purge non hidden items" << llendl; cat_array_t* categories; item_array_t* items; - // Get the list of direct descendants in tha categoy passed as argument + // Get the list of direct descendants in that category passed as argument getDirectDescendentsOf(id, categories, items); std::vector<LLUUID> list_uuids; // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 8aac879a93..544ca5e5dc 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -263,6 +263,11 @@ public: // Get the inventoryID or item that this item points to, else just return object_id const LLUUID& getLinkedItemID(const LLUUID& object_id) const; LLViewerInventoryItem* getLinkedItem(const LLUUID& object_id) const; + + // 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 diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 9db175ec2e..16427f2016 100755 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -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 deleted 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) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index e5b9e11d48..81ee7ac07e 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -137,7 +137,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : LLPanel(p), mInventoryObserver(NULL), mCompletionObserver(NULL), - mFolderRoot(NULL), mScroller(NULL), mSortOrderSetting(p.sort_order_setting), mInventory(p.inventory), @@ -196,6 +195,32 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) return LLUICtrlFactory::create<LLFolderView>(p); } +void LLInventoryPanel::clearFolderRoot() +{ + gIdleCallbacks.deleteFunction(idle, this); + gIdleCallbacks.deleteFunction(onIdle, this); + + if (mInventoryObserver) + { + mInventory->removeObserver(mInventoryObserver); + delete mInventoryObserver; + mInventoryObserver = NULL; + } + if (mCompletionObserver) + { + mInventory->removeObserver(mCompletionObserver); + delete mCompletionObserver; + mCompletionObserver = NULL; + } + + if (mScroller) + { + removeChild(mScroller); + delete mScroller; + mScroller = NULL; + } +} + void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { // save off copy of params @@ -203,23 +228,23 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) // Clear up the root view // Note: This needs to be done *before* we build the new folder view LLUUID root_id = getRootFolderID(); - if (mFolderRoot) + if (mFolderRoot.get()) { removeItemID(root_id); - mFolderRoot->destroyView(); - mFolderRoot = NULL; + mFolderRoot.get()->destroyView(); } mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves { // Determine the root folder in case specified, and // build the views starting with that folder. - mFolderRoot = createFolderRoot(root_id); + LLFolderView* folder_view = createFolderRoot(root_id); + mFolderRoot = folder_view->getHandle(); - addItemID(root_id, mFolderRoot); + addItemID(root_id, mFolderRoot.get()); } mCommitCallbackRegistrar.popScope(); - mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar); // Scroller LLRect scroller_view_rect = getRect(); @@ -228,10 +253,10 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) scroller_params.rect(scroller_view_rect); mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); addChild(mScroller); - mScroller->addChild(mFolderRoot); - mFolderRoot->setScrollContainer(mScroller); - mFolderRoot->setFollowsAll(); - mFolderRoot->addChild(mFolderRoot->mStatusTextBox); + mScroller->addChild(mFolderRoot.get()); + mFolderRoot.get()->setScrollContainer(mScroller); + mFolderRoot.get()->setFollowsAll(); + mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox); // Set up the callbacks from the inventory we're viewing, and then build everything. mInventoryObserver = new LLInventoryPanelObserver(this); @@ -259,8 +284,11 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) } // hide inbox - getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); - getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); + if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible")) + { + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); + } // set the filter for the empty folder if the debug setting is on if (gSavedSettings.getBOOL("DebugHideEmptySystemFolders")) @@ -277,23 +305,13 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) LLInventoryPanel::~LLInventoryPanel() { - gIdleCallbacks.deleteFunction(idle, this); - U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - gSavedSettings.setU32(mSortOrderSetting, sort_order); - } - - gIdleCallbacks.deleteFunction(onIdle, this); - - // LLView destructor will take care of the sub-views. - mInventory->removeObserver(mInventoryObserver); - mInventory->removeObserver(mCompletionObserver); - delete mInventoryObserver; - delete mCompletionObserver; - - mScroller = NULL; + if (mSortOrderSetting != INHERIT_SORT_ORDER) + { + gSavedSettings.setU32(mSortOrderSetting, sort_order); + } + + clearFolderRoot(); } void LLInventoryPanel::draw() @@ -360,9 +378,9 @@ void LLInventoryPanel::setSortOrder(U32 order) if (order != getFolderViewModel()->getSorter().getSortOrder()) { getFolderViewModel()->setSorter(sorter); - mFolderRoot->arrangeAll(); + mFolderRoot.get()->arrangeAll(); // try to keep selection onscreen, even if it wasn't to start with - mFolderRoot->scrollToShowSelection(); + mFolderRoot.get()->scrollToShowSelection(); } } @@ -505,7 +523,7 @@ void LLInventoryPanel::modelChanged(U32 mask) // Add the UI element for this item. buildNewViews(item_id); // Select any newly created object that has the auto rename at top of folder root set. - if(mFolderRoot->getRoot()->needsAutoRename()) + if(mFolderRoot.get()->getRoot()->needsAutoRename()) { setSelection(item_id, FALSE); } @@ -556,17 +574,11 @@ void LLInventoryPanel::modelChanged(U32 mask) } } -LLFolderView* LLInventoryPanel::getRootFolder() -{ - return mFolderRoot; -} - LLUUID LLInventoryPanel::getRootFolderID() { - if (mFolderRoot && mFolderRoot->getViewModelItem()) + if (mFolderRoot.get() && mFolderRoot.get()->getViewModelItem()) { - return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); - + return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot.get()->getViewModelItem())->getUUID(); } else { @@ -587,6 +599,9 @@ LLUUID LLInventoryPanel::getRootFolderID() } else if (preferred_type != LLFolderType::FT_NONE) { + LLStringExplicit label(mParams.start_folder.name()); + setLabel(label); + root_id = gInventory.findCategoryUUIDForType(preferred_type, false); if (root_id.isNull()) { @@ -646,24 +661,33 @@ void LLInventoryPanel::idle(void* user_data) } - panel->mFolderRoot->update(); - // while dragging, update selection rendering to reflect single/multi drag status - if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) - { - EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); - if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) - { - panel->mFolderRoot->setShowSingleSelection(TRUE); - } - else - { - panel->mFolderRoot->setShowSingleSelection(FALSE); - } -} - else - { - panel->mFolderRoot->setShowSingleSelection(FALSE); - } + // Take into account the fact that the root folder might be invalidated + if (panel->mFolderRoot.get()) + { + panel->mFolderRoot.get()->update(); + // while dragging, update selection rendering to reflect single/multi drag status + if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) + { + EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); + if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) + { + panel->mFolderRoot.get()->setShowSingleSelection(TRUE); + } + else + { + panel->mFolderRoot.get()->setShowSingleSelection(FALSE); + } + } + else + { + panel->mFolderRoot.get()->setShowSingleSelection(FALSE); + } + } + else + { + llwarns << "Inventory : Deleted folder root detected on panel" << llendl; + panel->clearFolderRoot(); + } } @@ -714,7 +738,7 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br LLFolderViewFolder::Params params(mParams.folder); params.name = bridge->getDisplayName(); - params.root = mFolderRoot; + params.root = mFolderRoot.get(); params.listener = bridge; params.tool_tip = params.name; @@ -730,7 +754,7 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge params.name = bridge->getDisplayName(); params.creation_date = bridge->getCreationDate(); - params.root = mFolderRoot; + params.root = mFolderRoot.get(); params.listener = bridge; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; @@ -771,7 +795,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) LLInventoryType::IT_CATEGORY, this, &mInventoryViewModel, - mFolderRoot, + mFolderRoot.get(), objectp->getUUID()); if (new_listener) { @@ -787,7 +811,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) item->getInventoryType(), this, &mInventoryViewModel, - mFolderRoot, + mFolderRoot.get(), item->getUUID(), item->getFlags()); @@ -844,7 +868,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) void LLInventoryPanel::openStartFolderOrMyInventory() { // Find My Inventory folder and open it up by name - for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child)) + for (LLView *child = mFolderRoot.get()->getFirstChild(); child; child = mFolderRoot.get()->findNextSibling(child)) { LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child); if (fchild @@ -859,12 +883,12 @@ void LLInventoryPanel::openStartFolderOrMyInventory() void LLInventoryPanel::onItemsCompletion() { - if (mFolderRoot) mFolderRoot->updateMenu(); + if (mFolderRoot.get()) mFolderRoot.get()->updateMenu(); } void LLInventoryPanel::openSelected() { - LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem(); + LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem(); if(!folder_item) return; LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); if(!bridge) return; @@ -873,7 +897,7 @@ void LLInventoryPanel::openSelected() void LLInventoryPanel::unSelectAll() { - mFolderRoot->setSelection(NULL, FALSE, FALSE); + mFolderRoot.get()->setSelection(NULL, FALSE, FALSE); } @@ -911,14 +935,14 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // If folder view is empty the (x, y) point won't be in its rect // so the handler must be called explicitly. // but only if was not handled before. See EXT-6746. - if (!handled && !mFolderRoot->hasVisibleChildren()) + if (!handled && !mFolderRoot.get()->hasVisibleChildren()) { - handled = mFolderRoot->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + handled = mFolderRoot.get()->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } if (handled) { - mFolderRoot->setDragAndDropThisFrame(); + mFolderRoot.get()->setDragAndDropThisFrame(); } } @@ -928,7 +952,7 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLInventoryPanel::onFocusLost() { // inventory no longer handles cut/copy/paste/delete - if (LLEditMenuHandler::gEditMenuHandler == mFolderRoot) + if (LLEditMenuHandler::gEditMenuHandler == mFolderRoot.get()) { LLEditMenuHandler::gEditMenuHandler = NULL; } @@ -939,7 +963,7 @@ void LLInventoryPanel::onFocusLost() void LLInventoryPanel::onFocusReceived() { // inventory now handles cut/copy/paste/delete - LLEditMenuHandler::gEditMenuHandler = mFolderRoot; + LLEditMenuHandler::gEditMenuHandler = mFolderRoot.get(); LLPanel::onFocusReceived(); } @@ -950,7 +974,7 @@ bool LLInventoryPanel::addBadge(LLBadge * badge) if (acceptsBadge()) { - badge_added = badge->addToView(mFolderRoot); + badge_added = badge->addToView(mFolderRoot.get()); } return badge_added; @@ -958,8 +982,8 @@ bool LLInventoryPanel::addBadge(LLBadge * badge) void LLInventoryPanel::openAllFolders() { - mFolderRoot->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); - mFolderRoot->arrangeAll(); + mFolderRoot.get()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); + mFolderRoot.get()->arrangeAll(); } void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus) @@ -975,9 +999,9 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb) { - if (mFolderRoot) + if (mFolderRoot.get()) { - mFolderRoot->setSelectCallback(cb); + mFolderRoot.get()->setSelectCallback(cb); } } @@ -1001,7 +1025,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it } } - LLFolderView* fv = getRootFolder(); + LLFolderView* fv = mFolderRoot.get(); if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename { fv->setNeedsAutoRename(FALSE); @@ -1020,7 +1044,7 @@ void LLInventoryPanel::doCreate(const LLSD& userdata) bool LLInventoryPanel::beginIMSession() { - std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot.get()->getSelectionList(); std::string name; @@ -1114,7 +1138,7 @@ bool LLInventoryPanel::beginIMSession() bool LLInventoryPanel::attachObject(const LLSD& userdata) { // Copy selected item UUIDs to a vector. - std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot.get()->getSelectionList(); uuid_vec_t items; for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); @@ -1141,7 +1165,7 @@ BOOL LLInventoryPanel::getSinceLogoff() void LLInventoryPanel::dumpSelectionInformation(void* user_data) { LLInventoryPanel* iv = (LLInventoryPanel*)user_data; - iv->mFolderRoot->dumpSelectionInformation(); + iv->mFolderRoot.get()->dumpSelectionInformation(); } BOOL is_inventorysp_active() @@ -1343,7 +1367,7 @@ void LLInventoryPanel::updateSelection() void LLInventoryPanel::doToSelected(const LLSD& userdata) { - LLInventoryAction::doToSelected(mInventory, mFolderRoot, userdata.asString()); + LLInventoryAction::doToSelected(mInventory, mFolderRoot.get(), userdata.asString()); return; } @@ -1357,7 +1381,7 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) // Open selected items if enter key hit on the inventory panel if (mask == MASK_NONE) { - LLInventoryAction::doToSelected(mInventory, mFolderRoot, "open"); + LLInventoryAction::doToSelected(mInventory, mFolderRoot.get(), "open"); handled = TRUE; } break; @@ -1367,7 +1391,7 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) // Note: on Mac laptop keyboards, backspace and delete are one and the same if (isSelectionRemovable() && (mask == MASK_NONE)) { - LLInventoryAction::doToSelected(mInventory, mFolderRoot, "delete"); + LLInventoryAction::doToSelected(mInventory, mFolderRoot.get(), "delete"); handled = TRUE; } break; @@ -1378,9 +1402,9 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) bool LLInventoryPanel::isSelectionRemovable() { bool can_delete = false; - if (mFolderRoot) + if (mFolderRoot.get()) { - std::set<LLFolderViewItem*> selection_set = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selection_set = mFolderRoot.get()->getSelectionList(); if (!selection_set.empty()) { can_delete = true; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 00a90325ad..c0ce513694 100755 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -181,7 +181,7 @@ public: LLInventoryFilter::EFolderShow getShowFolderState(); // This method is called when something has changed about the inventory. void modelChanged(U32 mask); - LLFolderView* getRootFolder(); + LLFolderView* getRootFolder() { return mFolderRoot.get(); } LLUUID getRootFolderID(); LLScrollContainer* getScrollableContainer() { return mScroller; } @@ -217,8 +217,11 @@ public: void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); void updateSelection(); - LLFolderViewModelInventory* getFolderViewModel(); - const LLFolderViewModelInventory* getFolderViewModel() const; + LLFolderViewModelInventory* getFolderViewModel() { return &mInventoryViewModel; } + const LLFolderViewModelInventory* getFolderViewModel() const { return &mInventoryViewModel; } + + // Clean up stuff when the folder root gets deleted + void clearFolderRoot(); protected: void openStartFolderOrMyInventory(); // open the first level of inventory @@ -233,7 +236,7 @@ protected: bool mShowItemLinkOverlays; // Shows link graphic over inventory item icons bool mShowEmptyMessage; - LLFolderView* mFolderRoot; + LLHandle<LLFolderView> mFolderRoot; LLScrollContainer* mScroller; LLFolderViewModelInventory mInventoryViewModel; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 0b009b68f7..05c9d76810 100755 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llhttpclient.h" +#include "llsdserialize.h" #include "lltimer.h" #include "lltrans.h" #include "llviewercontrol.h" @@ -135,19 +136,25 @@ namespace LLMarketplaceImport llinfos << " SLM POST status: " << status << llendl; llinfos << " SLM POST reason: " << reason << llendl; llinfos << " SLM POST content: " << content.asString() << llendl; - llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; } - if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || - (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || - (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) + // MAINT-2301 : we determined we can safely ignore that error in that context + if (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM POST clearing marketplace cookie due to authentication failure or timeout" << llendl; + llinfos << " SLM POST : Ignoring time out status and treating it as success" << llendl; + } + status = MarketplaceErrorCodes::IMPORT_DONE; + } + + if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) + { + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST clearing marketplace cookie due to client or server error" << llendl; } - sMarketplaceCookie.clear(); } @@ -182,20 +189,25 @@ namespace LLMarketplaceImport llinfos << " SLM GET status: " << status << llendl; llinfos << " SLM GET reason: " << reason << llendl; llinfos << " SLM GET content: " << content.asString() << llendl; - llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; } - if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || - (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) + // 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 initally empty + if ((status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) && + (status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) && + (status != MarketplaceErrorCodes::IMPORT_NOT_FOUND)) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl; + llinfos << " SLM GET clearing marketplace cookie due to client or server error" << llendl; } - sMarketplaceCookie.clear(); } + else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)) + { + llinfos << " SLM GET : Got error status = " << status << ", but marketplace cookie not cleared." << llendl; + } sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING); sImportGetPending = false; @@ -256,7 +268,12 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET: " << url << llendl; + llinfos << " SLM GET: establishMarketplaceSessionCookie, LLHTTPClient::get, url = " << url << llendl; + LLSD headers = LLViewerMedia::getHeaders(); + std::stringstream str; + LLSDSerialize::toPrettyXML(headers, str); + llinfos << " SLM GET: headers " << llendl; + llinfos << str.str() << llendl; } slmGetTimer.start(); @@ -287,7 +304,11 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET: " << url << llendl; + llinfos << " SLM GET: pollStatus, LLHTTPClient::get, url = " << url << llendl; + std::stringstream str; + LLSDSerialize::toPrettyXML(headers, str); + llinfos << " SLM GET: headers " << llendl; + llinfos << str.str() << llendl; } slmGetTimer.start(); @@ -321,11 +342,15 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM POST: " << url << llendl; + llinfos << " SLM POST: triggerImport, LLHTTPClient::post, url = " << url << llendl; + std::stringstream str; + LLSDSerialize::toPrettyXML(headers, str); + llinfos << " SLM POST: headers " << llendl; + llinfos << str.str() << llendl; } slmPostTimer.start(); - LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers); + LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers); return true; } @@ -356,6 +381,7 @@ LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter() : mAutoTriggerImport(false) , mImportInProgress(false) , mInitialized(false) + , mMarketPlaceStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) , mErrorInitSignal(NULL) , mStatusChangedSignal(NULL) , mStatusReportSignal(NULL) @@ -394,20 +420,27 @@ boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallb void LLMarketplaceInventoryImporter::initialize() { - llassert(!mInitialized); + if (mInitialized) + { + return; + } if (!LLMarketplaceImport::hasSessionCookie()) { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING; LLMarketplaceImport::establishMarketplaceSessionCookie(); } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; + } } void LLMarketplaceInventoryImporter::reinitializeAndTriggerImport() { mInitialized = false; - + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED; initialize(); - mAutoTriggerImport = true; } @@ -459,17 +492,30 @@ void LLMarketplaceInventoryImporter::updateImport() if (mInitialized) { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; // Follow up with auto trigger of import if (mAutoTriggerImport) { mAutoTriggerImport = false; - mImportInProgress = triggerImport(); } } - else if (mErrorInitSignal) + else { - (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + U32 status = LLMarketplaceImport::getResultStatus(); + if ((status == MarketplaceErrorCodes::IMPORT_FORBIDDEN) || + (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT; + } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; + } + if (mErrorInitSignal && (mMarketPlaceStatus == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE)) + { + (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } } } } diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index 4b8f7a1ac7..abe60890a3 100755 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -47,10 +47,27 @@ namespace MarketplaceErrorCodes IMPORT_DONE = 200, IMPORT_PROCESSING = 202, IMPORT_REDIRECT = 302, + IMPORT_BAD_REQUEST = 400, IMPORT_AUTHENTICATION_ERROR = 401, + IMPORT_FORBIDDEN = 403, + IMPORT_NOT_FOUND = 404, IMPORT_DONE_WITH_ERRORS = 409, IMPORT_JOB_FAILED = 410, IMPORT_JOB_TIMEOUT = 499, + IMPORT_SERVER_SITE_DOWN = 500, + IMPORT_SERVER_API_DISABLED = 503, + }; +} + +namespace MarketplaceStatusCodes +{ + enum sCode + { + MARKET_PLACE_NOT_INITIALIZED = 0, + MARKET_PLACE_INITIALIZING = 1, + MARKET_PLACE_CONNECTION_FAILURE = 2, + MARKET_PLACE_MERCHANT = 3, + MARKET_PLACE_NOT_MERCHANT = 4, }; } @@ -73,6 +90,8 @@ public: void initialize(); bool triggerImport(); bool isImportInProgress() const { return mImportInProgress; } + bool isInitialized() const { return mInitialized; } + U32 getMarketPlaceStatus() const { return mMarketPlaceStatus; } protected: void reinitializeAndTriggerImport(); @@ -82,6 +101,7 @@ private: bool mAutoTriggerImport; bool mImportInProgress; bool mInitialized; + U32 mMarketPlaceStatus; status_report_signal_t * mErrorInitSignal; status_changed_signal_t * mStatusChangedSignal; diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index adfb2dee86..da938712d7 100755 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -69,7 +69,7 @@ LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge LLInboxFolderViewFolder::Params params; params.name = bridge->getDisplayName(); - params.root = mFolderRoot; + params.root = mFolderRoot.get(); params.listener = bridge; params.tool_tip = params.name; params.font_color = item_color; @@ -86,7 +86,7 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b params.name = bridge->getDisplayName(); params.creation_date = bridge->getCreationDate(); - params.root = mFolderRoot; + params.root = mFolderRoot.get(); params.listener = bridge; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 4c2213c198..5eadd65884 100755 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -91,17 +91,17 @@ LLFolderView * LLPlacesInventoryPanel::createFolderRoot(LLUUID root_id ) void LLPlacesInventoryPanel::saveFolderState() { mSavedFolderState->setApply(FALSE); - mFolderRoot->applyFunctorRecursively(*mSavedFolderState); + mFolderRoot.get()->applyFunctorRecursively(*mSavedFolderState); } // re-open folders which state was saved void LLPlacesInventoryPanel::restoreFolderState() { mSavedFolderState->setApply(TRUE); - mFolderRoot->applyFunctorRecursively(*mSavedFolderState); + mFolderRoot.get()->applyFunctorRecursively(*mSavedFolderState); LLOpenFoldersWithSelection opener; - mFolderRoot->applyFunctorRecursively(opener); - mFolderRoot->scrollToShowSelection(); + mFolderRoot.get()->applyFunctorRecursively(opener); + mFolderRoot.get()->scrollToShowSelection(); } S32 LLPlacesInventoryPanel::notify(const LLSD& info) @@ -111,11 +111,11 @@ S32 LLPlacesInventoryPanel::notify(const LLSD& info) std::string str_action = info["action"]; if(str_action == "select_first") { - return mFolderRoot->notify(info); + return mFolderRoot.get()->notify(info); } else if(str_action == "select_last") { - return mFolderRoot->notify(info); + return mFolderRoot.get()->notify(info); } } return 0; diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index cbf43dbb93..b78cb61cb9 100755 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -119,7 +119,6 @@ private: LLSidepanelInventory::LLSidepanelInventory() : LLPanel() , mItemPanel(NULL) - , mInventoryPanelInbox(NULL) , mPanelMainInventory(NULL) , mInboxEnabled(false) , mCategoriesObserver(NULL) @@ -299,7 +298,7 @@ void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID) // (this can happen multiple times on the initial session that creates the inbox) // - if (mInventoryPanelInbox != NULL) + if (mInventoryPanelInbox.get() != NULL) { return; } @@ -333,7 +332,8 @@ void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID) // LLPanelMarketplaceInbox * inbox = getChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL); - mInventoryPanelInbox = inbox->setupInventoryPanel(); + LLInventoryPanel* inventory_panel = inbox->setupInventoryPanel(); + mInventoryPanelInbox = inventory_panel->getInventoryPanelHandle(); } void LLSidepanelInventory::enableInbox(bool enabled) @@ -461,9 +461,9 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action) LLFolderViewItem* current_item = mPanelMainInventory->getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) { - if (mInventoryPanelInbox) + if (mInventoryPanelInbox.get() && mInventoryPanelInbox.get()->getRootFolder()) { - current_item = mInventoryPanelInbox->getRootFolder()->getCurSelectedItem(); + current_item = mInventoryPanelInbox.get()->getRootFolder()->getCurSelectedItem(); } if (!current_item) @@ -614,10 +614,10 @@ void LLSidepanelInventory::updateVerbs() bool LLSidepanelInventory::canShare() { - LLInventoryPanel* inbox = mInventoryPanelInbox; + LLInventoryPanel* inbox = mInventoryPanelInbox.get(); // Avoid flicker in the Recent tab while inventory is being loaded. - if ( (!inbox || inbox->getRootFolder()->getSelectionList().empty()) + if ( (!inbox || !inbox->getRootFolder() || inbox->getRootFolder()->getSelectionList().empty()) && (mPanelMainInventory && !mPanelMainInventory->getActivePanel()->getRootFolder()->hasVisibleChildren()) ) { return false; @@ -652,9 +652,9 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem() if (!current_item) { - if (mInventoryPanelInbox) + if (mInventoryPanelInbox.get() && mInventoryPanelInbox.get()->getRootFolder()) { - current_item = mInventoryPanelInbox->getRootFolder()->getCurSelectedItem(); + current_item = mInventoryPanelInbox.get()->getRootFolder()->getCurSelectedItem(); } if (!current_item) @@ -671,12 +671,12 @@ U32 LLSidepanelInventory::getSelectedCount() { int count = 0; - std::set<LLFolderViewItem*> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); count += selection_list.size(); - if ((count == 0) && mInboxEnabled && (mInventoryPanelInbox != NULL)) + if ((count == 0) && mInboxEnabled && mInventoryPanelInbox.get() && mInventoryPanelInbox.get()->getRootFolder()) { - selection_list = mInventoryPanelInbox->getRootFolder()->getSelectionList(); + selection_list = mInventoryPanelInbox.get()->getRootFolder()->getSelectionList(); count += selection_list.size(); } @@ -714,9 +714,9 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox) } } - if (clearInbox && mInboxEnabled && (mInventoryPanelInbox != NULL)) + if (clearInbox && mInboxEnabled && mInventoryPanelInbox.get()) { - mInventoryPanelInbox->clearSelection(); + mInventoryPanelInbox.get()->clearSelection(); } updateVerbs(); @@ -726,9 +726,9 @@ std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList() { std::set<LLFolderViewItem*> inventory_selected_uuids; - if (mInboxEnabled && (mInventoryPanelInbox != NULL)) + if (mInboxEnabled && mInventoryPanelInbox.get() && mInventoryPanelInbox.get()->getRootFolder()) { - inventory_selected_uuids = mInventoryPanelInbox->getRootFolder()->getSelectionList(); + inventory_selected_uuids = mInventoryPanelInbox.get()->getRootFolder()->getSelectionList(); } return inventory_selected_uuids; diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index e8b2808d4f..17a3098db9 100755 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -57,7 +57,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); LLInventoryPanel* getActivePanel(); // Returns an active inventory panel, if any. - LLInventoryPanel* getInboxPanel() const { return mInventoryPanelInbox; } + LLInventoryPanel* getInboxPanel() const { return mInventoryPanelInbox.get(); } LLPanelMainInventory* getMainInventoryPanel() const { return mPanelMainInventory; } BOOL isMainInventoryPanelActive() const; @@ -99,7 +99,7 @@ protected: // private: LLPanel* mInventoryPanel; // Main inventory view - LLInventoryPanel* mInventoryPanelInbox; + LLHandle<LLInventoryPanel> mInventoryPanelInbox; LLSidepanelItemInfo* mItemPanel; // Individual item view LLSidepanelTaskInfo* mTaskPanel; // Individual in-world object view LLPanelMainInventory* mPanelMainInventory; diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index a179b61cff..991f6b40e6 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -30,6 +30,9 @@ #include "lldictionary.h" #include "llmemory.h" #include "llvisualparam.h" +#include "llcontrol.h" + +extern LLControlGroup gSavedSettings; static const std::string empty_string; @@ -132,8 +135,9 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE, true)); addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); - addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); - addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); + bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible"); + addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); + addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a93601f5fd..4a0948991a 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -271,7 +271,7 @@ See the [[MARKETPLACE_IMPORTS_URL] error log] for more information. icon="OutboxStatus_Error" name="OutboxImportFailed" type="outbox"> -Transfer failed +Transfer failed with error '[ERROR_CODE]' No folders were sent to the Marketplace because of a system or network error. Try again later. @@ -284,7 +284,7 @@ No folders were sent to the Marketplace because of a system or network error. T icon="OutboxStatus_Error" name="OutboxInitFailed" type="outbox"> -Marketplace initialization failed +Marketplace initialization failed with error '[ERROR_CODE]' Initialization with the Marketplace failed because of a system or network error. Try again later. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7e79d297ef..9300652eaa 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2209,6 +2209,16 @@ If you'd like to become a merchant, you'll need to [[MARKETPLACE_CREATE_STORE_UR <string name="InventoryOutboxNoItems"> Drag folders to this area and click "Send to Marketplace" to list them for sale on the [[MARKETPLACE_DASHBOARD_URL] Marketplace]. </string> + <string name="InventoryOutboxInitializingTitle">Initializing Marketplace.</string> + <string name="InventoryOutboxInitializingTooltip"></string> + <string name="InventoryOutboxInitializing"> +We are accessing your account on the [[MARKETPLACE_CREATE_STORE_URL] Marketplace store]. + </string> + <string name="InventoryOutboxErrorTitle">Marketplace Errors.</string> + <string name="InventoryOutboxErrorTooltip"></string> + <string name="InventoryOutboxError"> +The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. + </string> <string name="Marketplace Error None">No errors</string> <string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string> |