From 3c18de21369260ec9b7ba39c0e360045dd65e30d Mon Sep 17 00:00:00 2001
From: Rider Linden <rider@lindenlab.com>
Date: Thu, 10 May 2018 17:08:13 -0700
Subject: Settings editor available from the open context on the menu.  Can
 edit inventory items.

---
 indra/newview/llfloaterfixedenvironment.cpp | 165 ++++++++++++++++++++--------
 indra/newview/llfloaterfixedenvironment.h   |  27 +++--
 indra/newview/llinventorybridge.cpp         |  43 +++++++-
 indra/newview/llsettingsvo.cpp              | 163 ++++++++++++++-------------
 indra/newview/llsettingsvo.h                |  27 +++--
 indra/newview/llviewerinventory.cpp         |  13 +++
 indra/newview/llviewerinventory.h           |   3 +
 7 files changed, 293 insertions(+), 148 deletions(-)

diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index f95e41408f..f03c8ba7d1 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -38,6 +38,8 @@
 #include "lltabcontainer.h"
 #include "llfilepicker.h"
 
+#include "llviewerparcelmgr.h"
+
 // newview
 #include "llpaneleditwater.h"
 #include "llpaneleditsky.h"
@@ -47,8 +49,10 @@
 
 #include "llenvironment.h"
 #include "llagent.h"
+#include "llparcel.h"
 
 #include "llsettingsvo.h"
+#include "llinventorymodel.h"
 
 namespace
 {
@@ -56,21 +60,30 @@ namespace
 
     const std::string CONTROL_TAB_AREA("tab_settings");
 
-    const std::string BUTTON_NAME_LOAD("btn_load");
     const std::string BUTTON_NAME_IMPORT("btn_import");
     const std::string BUTTON_NAME_COMMIT("btn_commit");
     const std::string BUTTON_NAME_CANCEL("btn_cancel");
+    const std::string BUTTON_NAME_FLYOUT("btn_flyout");
 
     const std::string ACTION_SAVE("save_settings");
     const std::string ACTION_SAVEAS("save_as_new_settings");
     const std::string ACTION_APPLY_LOCAL("apply_local");
     const std::string ACTION_APPLY_PARCEL("apply_parcel");
     const std::string ACTION_APPLY_REGION("apply_region");
+
+    const std::string XML_FLYOUTMENU_FILE("menu_save_settings.xml");
 }
 
+//=========================================================================
+const std::string LLFloaterFixedEnvironment::KEY_INVENTORY_ID("inventory_id");
+
+
+//=========================================================================
 LLFloaterFixedEnvironment::LLFloaterFixedEnvironment(const LLSD &key) :
     LLFloater(key),
-    mFlyoutControl(nullptr)
+    mFlyoutControl(nullptr),
+    mInventoryId(),
+    mInventoryItem(nullptr)
 {
 }
 
@@ -87,16 +100,40 @@ BOOL LLFloaterFixedEnvironment::postBuild()
     mTxtName->setCommitOnFocusLost(TRUE);
     mTxtName->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNameChanged(mTxtName->getValue().asString()); });
 
-    getChild<LLButton>(BUTTON_NAME_LOAD)->setClickedCallback([this](LLUICtrl *, const LLSD &) { onButtonLoad(); });
     getChild<LLButton>(BUTTON_NAME_IMPORT)->setClickedCallback([this](LLUICtrl *, const LLSD &) { onButtonImport(); });
     getChild<LLButton>(BUTTON_NAME_CANCEL)->setClickedCallback([this](LLUICtrl *, const LLSD &) { onButtonCancel(); });
 
-    mFlyoutControl = new LLFlyoutComboBtn(this, "btn_commit", "btn_flyout", "menu_save_settings.xml");
+    mFlyoutControl = new LLFlyoutComboBtn(this, BUTTON_NAME_COMMIT, BUTTON_NAME_FLYOUT, XML_FLYOUTMENU_FILE);
     mFlyoutControl->setAction([this](LLUICtrl *ctrl, const LLSD &data) { onButtonApply(ctrl, data); });
 
     return TRUE;
 }
 
+void LLFloaterFixedEnvironment::onOpen(const LLSD& key)
+{
+    LLUUID invid;
+
+    if (key.has(KEY_INVENTORY_ID))
+    {
+        invid = key[KEY_INVENTORY_ID].asUUID();
+    }
+
+    loadInventoryItem(invid);
+    LL_INFOS("SETTINGS") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
+
+    updateEditEnvironment();
+    syncronizeTabs();
+    refresh();
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
+
+}
+
+void LLFloaterFixedEnvironment::onClose(bool app_quitting)
+{
+    mSettings.reset();
+    syncronizeTabs();
+}
+
 void LLFloaterFixedEnvironment::onFocusReceived()
 {
     updateEditEnvironment();
@@ -119,12 +156,10 @@ void LLFloaterFixedEnvironment::refresh()
         return;
     }
 
-    bool enableApplyAndLoad = canUseInventory();
+    bool is_inventory_avail = canUseInventory();
 
-    mFlyoutControl->setMenuItemEnabled(ACTION_SAVE, enableApplyAndLoad);
-    mFlyoutControl->setMenuItemEnabled(ACTION_SAVEAS, enableApplyAndLoad);
-
-    getChild<LLButton>(BUTTON_NAME_LOAD)->setEnabled(enableApplyAndLoad);
+    mFlyoutControl->setMenuItemEnabled(ACTION_SAVE, is_inventory_avail);
+    mFlyoutControl->setMenuItemEnabled(ACTION_SAVEAS, is_inventory_avail);
 
     mTxtName->setValue(mSettings->getName());
 
@@ -150,14 +185,42 @@ void LLFloaterFixedEnvironment::syncronizeTabs()
     }
 }
 
-void LLFloaterFixedEnvironment::onNameChanged(const std::string &name)
+void LLFloaterFixedEnvironment::loadInventoryItem(const LLUUID  &inventoryId)
 {
-    mSettings->setName(name);
+    if (inventoryId.isNull())
+    {
+        mInventoryItem = nullptr;
+        mInventoryId.setNull();
+        return;
+    }
+
+    mInventoryId = inventoryId;
+    LL_INFOS("SETTINGS") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
+    mInventoryItem = gInventory.getItem(mInventoryId);
+
+    if (!mInventoryItem)
+    {
+        LL_WARNS("SETTINGS") << "Could not find inventory item with Id = " << mInventoryId << LL_ENDL;
+        mInventoryId.setNull();
+        mInventoryItem = nullptr;
+        return;
+    }
+
+    LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
+        [this](LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status, LLExtStat) { onAssetLoaded(asset_id, settins, status); });
 }
 
-void LLFloaterFixedEnvironment::onButtonLoad()
+void LLFloaterFixedEnvironment::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status)
 {
-    doLoadFromInventory();
+    mSettings = settins;
+    updateEditEnvironment();
+    syncronizeTabs();
+    refresh();
+}
+
+void LLFloaterFixedEnvironment::onNameChanged(const std::string &name)
+{
+    mSettings->setName(name);
 }
 
 void LLFloaterFixedEnvironment::onButtonImport()
@@ -171,11 +234,11 @@ void LLFloaterFixedEnvironment::onButtonApply(LLUICtrl *ctrl, const LLSD &data)
 
     if (ctrl_action == ACTION_SAVE)
     {
-        doApplyCreateNewInventory();
+        doApplyUpdateInventory();
     }
     else if (ctrl_action == ACTION_SAVEAS)
     {
-        doApplyUpdateInventory();
+        doApplyCreateNewInventory();
     }
     else if ((ctrl_action == ACTION_APPLY_LOCAL) ||
         (ctrl_action == ACTION_APPLY_PARCEL) ||
@@ -198,12 +261,15 @@ void LLFloaterFixedEnvironment::onButtonCancel()
 void LLFloaterFixedEnvironment::doApplyCreateNewInventory()
 {
     // This method knows what sort of settings object to create.
-    LLSettingsVOBase::createInventoryItem(mSettings);
+    LLSettingsVOBase::createInventoryItem(mSettings, [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
 }
 
 void LLFloaterFixedEnvironment::doApplyUpdateInventory()
 {
-    // todo update existing inventory object.
+    if (mInventoryId.isNull())
+        LLSettingsVOBase::createInventoryItem(mSettings, [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    else
+        LLSettingsVOBase::updateInventoryItem(mSettings, mInventoryId, [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryUpdated(asset_id, inventory_id, results); });
 }
 
 void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where)
@@ -230,20 +296,50 @@ void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where)
     }
 }
 
+void LLFloaterFixedEnvironment::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
+{
+    LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been created with asset " << asset_id << " results are:" << results << LL_ENDL;
+    
+    setFocus(TRUE);                 // Call back the focus...
+    loadInventoryItem(inventory_id);
+}
+
+void LLFloaterFixedEnvironment::onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
+{
+    LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been updated with asset " << asset_id << " results are:" << results << LL_ENDL;
+
+    if (inventory_id != mInventoryId)
+    {
+        loadInventoryItem(inventory_id);
+    }
+}
+
 //-------------------------------------------------------------------------
 bool LLFloaterFixedEnvironment::canUseInventory() const
 {
-    return !gAgent.getRegionCapability("UpdateSettingsAgentInventory").empty();
+    return LLEnvironment::instance().isInventoryEnabled();
 }
 
 bool LLFloaterFixedEnvironment::canApplyRegion() const
 {
-    return true;
+    return gAgent.canManageEstate();
 }
 
 bool LLFloaterFixedEnvironment::canApplyParcel() const
 {
-    return false;
+    LLParcelSelectionHandle handle(LLViewerParcelMgr::instance().getParcelSelection());
+    LLParcel *parcel(nullptr);
+
+    if (handle)
+        parcel = handle->getParcel();
+    if (!parcel)
+        parcel = LLViewerParcelMgr::instance().getAgentParcel();
+
+    if (!parcel)
+        return false;
+
+    return parcel->allowModifyBy(gAgent.getID(), gAgent.getGroupID()) && 
+        LLEnvironment::instance().isExtendedEnvironmentEnabled();
 }
 
 //=========================================================================
@@ -282,21 +378,12 @@ void LLFloaterFixedEnvironmentWater::onOpen(const LLSD& key)
         // TODO: Should we grab sky and keep it around for reference?
     }
 
-    updateEditEnvironment();
-    syncronizeTabs();
-    refresh();
-    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
+    LLFloaterFixedEnvironment::onOpen(key);
 }
 
 void LLFloaterFixedEnvironmentWater::onClose(bool app_quitting)
 {
-    mSettings.reset();
-    syncronizeTabs();
-}
-
-void LLFloaterFixedEnvironmentWater::doLoadFromInventory()
-{
-
+    LLFloaterFixedEnvironment::onClose(app_quitting);
 }
 
 void LLFloaterFixedEnvironmentWater::doImportFromDisk()
@@ -364,24 +451,16 @@ void LLFloaterFixedEnvironmentSky::onOpen(const LLSD& key)
         mSettings = LLEnvironment::instance().getEnvironmentFixedSky(LLEnvironment::ENV_CURRENT)->buildClone();
         mSettings->setName("Snapshot sky (new)");
 
-        // TODO: Should we grab sky and keep it around for reference?
+        // TODO: Should we grab water and keep it around for reference?
     }
 
-    updateEditEnvironment();
-    syncronizeTabs();
-    refresh();
-    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
-}
+    LLFloaterFixedEnvironment::onOpen(key);
 
-void LLFloaterFixedEnvironmentSky::onClose(bool app_quitting)
-{
-    mSettings.reset();
-    syncronizeTabs();
 }
 
-void LLFloaterFixedEnvironmentSky::doLoadFromInventory()
+void LLFloaterFixedEnvironmentSky::onClose(bool app_quitting)
 {
-
+    LLFloaterFixedEnvironment::onClose(app_quitting);
 }
 
 void LLFloaterFixedEnvironmentSky::doImportFromDisk()
diff --git a/indra/newview/llfloaterfixedenvironment.h b/indra/newview/llfloaterfixedenvironment.h
index 22ce167244..782dc9e61c 100644
--- a/indra/newview/llfloaterfixedenvironment.h
+++ b/indra/newview/llfloaterfixedenvironment.h
@@ -30,6 +30,7 @@
 #include "llfloater.h"
 #include "llsettingsbase.h"
 #include "llflyoutcombobtn.h"
+#include "llinventory.h"
 
 class LLTabContainer;
 class LLButton;
@@ -43,29 +44,33 @@ class LLFloaterFixedEnvironment : public LLFloater
     LOG_CLASS(LLFloaterFixedEnvironment);
 
 public:
+    static const std::string    KEY_INVENTORY_ID;
+
                             LLFloaterFixedEnvironment(const LLSD &key);
                             ~LLFloaterFixedEnvironment();
 
-    virtual BOOL	        postBuild()         override;
+    virtual BOOL	        postBuild()                 override;
+    virtual void            onOpen(const LLSD& key)     override;
+    virtual void            onClose(bool app_quitting)  override;
 
-    virtual void            onFocusReceived()   override;
-    virtual void            onFocusLost()       override;
+    virtual void            onFocusReceived()           override;
+    virtual void            onFocusLost()               override;
 
     void                    setEditSettings(const LLSettingsBase::ptr_t &settings)  { mSettings = settings; syncronizeTabs(); refresh(); }
     LLSettingsBase::ptr_t   getEditSettings()   const                           { return mSettings; }
 
 protected:
     virtual void            updateEditEnvironment() = 0;
-    virtual void            refresh()           override;
-
+    virtual void            refresh()                   override;
     virtual void            syncronizeTabs();
 
+    void                    loadInventoryItem(const LLUUID  &inventoryId);
+
     LLTabContainer *        mTab;
     LLLineEditor *          mTxtName;
 
     LLSettingsBase::ptr_t   mSettings;
 
-    virtual void            doLoadFromInventory() = 0;
     virtual void            doImportFromDisk() = 0;
     virtual void            doApplyCreateNewInventory();
     virtual void            doApplyUpdateInventory();
@@ -77,14 +82,20 @@ protected:
 
     LLFlyoutComboBtn *      mFlyoutControl;
 
+    LLUUID                  mInventoryId;
+    LLInventoryItem *       mInventoryItem;
+
+    void                    onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
+    void                    onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
+
 private:
     void                    onNameChanged(const std::string &name);
 
-    void                    onButtonLoad();
     void                    onButtonImport();
     void                    onButtonApply(LLUICtrl *ctrl, const LLSD &data);
     void                    onButtonCancel();
 
+    void                    onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status);
 };
 
 class LLFloaterFixedEnvironmentWater : public LLFloaterFixedEnvironment
@@ -102,7 +113,6 @@ public:
 protected:
     virtual void            updateEditEnvironment()     override;
 
-    virtual void            doLoadFromInventory()       override;
     virtual void            doImportFromDisk()          override;
 
 private:
@@ -123,7 +133,6 @@ public:
 protected:
     virtual void            updateEditEnvironment()     override;
 
-    virtual void            doLoadFromInventory()       override;
     virtual void            doImportFromDisk()          override;
 
 private:
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 9311861d83..7697714f2f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -6910,7 +6910,11 @@ void LLSettingsBridge::performAction(LLInventoryModel* model, std::string action
 
 void LLSettingsBridge::openItem()
 {
-    LLItemBridge::openItem();
+    LLViewerInventoryItem* item = getItem();
+    if (item)
+    {
+        LLInvFVBridgeAction::doAction(item->getType(), mUUID, getInventoryModel());
+    }
 }
 
 void LLSettingsBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
@@ -7271,6 +7275,40 @@ void LLWearableBridgeAction::wearOnAvatar()
 	}
 }
 
+class LLSettingsBridgeAction
+    : public LLInvFVBridgeAction
+{
+    friend class LLInvFVBridgeAction;
+public:
+    virtual void doIt()
+    {
+        LLViewerInventoryItem* item = getItem();
+        if (item)
+        {
+            LLSettingsType::type_e type = item->getSettingsType();
+            switch (type)
+            {
+            case LLSettingsType::ST_SKY:
+                LLFloaterReg::showInstance("env_fixed_environmentent_sky", LLSDMap("inventory_id", item->getUUID()), TAKE_FOCUS_YES);
+                break;
+            case LLSettingsType::ST_WATER:
+                LLFloaterReg::showInstance("env_fixed_environmentent_water", LLSDMap("inventory_id", item->getUUID()), TAKE_FOCUS_YES);
+                break;
+            case LLSettingsType::ST_DAYCYCLE:
+                //LLFloaterReg::showInstance("env_fixed_environmentent_day", LLSDMap("inventory_id", item->getUUID()), TAKE_FOCUS_YES);
+                break;
+            default:
+                break;
+            }
+        }
+        LLInvFVBridgeAction::doIt();
+    }
+    virtual ~LLSettingsBridgeAction(){}
+protected:
+    LLSettingsBridgeAction(const LLUUID& id, LLInventoryModel* model) : LLInvFVBridgeAction(id, model) {}
+};
+
+
 LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
 													   const LLUUID& uuid,
 													   LLInventoryModel* model)
@@ -7309,6 +7347,9 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
 		case LLAssetType::AT_BODYPART:
 			action = new LLWearableBridgeAction(uuid,model);
 			break;
+        case LLAssetType::AT_SETTINGS:
+            action = new LLSettingsBridgeAction(uuid, model);
+            break;
 		default:
 			break;
 	}
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 01d7ab3dcf..ed3c18ef4e 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -55,6 +55,8 @@
 #include "llpermissions.h"
 
 #include "llinventorymodel.h"
+#include "llassetstorage.h"
+#include "llvfile.h"
 
 #undef  VERIFY_LEGACY_CONVERSION
 
@@ -101,70 +103,7 @@ private:
 
 
 //=========================================================================
-#if 0
-void LLSettingsVOBase::storeAsAsset(const LLSettingsBase::ptr_t &settings)
-{
-    LLTransactionID tid;
-    tid.generate();
-
-    LLAssetID aid(tid.makeAssetID(gAgent.getSecureSessionID()));
-
-    const std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, aid.asString()) + ".setting";
-
-    if (!exportFile(settings, filename))
-    {
-        LL_WARNS("SETTINGS") << "Unable to save settings file named '" << filename << "'." << LL_ENDL;
-
-        LLSD args;
-        args["NAME"] = aid.asString() + "setting";
-        LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args);
-        return;
-    }
-
-    SettingsSaveData::ptr_t psave = std::make_shared<SettingsSaveData>();
-    psave->mType = settings->getSettingType();
-    psave->mSettings = settings;
-    psave->mTempFile = filename;
-    psave->mTransId = tid;
-
-    gAssetStorage->storeAssetData(filename, tid, LLAssetType::AT_SETTINGS,
-        [psave](const LLUUID &assetId, void *, S32 status, LLExtStat extstat) {
-            onSaveNewAssetComplete(assetId, psave, status, extstat);
-        },
-        nullptr);
-
-}
-
-void testingOnGotAsset(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)
-{
-    LL_WARNS("SETTINGS") << "Got back stored setting with id '" << asset_id << "' status is " << status << ":" << ext_status << LL_ENDL;
-}
-
-
-void LLSettingsVOBase::onSaveNewAssetComplete(const LLUUID& new_asset_id, const LLSettingsVOBase::SettingsSaveData::ptr_t &savedata, 
-        S32 status, LLExtStat ext_status)
-{
-    if (!status)
-    {
-        // Success
-        LL_INFOS("SETTINGS") << "Saved setting of type '" << savedata->mType << "' as " << new_asset_id << LL_ENDL;
-    }
-    else
-    {
-        LL_WARNS("SETTINGS") << "Unable to save '" << savedata->mType << "' to central asset store." << LL_ENDL;
-        LLSD args;
-        args["NAME"] = savedata->mType;
-        LLNotificationsUtil::add("CannotSaveToAssetStore", args);
-    }
-
-    gAssetStorage->getAssetData(new_asset_id, LLAssetType::AT_SETTINGS, &testingOnGotAsset, nullptr);
-
-    std::remove(savedata->mTempFile.c_str());
-}
-#endif
-
-
-void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings)
+void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings, inventory_result_fn callback)
 {
     LLTransactionID tid;
     LLUUID          parentFolder; //= gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
@@ -172,8 +111,8 @@ void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings
 
     tid.generate();
 
-    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([settings](const LLUUID &inventoryId) {
-            LLSettingsVOBase::onInventoryItemCreated(inventoryId, settings);
+    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([settings, callback](const LLUUID &inventoryId) {
+            LLSettingsVOBase::onInventoryItemCreated(inventoryId, settings, callback);
         });
 
     create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
@@ -182,14 +121,13 @@ void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings
         settings->getSettingTypeValue(), nextOwnerPerm, cb);
 }
 
-void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings)
+void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback)
 {
     // We need to update some inventory stuff here.... maybe.
-    uploadSettingsAsset(settings, inventoryId);
+    updateInventoryItem(settings, inventoryId, callback);
 }
 
-
-void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id)
+void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id, inventory_result_fn callback)
 {
     const LLViewerRegion* region = gAgent.getRegion();
     if (!region)
@@ -200,7 +138,7 @@ void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings
 
     std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
 
-    if (agent_url.empty())
+    if (!LLEnvironment::instance().isInventoryEnabled())
     {
         LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
         return;
@@ -211,14 +149,14 @@ void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings
     LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
 
     LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(), 
-        [settings](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
-            LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings);
+        [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
+            LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings, callback);
         });
 
     LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
 }
 
-void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id)
+void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id, inventory_result_fn callback)
 {
     const LLViewerRegion* region = gAgent.getRegion();
     if (!region)
@@ -229,7 +167,7 @@ void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings
 
     std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
 
-    if (agent_url.empty())
+    if (!LLEnvironment::instance().isInventoryEnabled())
     {
         LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
         return;
@@ -243,23 +181,71 @@ void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings
     LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
 
     LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(object_id, inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(),
-        [settings](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
-        LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings);
+        [settings, callback](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
+        LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings, callback);
     });
 
     LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
 }
 
-void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings)
+void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
 {
-    LL_WARNS("SETTINGS") << "Upload to inventory complete!" << LL_ENDL;
+    LL_WARNS("SETTINGS") << "itemId:" << itemId << " newAssetId:" << newAssetId << " newItemId:" << newItemId << " response:" << response << LL_ENDL;
+    if (callback)
+        callback( newAssetId, itemId, LLUUID::null, response );
 }
 
-void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings)
+void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
 {
     LL_WARNS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
+    if (callback)
+        callback(newAssetId, itemId, taskId, response);
 }
 
+
+void LLSettingsVOBase::getSettingsAsset(const LLUUID &assetId, LLSettingsVOBase::asset_download_fn callback)
+{
+    gAssetStorage->getAssetData(assetId, LLAssetType::AT_SETTINGS,
+        [callback](LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType, void *, S32 status, LLExtStat ext_status) 
+            { onAssetDownloadComplete(vfs, asset_id, status, ext_status, callback); },
+        nullptr, true);
+
+}
+
+void LLSettingsVOBase::onAssetDownloadComplete(LLVFS *vfs, const LLUUID &asset_id, S32 status, LLExtStat ext_status, LLSettingsVOBase::asset_download_fn callback)
+{
+    LLSettingsBase::ptr_t settings;
+    if (!status)
+    {
+        LLVFile file(vfs, asset_id, LLAssetType::AT_SETTINGS, LLVFile::READ);
+        S32 size = file.getSize();
+
+        std::string buffer(size + 1, '\0');
+        file.read((U8 *)buffer.data(), size);
+
+        std::stringstream llsdstream(buffer);
+        LLSD llsdsettings;
+
+        if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1))
+        {
+            settings = createFromLLSD(llsdsettings);
+        }
+
+        if (!settings)
+        {
+            status = 1;
+            LL_WARNS("SETTINGS") << "Unable to creat settings object." << LL_ENDL;
+        }
+
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "Error retrieving asset asset_id. Status code=" << status << " ext_status=" << ext_status << LL_ENDL;
+    }
+    callback(asset_id, settings, status, ext_status);
+}
+
+
 bool LLSettingsVOBase::exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format)
 {
     try
@@ -311,7 +297,18 @@ LLSettingsBase::ptr_t LLSettingsVOBase::importFile(const std::string &filename)
         return LLSettingsBase::ptr_t();
     }
 
-    std::string settingtype = settings[SETTING_NAME].asString();
+    return createFromLLSD(settings);
+}
+
+LLSettingsBase::ptr_t LLSettingsVOBase::createFromLLSD(const LLSD &settings)
+{
+    if (!settings.has(SETTING_TYPE))
+    {
+        LL_WARNS("SETTINGS") << "No settings type in LLSD" << LL_ENDL;
+        return LLSettingsBase::ptr_t();
+    }
+
+    std::string settingtype = settings[SETTING_TYPE].asString();
 
     LLSettingsBase::ptr_t psetting;
 
@@ -328,10 +325,10 @@ LLSettingsBase::ptr_t LLSettingsVOBase::importFile(const std::string &filename)
         return LLSettingsVODay::buildDay(settings);
     }
 
-    LL_WARNS("SETTINGS") << "Unable to determine settings type for '" << filename << "'." << LL_ENDL;
+    LL_WARNS("SETTINGS") << "Unable to determine settings type for '" << settingtype << "'." << LL_ENDL;
     return LLSettingsBase::ptr_t();
-}
 
+}
 
 //=========================================================================
 LLSettingsVOSky::LLSettingsVOSky(const LLSD &data, bool isAdvanced)
diff --git a/indra/newview/llsettingsvo.h b/indra/newview/llsettingsvo.h
index 3c47009d5f..3339aaf037 100644
--- a/indra/newview/llsettingsvo.h
+++ b/indra/newview/llsettingsvo.h
@@ -36,23 +36,27 @@
 #include "llsdserialize.h"
 
 #include "llextendedstatus.h"
+#include <boost/signals2.hpp>
+
+class LLVFS;
 
 //=========================================================================
 class LLSettingsVOBase : public LLSettingsBase
 {
 public:
-#if 0
-    static void     storeAsAsset(const LLSettingsBase::ptr_t &settings);
-#endif
+    typedef std::function<void(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status, LLExtStat extstat)>  asset_download_fn;
+    typedef std::function<void(LLUUID asset_id, LLUUID inventory_id, LLUUID object_id, LLSD results)>           inventory_result_fn;
 
-    static void     createInventoryItem(const LLSettingsBase::ptr_t &settings);
+    static void     createInventoryItem(const LLSettingsBase::ptr_t &settings, inventory_result_fn callback = inventory_result_fn());
     
-    static void     uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id);
-    static void     uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id);
+    static void     updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id, inventory_result_fn callback = inventory_result_fn());
+    static void     updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id, inventory_result_fn callback = inventory_result_fn());
 
+    static void     getSettingsAsset(const LLUUID &assetId, asset_download_fn callback);
 
     static bool     exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format = LLSDSerialize::LLSD_NOTATION);
     static LLSettingsBase::ptr_t importFile(const std::string &filename);
+    static LLSettingsBase::ptr_t createFromLLSD(const LLSD &settings);
 
 private:
     struct SettingsSaveData
@@ -66,13 +70,12 @@ private:
 
     LLSettingsVOBase() {}
 
-    static void     onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings);
+    static void     onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback);
 
-#if 0
-    static void     onSaveNewAssetComplete(const LLUUID& new_asset_id, const SettingsSaveData::ptr_t &savedata, S32 status, LLExtStat ext_status);
-#endif
-    static void     onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings);
-    static void     onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings);
+    static void     onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback);
+    static void     onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback);
+    
+    static void     onAssetDownloadComplete(LLVFS *vfs, const LLUUID &asset_id, S32 status, LLExtStat ext_status, asset_download_fn callback);
 };
 
 //=========================================================================
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 8665fb3234..ec457c1b5d 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -2035,6 +2035,19 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const
 	return LLWearableType::inventoryFlagsToWearableType(getFlags());
 }
 
+bool LLViewerInventoryItem::isSettingsType() const
+{
+    return (getInventoryType() == LLInventoryType::IT_SETTINGS);
+}
+
+LLSettingsType::type_e LLViewerInventoryItem::getSettingsType() const
+{
+    if (!isSettingsType())
+    {
+        return LLSettingsType::ST_NONE;
+    }
+    return LLSettingsType::fromInventoryFlags(getFlags());
+}
 
 time_t LLViewerInventoryItem::getCreationDate() const
 {
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index be100a764a..d537b28682 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -75,6 +75,9 @@ public:
 	virtual LLInventoryType::EType getInventoryType() const;
 	virtual bool isWearableType() const;
 	virtual LLWearableType::EType getWearableType() const;
+    virtual bool isSettingsType() const;
+    virtual LLSettingsType::type_e getSettingsType() const;
+
 	virtual U32 getFlags() const;
 	virtual time_t getCreationDate() const;
 	virtual U32 getCRC32() const; // really more of a checksum.
-- 
cgit v1.2.3