Merge branch 'DRTVWR-567' of https://github.com/secondlife/viewer
# Conflicts: # indra/llui/llfolderviewitem.cpp # indra/llui/llfolderviewitem.h # indra/newview/app_settings/settings.xml # indra/newview/llaisapi.cpp # indra/newview/llinventorybridge.cpp # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventorymodel.h # indra/newview/llinventorymodelbackgroundfetch.cpp # indra/newview/llinventorymodelbackgroundfetch.h # indra/newview/llsidepanelinventory.cpp # indra/newview/skins/default/xui/en/panel_main_inventory.xmlmaster
commit
2180c2a443
|
|
@ -44,6 +44,7 @@
|
|||
static const std::string INV_ITEM_ID_LABEL("item_id");
|
||||
static const std::string INV_FOLDER_ID_LABEL("cat_id");
|
||||
static const std::string INV_PARENT_ID_LABEL("parent_id");
|
||||
static const std::string INV_THUMBNAIL_LABEL("thumbnail");
|
||||
static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id");
|
||||
static const std::string INV_ASSET_TYPE_LABEL("type");
|
||||
static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
|
||||
|
|
@ -748,6 +749,26 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
|
|||
{
|
||||
mType = LLAssetType::lookup(valuestr);
|
||||
}
|
||||
else if (0 == strcmp("metadata", keyword))
|
||||
{
|
||||
LLSD metadata(valuestr);
|
||||
if (metadata.has("thumbnail"))
|
||||
{
|
||||
const LLSD& thumbnail = metadata["thumbnail"];
|
||||
if (thumbnail.has("asset_id"))
|
||||
{
|
||||
setThumbnailUUID(thumbnail["asset_id"].asUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
setThumbnailUUID(LLUUID::null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setThumbnailUUID(LLUUID::null);
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp("inv_type", keyword))
|
||||
{
|
||||
mInventoryType = LLInventoryType::lookup(std::string(valuestr));
|
||||
|
|
@ -837,6 +858,13 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu
|
|||
output_stream << "\t\tparent_id\t" << uuid_str << "\n";
|
||||
mPermissions.exportLegacyStream(output_stream);
|
||||
|
||||
if (mThumbnailUUID.notNull())
|
||||
{
|
||||
LLSD metadata;
|
||||
metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID);
|
||||
output_stream << "\t\tmetadata\t" << metadata << "|\n";
|
||||
}
|
||||
|
||||
// Check for permissions to see the asset id, and if so write it
|
||||
// out as an asset id. Otherwise, apply our cheesy encryption.
|
||||
if(include_asset_key)
|
||||
|
|
@ -890,6 +918,11 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
|
|||
sd[INV_PARENT_ID_LABEL] = mParentUUID;
|
||||
sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
|
||||
|
||||
if (mThumbnailUUID.notNull())
|
||||
{
|
||||
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
|
||||
}
|
||||
|
||||
U32 mask = mPermissions.getMaskBase();
|
||||
if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|
||||
|| (mAssetUUID.isNull()))
|
||||
|
|
@ -941,6 +974,35 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
|
|||
{
|
||||
mParentUUID = sd[w];
|
||||
}
|
||||
mThumbnailUUID.setNull();
|
||||
w = INV_THUMBNAIL_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
const LLSD &thumbnail_map = sd[w];
|
||||
w = INV_ASSET_ID_LABEL;
|
||||
if (thumbnail_map.has(w))
|
||||
{
|
||||
mThumbnailUUID = thumbnail_map[w];
|
||||
}
|
||||
/* Example:
|
||||
<key> asset_id </key>
|
||||
<uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid>
|
||||
<key> perms </key>
|
||||
<integer> 8 </integer>
|
||||
<key>service</key>
|
||||
<integer> 3 </integer>
|
||||
<key>version</key>
|
||||
<integer> 1 </key>
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
w = INV_THUMBNAIL_ID_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
mThumbnailUUID = sd[w].asUUID();
|
||||
}
|
||||
}
|
||||
w = INV_PERMISSIONS_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
|
|
@ -1116,11 +1178,15 @@ LLSD LLInventoryCategory::asLLSD() const
|
|||
LLSD sd = LLSD();
|
||||
sd["item_id"] = mUUID;
|
||||
sd["parent_id"] = mParentUUID;
|
||||
sd["thumbnail_id"] = mThumbnailUUID;
|
||||
S8 type = static_cast<S8>(mPreferredType);
|
||||
sd["type"] = type;
|
||||
sd["name"] = mName;
|
||||
|
||||
if (mThumbnailUUID.notNull())
|
||||
{
|
||||
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
|
||||
}
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
|
|
@ -1149,10 +1215,24 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
|
|||
{
|
||||
mParentUUID = sd[w];
|
||||
}
|
||||
w = INV_THUMBNAIL_ID_LABEL;
|
||||
mThumbnailUUID.setNull();
|
||||
w = INV_THUMBNAIL_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
mThumbnailUUID = sd[w];
|
||||
const LLSD &thumbnail_map = sd[w];
|
||||
w = INV_ASSET_ID_LABEL;
|
||||
if (thumbnail_map.has(w))
|
||||
{
|
||||
mThumbnailUUID = thumbnail_map[w];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
w = INV_THUMBNAIL_ID_LABEL;
|
||||
if (sd.has(w))
|
||||
{
|
||||
mThumbnailUUID = sd[w];
|
||||
}
|
||||
}
|
||||
w = INV_ASSET_TYPE_LABEL;
|
||||
if (sd.has(w))
|
||||
|
|
@ -1245,6 +1325,26 @@ BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
|
|||
LLStringUtil::replaceNonstandardASCII(mName, ' ');
|
||||
LLStringUtil::replaceChar(mName, '|', ' ');
|
||||
}
|
||||
else if (0 == strcmp("metadata", keyword))
|
||||
{
|
||||
LLSD metadata(valuestr);
|
||||
if (metadata.has("thumbnail"))
|
||||
{
|
||||
const LLSD& thumbnail = metadata["thumbnail"];
|
||||
if (thumbnail.has("asset_id"))
|
||||
{
|
||||
setThumbnailUUID(thumbnail["asset_id"].asUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
setThumbnailUUID(LLUUID::null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setThumbnailUUID(LLUUID::null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "unknown keyword '" << keyword
|
||||
|
|
@ -1265,6 +1365,12 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL)
|
|||
output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
|
||||
output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n";
|
||||
output_stream << "\t\tname\t" << mName.c_str() << "|\n";
|
||||
if (mThumbnailUUID.notNull())
|
||||
{
|
||||
LLSD metadata;
|
||||
metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID);
|
||||
output_stream << "\t\tmetadata\t" << metadata << "|\n";
|
||||
}
|
||||
output_stream << "\t}\n";
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1278,6 +1384,11 @@ LLSD LLInventoryCategory::exportLLSD() const
|
|||
cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
|
||||
cat_data[INV_NAME_LABEL] = mName;
|
||||
|
||||
if (mThumbnailUUID.notNull())
|
||||
{
|
||||
cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
|
||||
}
|
||||
|
||||
return cat_data;
|
||||
}
|
||||
|
||||
|
|
@ -1299,6 +1410,16 @@ bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
|
|||
{
|
||||
setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
|
||||
}
|
||||
LLUUID thumbnail_uuid;
|
||||
if (cat_data.has(INV_THUMBNAIL_LABEL))
|
||||
{
|
||||
const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
|
||||
if (thumbnail_data.has(INV_ASSET_ID_LABEL))
|
||||
{
|
||||
thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
|
||||
}
|
||||
}
|
||||
setThumbnailUUID(thumbnail_uuid);
|
||||
if (cat_data.has(INV_NAME_LABEL))
|
||||
{
|
||||
mName = cat_data[INV_NAME_LABEL].asString();
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ LLFolderViewItem::Params::Params()
|
|||
text_pad("text_pad", 0),
|
||||
text_pad_right("text_pad_right", 0),
|
||||
single_folder_mode("single_folder_mode", false),
|
||||
double_click_override("double_click_override", false),
|
||||
arrow_size("arrow_size", 0),
|
||||
max_folder_item_overlap("max_folder_item_overlap", 0),
|
||||
// <FS:Ansariel> Inventory specials
|
||||
|
|
@ -161,9 +162,10 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
|
|||
mArrowSize(p.arrow_size),
|
||||
mSingleFolderMode(p.single_folder_mode),
|
||||
mMaxFolderItemOverlap(p.max_folder_item_overlap),
|
||||
// <FS:Ansariel> Inventory specials
|
||||
mForInventory(p.for_inventory),
|
||||
mItemTopPad(p.item_top_pad)
|
||||
mDoubleClickOverride(p.double_click_override),
|
||||
// <FS:Ansariel> Inventory specials
|
||||
mForInventory(p.for_inventory),
|
||||
mItemTopPad(p.item_top_pad)
|
||||
{
|
||||
if (!sColorSetInitialized)
|
||||
{
|
||||
|
|
@ -2192,16 +2194,19 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
|
|||
}
|
||||
if( !handled )
|
||||
{
|
||||
static LLUICachedControl<U32> double_click_action("MultiModeDoubleClickFolder", false);
|
||||
if (double_click_action == 1)
|
||||
if(mDoubleClickOverride)
|
||||
{
|
||||
getViewModelItem()->navigateToFolder(true);
|
||||
return TRUE;
|
||||
}
|
||||
if (double_click_action == 2)
|
||||
{
|
||||
getViewModelItem()->navigateToFolder(false, true);
|
||||
return TRUE;
|
||||
static LLUICachedControl<U32> double_click_action("MultiModeDoubleClickFolder", false);
|
||||
if (double_click_action == 1)
|
||||
{
|
||||
getViewModelItem()->navigateToFolder(true);
|
||||
return TRUE;
|
||||
}
|
||||
if (double_click_action == 2)
|
||||
{
|
||||
getViewModelItem()->navigateToFolder(false, true);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ public:
|
|||
text_pad_right,
|
||||
arrow_size,
|
||||
max_folder_item_overlap;
|
||||
Optional<bool> single_folder_mode;
|
||||
Optional<bool> single_folder_mode,
|
||||
double_click_override;
|
||||
|
||||
// <FS:Ansariel> Inventory specials
|
||||
Optional<bool> for_inventory;
|
||||
|
|
@ -127,6 +128,7 @@ protected:
|
|||
mAllowWear,
|
||||
mAllowDrop,
|
||||
mSingleFolderMode,
|
||||
mDoubleClickOverride,
|
||||
mSelectPending,
|
||||
mIsItemCut;
|
||||
|
||||
|
|
|
|||
|
|
@ -539,6 +539,15 @@ void LLUICtrl::setControlVariable(LLControlVariable* control)
|
|||
}
|
||||
}
|
||||
|
||||
void LLUICtrl::removeControlVariable()
|
||||
{
|
||||
if (mControlVariable)
|
||||
{
|
||||
mControlConnection.disconnect();
|
||||
mControlVariable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ public:
|
|||
bool setControlValue(const LLSD& value);
|
||||
void setControlVariable(LLControlVariable* control);
|
||||
virtual void setControlName(const std::string& control, LLView *context = NULL);
|
||||
void removeControlVariable();
|
||||
|
||||
LLControlVariable* getControlVariable() { return mControlVariable; }
|
||||
// <FS:Ansariel> Accessors for other ControlVariables
|
||||
|
|
|
|||
|
|
@ -534,11 +534,10 @@ bool FloaterAO::newSetCallback(const LLSD& notification, const LLSD& response)
|
|||
|
||||
if (option == 0)
|
||||
{
|
||||
if (AOEngine::instance().addSet(newSetName).notNull())
|
||||
return AOEngine::instance().addSet(newSetName, [this](const LLUUID& new_cat_id)
|
||||
{
|
||||
reloading(true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
#include "llnotificationsutil.h"
|
||||
#include "llstring.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewerinventory.h"
|
||||
|
||||
#define ROOT_AO_FOLDER "#AO"
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
|
|
@ -978,26 +977,30 @@ void AOEngine::updateSortOrder(AOSet::AOState* state)
|
|||
}
|
||||
}
|
||||
|
||||
LLUUID AOEngine::addSet(const std::string& name, bool reload)
|
||||
bool AOEngine::addSet(const std::string& name, inventory_func_type callback, bool reload)
|
||||
{
|
||||
if (mAOFolder.isNull())
|
||||
{
|
||||
LL_WARNS("AOEngine") << ROOT_AO_FOLDER << " folder not there yet. Requesting recreation." << LL_ENDL;
|
||||
tick();
|
||||
return LLUUID::null;
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL wasProtected = gSavedPerAccountSettings.getBOOL("LockAOFolders");
|
||||
gSavedPerAccountSettings.setBOOL("LockAOFolders", FALSE);
|
||||
LL_DEBUGS("AOEngine") << "adding set folder " << name << LL_ENDL;
|
||||
LLUUID newUUID = gInventory.createNewCategory(mAOFolder, LLFolderType::FT_NONE, name);
|
||||
gSavedPerAccountSettings.setBOOL("LockAOFolders", wasProtected);
|
||||
|
||||
if (reload)
|
||||
gInventory.createNewCategory(mAOFolder, LLFolderType::FT_NONE, name, [callback, wasProtected, reload, this](const LLUUID &new_cat_id)
|
||||
{
|
||||
mTimerCollection.enableReloadTimer(true);
|
||||
}
|
||||
return newUUID;
|
||||
gSavedPerAccountSettings.setBOOL("LockAOFolders", wasProtected);
|
||||
|
||||
if (reload)
|
||||
{
|
||||
mTimerCollection.enableReloadTimer(true);
|
||||
}
|
||||
|
||||
callback(new_cat_id);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AOEngine::createAnimationLink(const AOSet* set, AOSet::AOState* state, const LLInventoryItem* item)
|
||||
|
|
@ -2177,8 +2180,51 @@ void AOEngine::processImport(bool from_timer)
|
|||
{
|
||||
if (mImportCategory.isNull())
|
||||
{
|
||||
mImportCategory = addSet(mImportSet->getName(), false);
|
||||
if (mImportCategory.isNull())
|
||||
bool success = addSet(mImportSet->getName(), [this, from_timer](const LLUUID& new_cat_id)
|
||||
{
|
||||
mImportCategory = new_cat_id;
|
||||
mImportSet->setInventoryUUID(mImportCategory);
|
||||
|
||||
bool allComplete = true;
|
||||
for (S32 index = 0; index < AOSet::AOSTATES_MAX; ++index)
|
||||
{
|
||||
AOSet::AOState* state = mImportSet->getState(index);
|
||||
if (state->mAnimations.size())
|
||||
{
|
||||
allComplete = false;
|
||||
LL_DEBUGS("AOEngine") << "state " << state->mName << " still has animations to link." << LL_ENDL;
|
||||
|
||||
for (S32 animationIndex = state->mAnimations.size() - 1; animationIndex >= 0; --animationIndex)
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "linking animation " << state->mAnimations[animationIndex].mName << LL_ENDL;
|
||||
if (createAnimationLink(mImportSet, state, gInventory.getItem(state->mAnimations[animationIndex].mInventoryUUID)))
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "link success, size " << state->mAnimations.size() << ", removing animation "
|
||||
<< (*(state->mAnimations.begin() + animationIndex)).mName << " from import state" << LL_ENDL;
|
||||
state->mAnimations.erase(state->mAnimations.begin() + animationIndex);
|
||||
LL_DEBUGS("AOEngine") << "deleted, size now: " << state->mAnimations.size() << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSD args;
|
||||
args["NAME"] = state->mAnimations[animationIndex].mName;
|
||||
LLNotificationsUtil::add("AOImportLinkFailed", args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allComplete)
|
||||
{
|
||||
mTimerCollection.enableImportTimer(false);
|
||||
mOldImportSets.push_back(mImportSet); //<ND/> FIRE-3801; Cannot delete here, or LLInstanceTracker gets upset. Just remember and delete mOldImportSets once we can.
|
||||
mImportSet = nullptr;
|
||||
mImportCategory.setNull();
|
||||
reload(from_timer);
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
mImportRetryCount++;
|
||||
if (mImportRetryCount == 5)
|
||||
|
|
@ -2199,47 +2245,7 @@ void AOEngine::processImport(bool from_timer)
|
|||
args["NAME"] = mImportSet->getName();
|
||||
LLNotificationsUtil::add("AOImportRetryCreateSet", args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
mImportSet->setInventoryUUID(mImportCategory);
|
||||
}
|
||||
|
||||
bool allComplete = true;
|
||||
for (S32 index = 0; index < AOSet::AOSTATES_MAX; ++index)
|
||||
{
|
||||
AOSet::AOState* state = mImportSet->getState(index);
|
||||
if (state->mAnimations.size())
|
||||
{
|
||||
allComplete = false;
|
||||
LL_DEBUGS("AOEngine") << "state " << state->mName << " still has animations to link." << LL_ENDL;
|
||||
|
||||
for (S32 animationIndex = state->mAnimations.size() - 1; animationIndex >= 0; --animationIndex)
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "linking animation " << state->mAnimations[animationIndex].mName << LL_ENDL;
|
||||
if (createAnimationLink(mImportSet, state, gInventory.getItem(state->mAnimations[animationIndex].mInventoryUUID)))
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "link success, size "<< state->mAnimations.size() << ", removing animation "
|
||||
<< (*(state->mAnimations.begin() + animationIndex)).mName << " from import state" << LL_ENDL;
|
||||
state->mAnimations.erase(state->mAnimations.begin() + animationIndex);
|
||||
LL_DEBUGS("AOEngine") << "deleted, size now: " << state->mAnimations.size() << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSD args;
|
||||
args["NAME"] = state->mAnimations[animationIndex].mName;
|
||||
LLNotificationsUtil::add("AOImportLinkFailed", args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allComplete)
|
||||
{
|
||||
mTimerCollection.enableImportTimer(false);
|
||||
mOldImportSets.push_back(mImportSet); //<ND/> FIRE-3801; Cannot delete here, or LLInstanceTracker gets upset. Just remember and delete mOldImportSets once we can.
|
||||
mImportSet = nullptr;
|
||||
mImportCategory.setNull();
|
||||
reload(from_timer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "lleventtimer.h"
|
||||
#include "llextendedstatus.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llviewerinventory.h"
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
class AOTimerCollection
|
||||
|
|
@ -105,7 +106,7 @@ class AOEngine
|
|||
|
||||
const LLUUID& getAOFolder() const;
|
||||
|
||||
LLUUID addSet(const std::string& name, bool reload = true);
|
||||
bool addSet(const std::string& name, inventory_func_type callback, bool reload = true);
|
||||
bool removeSet(AOSet* set);
|
||||
|
||||
bool addAnimation(const AOSet* set, AOSet::AOState* state, const LLInventoryItem* item, bool reload = true);
|
||||
|
|
|
|||
|
|
@ -7226,17 +7226,6 @@
|
|||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>InventoryInboxToggleState</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Stores the open/closed state of inventory Received items panel</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>InventoryLinking</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -152,35 +152,42 @@ void FSFloaterWearableFavorites::onOpen(const LLSD& /*info*/)
|
|||
{
|
||||
if (sFolderID.isNull())
|
||||
{
|
||||
initCategory();
|
||||
initCategory(boost::bind(&FSFloaterWearableFavorites::initialize, this));
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* category = gInventory.getCategory(sFolderID);
|
||||
if (!category)
|
||||
else
|
||||
{
|
||||
return;
|
||||
initialize();
|
||||
}
|
||||
|
||||
const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
LLViewerInventoryCategory* category_cof = gInventory.getCategory(cof);
|
||||
if (!category_cof)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gInventory.addObserver(mCategoriesObserver);
|
||||
mCategoriesObserver->addCategory(sFolderID, boost::bind(&FSFloaterWearableFavorites::updateList, this, sFolderID));
|
||||
mCategoriesObserver->addCategory(cof, boost::bind(&FSFloaterWearableFavorites::updateList, this, sFolderID));
|
||||
category->fetch();
|
||||
|
||||
mItemsList->setSortOrder((LLWearableItemsList::ESortOrder)gSavedSettings.getU32("FSWearableFavoritesSortOrder"));
|
||||
updateList(sFolderID);
|
||||
mItemsList->setDADCallback(boost::bind(&FSFloaterWearableFavorites::onItemDAD, this, _1));
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterWearableFavorites::initialize()
|
||||
{
|
||||
LLViewerInventoryCategory* category = gInventory.getCategory(sFolderID);
|
||||
if (!category)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
LLViewerInventoryCategory* category_cof = gInventory.getCategory(cof);
|
||||
if (!category_cof)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gInventory.addObserver(mCategoriesObserver);
|
||||
mCategoriesObserver->addCategory(sFolderID, boost::bind(&FSFloaterWearableFavorites::updateList, this, sFolderID));
|
||||
mCategoriesObserver->addCategory(cof, boost::bind(&FSFloaterWearableFavorites::updateList, this, sFolderID));
|
||||
category->fetch();
|
||||
|
||||
mItemsList->setSortOrder((LLWearableItemsList::ESortOrder)gSavedSettings.getU32("FSWearableFavoritesSortOrder"));
|
||||
updateList(sFolderID);
|
||||
mItemsList->setDADCallback(boost::bind(&FSFloaterWearableFavorites::onItemDAD, this, _1));
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void FSFloaterWearableFavorites::draw()
|
||||
{
|
||||
|
|
@ -226,7 +233,7 @@ std::optional<LLUUID> FSFloaterWearableFavorites::getWearableFavoritesFolderID()
|
|||
}
|
||||
|
||||
// static
|
||||
void FSFloaterWearableFavorites::initCategory()
|
||||
void FSFloaterWearableFavorites::initCategory(inventory_func_type callback)
|
||||
{
|
||||
if (!gInventory.isInventoryUsable())
|
||||
{
|
||||
|
|
@ -237,16 +244,30 @@ void FSFloaterWearableFavorites::initCategory()
|
|||
if (auto fs_favs_id = getWearableFavoritesFolderID(); fs_favs_id.has_value())
|
||||
{
|
||||
sFolderID = fs_favs_id.value();
|
||||
callback(sFolderID);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID fs_root_cat_id = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER);
|
||||
if (fs_root_cat_id.isNull())
|
||||
{
|
||||
fs_root_cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER);
|
||||
gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER, [callback](const LLUUID& new_cat_id)
|
||||
{
|
||||
gInventory.createNewCategory(new_cat_id, LLFolderType::FT_NONE, FS_WEARABLE_FAVORITES_FOLDER, [callback](const LLUUID& new_cat_id)
|
||||
{
|
||||
FSFloaterWearableFavorites::sFolderID = new_cat_id;
|
||||
callback(new_cat_id);
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.createNewCategory(fs_root_cat_id, LLFolderType::FT_NONE, FS_WEARABLE_FAVORITES_FOLDER, [callback](const LLUUID& new_cat_id)
|
||||
{
|
||||
FSFloaterWearableFavorites::sFolderID = new_cat_id;
|
||||
callback(new_cat_id);
|
||||
});
|
||||
}
|
||||
|
||||
sFolderID = gInventory.createNewCategory(fs_root_cat_id, LLFolderType::FT_NONE, FS_WEARABLE_FAVORITES_FOLDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#define FS_FLOATERWEARABLEFAVORITES_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llviewerinventory.h"
|
||||
#include "llwearableitemslist.h"
|
||||
#include <optional>
|
||||
|
||||
|
|
@ -79,10 +80,14 @@ public:
|
|||
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
|
||||
/*virtual*/ bool hasAccelerators() const { return true; }
|
||||
|
||||
static void initCategory();
|
||||
static void initCategory(inventory_func_type callback = no_op_inventory_func);
|
||||
static LLUUID getFavoritesFolder();
|
||||
|
||||
static LLUUID sFolderID;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
void updateList(const LLUUID& folder_id);
|
||||
|
||||
void onItemDAD(const LLUUID& item_id);
|
||||
|
|
@ -106,8 +111,6 @@ private:
|
|||
LLFilterEditor* mFilterEditor;
|
||||
LLMenuButton* mOptionsButton;
|
||||
LLHandle<LLView> mOptionsMenuHandle;
|
||||
|
||||
static LLUUID sFolderID;
|
||||
};
|
||||
|
||||
#endif // FS_FLOATERWEARABLEFAVORITES_H
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ private:
|
|||
FSLSLBridge::FSLSLBridge():
|
||||
mBridgeCreating(false),
|
||||
mpBridge(nullptr),
|
||||
mBridgeFolderID(LLUUID::null),
|
||||
mIsFirstCallDone(false),
|
||||
mAllowDetach(false),
|
||||
mFinishCreation(false),
|
||||
|
|
@ -176,7 +177,7 @@ bool FSLSLBridge::lslToViewer(std::string_view message, const LLUUID& fromID, co
|
|||
return false;
|
||||
}
|
||||
std::string_view tag = message.substr(0, tagend + 1);
|
||||
std::string ourBridge = findFSCategory().asString();
|
||||
std::string ourBridge = getBridgeFolder().asString();
|
||||
//</FS:TS> FIRE-962
|
||||
|
||||
bool bridgeIsEnabled = gSavedSettings.getBOOL("UseLSLBridge");
|
||||
|
|
@ -213,7 +214,7 @@ bool FSLSLBridge::lslToViewer(std::string_view message, const LLUUID& fromID, co
|
|||
|
||||
|
||||
// If something that looks like our current bridge is attached but failed auth, detach and recreate.
|
||||
const LLUUID catID = findFSCategory();
|
||||
const LLUUID catID = getBridgeFolder();
|
||||
LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID);
|
||||
if (fsBridge && get_is_item_worn(fsBridge->getUUID()))
|
||||
{
|
||||
|
|
@ -251,7 +252,7 @@ bool FSLSLBridge::lslToViewer(std::string_view message, const LLUUID& fromID, co
|
|||
|
||||
if (!mpBridge)
|
||||
{
|
||||
LLUUID catID = findFSCategory();
|
||||
LLUUID catID = getBridgeFolder();
|
||||
LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID);
|
||||
mpBridge = fsBridge;
|
||||
}
|
||||
|
|
@ -642,7 +643,7 @@ void FSLSLBridge::recreateBridge()
|
|||
//announce yourself
|
||||
report_to_nearby_chat(LLTrans::getString("fsbridge_creating"));
|
||||
|
||||
LLUUID catID = findFSCategory();
|
||||
LLUUID catID = getBridgeFolder();
|
||||
|
||||
FSLSLBridgeInventoryPreCreationCleanupObserver* bridgeInventoryObserver = new FSLSLBridgeInventoryPreCreationCleanupObserver(catID);
|
||||
bridgeInventoryObserver->startFetch();
|
||||
|
|
@ -663,7 +664,7 @@ void FSLSLBridge::cleanUpPreCreation()
|
|||
LLInventoryModel::cat_array_t cats;
|
||||
LLInventoryModel::item_array_t items;
|
||||
NameCollectFunctor namefunctor(mCurrentFullName);
|
||||
gInventory.collectDescendentsIf(findFSCategory(), cats, items, FALSE, namefunctor);
|
||||
gInventory.collectDescendentsIf(getBridgeFolder(), cats, items, FALSE, namefunctor);
|
||||
|
||||
mAllowedDetachables.clear();
|
||||
for (const auto& item : items)
|
||||
|
|
@ -699,7 +700,7 @@ void FSLSLBridge::finishCleanUpPreCreation()
|
|||
LLInventoryModel::cat_array_t cats;
|
||||
LLInventoryModel::item_array_t items;
|
||||
NameCollectFunctor namefunctor(mCurrentFullName);
|
||||
gInventory.collectDescendentsIf(findFSCategory(), cats, items, FALSE, namefunctor);
|
||||
gInventory.collectDescendentsIf(getBridgeFolder(), cats, items, FALSE, namefunctor);
|
||||
|
||||
for (const auto& item : items)
|
||||
{
|
||||
|
|
@ -743,26 +744,26 @@ void FSLSLBridge::initBridge()
|
|||
return;
|
||||
}
|
||||
|
||||
LLUUID catID = findFSCategory();
|
||||
LLUUID libCatID = findFSBridgeContainerCategory();
|
||||
setupFSCategory([this](const LLUUID& bridge_folder_id)
|
||||
{
|
||||
LLUUID libCatID = findFSBridgeContainerCategory();
|
||||
|
||||
//check for inventory load
|
||||
// AH: Use overloaded LLInventoryFetchDescendentsObserver to check for load of
|
||||
// bridge and bridge rock category before doing anything!
|
||||
LL_INFOS("FSLSLBridge") << "initBridge called. gInventory.isInventoryUsable = " << (gInventory.isInventoryUsable() ? "true" : "false") << LL_ENDL;
|
||||
uuid_vec_t cats;
|
||||
cats.push_back(catID);
|
||||
cats.push_back(libCatID);
|
||||
FSLSLBridgeInventoryObserver* bridgeInventoryObserver = new FSLSLBridgeInventoryObserver(cats);
|
||||
bridgeInventoryObserver->startFetch();
|
||||
if (bridgeInventoryObserver->isFinished())
|
||||
{
|
||||
bridgeInventoryObserver->done();
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.addObserver(bridgeInventoryObserver);
|
||||
}
|
||||
//check for inventory load
|
||||
// AH: Use overloaded LLInventoryFetchDescendentsObserver to check for load of
|
||||
// bridge and bridge rock category before doing anything!
|
||||
LL_INFOS("FSLSLBridge") << "initBridge called. gInventory.isInventoryUsable = " << (gInventory.isInventoryUsable() ? "true" : "false") << LL_ENDL;
|
||||
uuid_vec_t cats{ bridge_folder_id, libCatID };
|
||||
FSLSLBridgeInventoryObserver* bridgeInventoryObserver = new FSLSLBridgeInventoryObserver(cats);
|
||||
bridgeInventoryObserver->startFetch();
|
||||
if (bridgeInventoryObserver->isFinished())
|
||||
{
|
||||
bridgeInventoryObserver->done();
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.addObserver(bridgeInventoryObserver);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -786,7 +787,7 @@ void FSLSLBridge::startCreation()
|
|||
LL_INFOS("FSLSLBridge") << "startCreation called. gInventory.isInventoryUsable = " << (gInventory.isInventoryUsable() ? "true" : "false") << LL_ENDL;
|
||||
|
||||
//if bridge object doesn't exist - create and attach it, update script.
|
||||
const LLUUID catID = findFSCategory();
|
||||
const LLUUID catID = getBridgeFolder();
|
||||
LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID);
|
||||
|
||||
//detach everything else
|
||||
|
|
@ -836,7 +837,7 @@ void FSLSLBridge::startCreation()
|
|||
void FSLSLBridge::createNewBridge()
|
||||
{
|
||||
//check if user has a bridge
|
||||
const LLUUID catID = findFSCategory();
|
||||
const LLUUID catID = getBridgeFolder();
|
||||
|
||||
//attach the Linden rock from the library (will resize as soon as attached)
|
||||
const LLUUID libID = gInventory.getLibraryRootFolderID();
|
||||
|
|
@ -1193,7 +1194,7 @@ void FSLSLBridge::create_script_inner()
|
|||
return;
|
||||
}
|
||||
|
||||
const LLUUID catID = findFSCategory();
|
||||
const LLUUID catID = getBridgeFolder();
|
||||
|
||||
LLPointer<LLInventoryCallback> cb = new FSLSLBridgeScriptCallback();
|
||||
create_inventory_item(gAgentID,
|
||||
|
|
@ -1378,7 +1379,7 @@ std::string FSLSLBridgeScriptCallback::prepUploadFile(std::string &aBuffer)
|
|||
LL_WARNS("FSLSLBridge") << "Invalid bridge script" << LL_ENDL;
|
||||
return std::string();
|
||||
}
|
||||
aBuffer.replace(pos, bridgekey.length(), FSLSLBridge::getInstance()->findFSCategory().asString());
|
||||
aBuffer.replace(pos, bridgekey.length(), FSLSLBridge::getInstance()->getBridgeFolder().asString());
|
||||
|
||||
LLFILE *fpOut = LLFile::fopen(fNew, "wt");
|
||||
if (!fpOut)
|
||||
|
|
@ -1483,18 +1484,9 @@ bool FSLSLBridge::isItemAttached(const LLUUID& iID)
|
|||
return (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(iID));
|
||||
}
|
||||
|
||||
LLUUID FSLSLBridge::findFSCategory()
|
||||
void FSLSLBridge::setupFSCategory(inventory_func_type callback)
|
||||
{
|
||||
if (!mBridgeFolderID.isNull())
|
||||
{
|
||||
return mBridgeFolderID;
|
||||
}
|
||||
|
||||
LLUUID fsCatID;
|
||||
LLUUID bridgeCatID;
|
||||
|
||||
fsCatID = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER);
|
||||
if (!fsCatID.isNull())
|
||||
if (LLUUID fsCatID = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER); !fsCatID.isNull())
|
||||
{
|
||||
LLInventoryModel::item_array_t* items;
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
|
|
@ -1505,25 +1497,64 @@ LLUUID FSLSLBridge::findFSCategory()
|
|||
{
|
||||
if (cat->getName() == FS_BRIDGE_FOLDER)
|
||||
{
|
||||
bridgeCatID = cat->getUUID();
|
||||
break;
|
||||
mBridgeFolderID = cat->getUUID();
|
||||
callback(mBridgeFolderID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gInventory.createNewCategory(fsCatID, LLFolderType::FT_NONE, FS_BRIDGE_FOLDER, [this, callback](const LLUUID& new_cat_id)
|
||||
{
|
||||
mBridgeFolderID = new_cat_id;
|
||||
callback(mBridgeFolderID);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER, [this, callback](const LLUUID& new_cat_id)
|
||||
{
|
||||
gInventory.createNewCategory(new_cat_id, LLFolderType::FT_NONE, FS_BRIDGE_FOLDER, [this, callback](const LLUUID& new_cat_id)
|
||||
{
|
||||
mBridgeFolderID = new_cat_id;
|
||||
callback(mBridgeFolderID);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This used to be the place where the bridge folder was also created before it got moved to setupFSCategory.
|
||||
// We still need this method because it is used in processAttach / processDetach, which (unfortunately) might be called
|
||||
// before initBridge is called that sets up the bridge folder. But since apparently a bridge is already attached,
|
||||
// we can assume the folder already exists and we do not need to create it here anymore. And if something is attached
|
||||
// to where we attach the bridge and also has the same name as the bridge but is in a different folder, it won't make
|
||||
// any difference if we return the actual category ID or a null UUID for the check performed in processAttach.
|
||||
LLUUID FSLSLBridge::findFSCategory()
|
||||
{
|
||||
if (!mBridgeFolderID.isNull())
|
||||
{
|
||||
return mBridgeFolderID;
|
||||
}
|
||||
|
||||
if (LLUUID fsCatID = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER); !fsCatID.isNull())
|
||||
{
|
||||
LLInventoryModel::item_array_t* items;
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
gInventory.getDirectDescendentsOf(fsCatID, cats, items);
|
||||
if (cats)
|
||||
{
|
||||
for (const auto& cat : *cats)
|
||||
{
|
||||
if (cat->getName() == FS_BRIDGE_FOLDER)
|
||||
{
|
||||
mBridgeFolderID = cat->getUUID();
|
||||
return mBridgeFolderID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fsCatID = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER);
|
||||
}
|
||||
|
||||
if (bridgeCatID.isNull())
|
||||
{
|
||||
bridgeCatID = gInventory.createNewCategory(fsCatID, LLFolderType::FT_NONE, FS_BRIDGE_FOLDER);
|
||||
}
|
||||
|
||||
mBridgeFolderID = bridgeCatID;
|
||||
|
||||
return mBridgeFolderID;
|
||||
return LLUUID::null;
|
||||
}
|
||||
|
||||
LLUUID FSLSLBridge::findFSBridgeContainerCategory()
|
||||
|
|
@ -1613,7 +1644,7 @@ void FSLSLBridge::cleanUpBridgeFolder(const std::string& nameToCleanUp)
|
|||
return;
|
||||
}
|
||||
|
||||
LLUUID catID = findFSCategory();
|
||||
LLUUID catID = getBridgeFolder();
|
||||
LLViewerInventoryCategory::cat_array_t cats;
|
||||
LLViewerInventoryItem::item_array_t items;
|
||||
|
||||
|
|
@ -1665,7 +1696,7 @@ void FSLSLBridge::cleanUpOldVersions()
|
|||
|
||||
void FSLSLBridge::detachOtherBridges()
|
||||
{
|
||||
LLUUID catID = findFSCategory();
|
||||
LLUUID catID = getBridgeFolder();
|
||||
LLViewerInventoryCategory::cat_array_t cats;
|
||||
LLViewerInventoryItem::item_array_t items;
|
||||
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ private:
|
|||
|
||||
protected:
|
||||
LLViewerInventoryItem* findInvObject(const std::string& obj_name, const LLUUID& catID);
|
||||
void setupFSCategory(inventory_func_type callback);
|
||||
LLUUID findFSCategory();
|
||||
LLUUID findFSBridgeContainerCategory();
|
||||
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ void LLLibraryOutfitsFetch::folderDone()
|
|||
}
|
||||
|
||||
mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
|
||||
mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);
|
||||
mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING);
|
||||
|
||||
// If Library->Clothing->Initial Outfits exists, use that.
|
||||
LLNameCategoryCollector matchFolderFunctor("Initial Outfits");
|
||||
|
|
@ -461,46 +461,50 @@ void LLLibraryOutfitsFetch::libraryDone()
|
|||
gInventory.removeObserver(this);
|
||||
|
||||
LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this);
|
||||
mImportedClothingID = gInventory.createNewCategory(mClothingID,
|
||||
LLFolderType::FT_NONE,
|
||||
mImportedClothingName);
|
||||
// Copy each folder from library into clothing unless it already exists.
|
||||
for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
|
||||
iter != mLibraryClothingFolders.end();
|
||||
++iter)
|
||||
{
|
||||
const LLUUID& src_folder_id = (*iter); // Library clothing folder ID
|
||||
const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id);
|
||||
if (!cat)
|
||||
gInventory.createNewCategory(mClothingID, LLFolderType::FT_NONE,
|
||||
mImportedClothingName, [this, copy_waiter](const LLUUID& new_cat_id)
|
||||
{
|
||||
LL_WARNS() << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
mImportedClothingID = new_cat_id;
|
||||
// Copy each folder from library into clothing unless it already exists.
|
||||
for (uuid_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
|
||||
iter != mLibraryClothingFolders.end();
|
||||
++iter)
|
||||
{
|
||||
const LLUUID& src_folder_id = (*iter); // Library clothing folder ID
|
||||
const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id);
|
||||
if (!cat)
|
||||
{
|
||||
LL_WARNS() << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id))
|
||||
{
|
||||
LL_INFOS() << "Skipping non-outfit folder name:" << cat->getName() << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id))
|
||||
{
|
||||
LL_INFOS() << "Skipping non-outfit folder name:" << cat->getName() << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't copy the category if it already exists.
|
||||
LLNameCategoryCollector matchFolderFunctor(cat->getName());
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t wearable_array;
|
||||
gInventory.collectDescendentsIf(mImportedClothingID,
|
||||
cat_array, wearable_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
matchFolderFunctor);
|
||||
if (cat_array.size() > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Don't copy the category if it already exists.
|
||||
LLNameCategoryCollector matchFolderFunctor(cat->getName());
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t wearable_array;
|
||||
gInventory.collectDescendentsIf(mImportedClothingID,
|
||||
cat_array, wearable_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
matchFolderFunctor);
|
||||
if (cat_array.size() > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID,
|
||||
LLFolderType::FT_NONE,
|
||||
cat->getName());
|
||||
LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter);
|
||||
}
|
||||
gInventory.createNewCategory(mImportedClothingID,
|
||||
LLFolderType::FT_NONE,
|
||||
cat->getName(),
|
||||
[src_folder_id, copy_waiter](const LLUUID& new_cat_id) {
|
||||
LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, new_cat_id, copy_waiter);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LLLibraryOutfitsFetch::importedFolderFetch()
|
||||
|
|
@ -556,8 +560,6 @@ void LLLibraryOutfitsFetch::contentsDone()
|
|||
{
|
||||
LL_INFOS() << "start" << LL_ENDL;
|
||||
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t wearable_array;
|
||||
|
||||
LLPointer<LLInventoryCallback> order_myoutfits_on_destroy = new LLBoostFuncInventoryCallback(no_op_inventory_func, order_my_outfits_cb);
|
||||
|
||||
|
|
@ -577,24 +579,26 @@ void LLLibraryOutfitsFetch::contentsDone()
|
|||
if (cat->getName() == LLStartUp::getInitialOutfitName()) continue;
|
||||
|
||||
// First, make a folder in the My Outfits directory.
|
||||
LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName());
|
||||
|
||||
cat_array.clear();
|
||||
wearable_array.clear();
|
||||
// Collect the contents of each imported clothing folder, so we can create new outfit links for it
|
||||
gInventory.collectDescendents(folder_id, cat_array, wearable_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
|
||||
LLInventoryObject::const_object_list_t item_array;
|
||||
for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
|
||||
wearable_iter != wearable_array.end();
|
||||
++wearable_iter)
|
||||
gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName(), [folder_id, order_myoutfits_on_destroy](const LLUUID&)
|
||||
{
|
||||
LLConstPointer<LLInventoryObject> item = wearable_iter->get();
|
||||
item_array.push_back(item);
|
||||
}
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t wearable_array;
|
||||
|
||||
link_inventory_array(LLAppearanceMgr::instance().getCOF(), item_array, order_myoutfits_on_destroy);
|
||||
// Collect the contents of each imported clothing folder, so we can create new outfit links for it
|
||||
gInventory.collectDescendents(folder_id, cat_array, wearable_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
|
||||
LLInventoryObject::const_object_list_t item_array;
|
||||
for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
|
||||
wearable_iter != wearable_array.end();
|
||||
++wearable_iter)
|
||||
{
|
||||
LLConstPointer<LLInventoryObject> item = wearable_iter->get();
|
||||
item_array.push_back(item);
|
||||
}
|
||||
|
||||
link_inventory_array(LLAppearanceMgr::instance().getCOF(), item_array, order_myoutfits_on_destroy);
|
||||
});
|
||||
}
|
||||
|
||||
mOutfitsPopulated = true;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "llinventorymodel.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
|
|
@ -98,6 +100,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c
|
|||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
callback(LLUUID::null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -372,6 +375,125 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t
|
|||
EnqueueAISCommand("UpdateItem", proc);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback)
|
||||
{
|
||||
|
||||
std::string cap;
|
||||
|
||||
cap = (type == INVENTORY) ? getInvCap() : getLibCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/item/") + itemId.asString();
|
||||
|
||||
invokationFn_t getFn = boost::bind(
|
||||
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
|
||||
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
||||
//----
|
||||
// _1 -> httpAdapter
|
||||
// _2 -> httpRequest
|
||||
// _3 -> url
|
||||
// _4 -> body
|
||||
// _5 -> httpOptions
|
||||
// _6 -> httpHeaders
|
||||
(&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6);
|
||||
|
||||
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
|
||||
_1, getFn, url, itemId, LLSD(), callback, FETCHITEM));
|
||||
|
||||
EnqueueAISCommand("FetchItem", proc);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool recursive, completion_t callback, S32 depth)
|
||||
{
|
||||
std::string cap;
|
||||
|
||||
cap = (type == INVENTORY) ? getInvCap() : getLibCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
callback(LLUUID::null);
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/category/") + catId.asString() + "/children";
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
url += "?depth=*";
|
||||
}
|
||||
else
|
||||
{
|
||||
url += "?depth=" + std::to_string(depth);
|
||||
}
|
||||
|
||||
invokationFn_t getFn = boost::bind(
|
||||
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
|
||||
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
||||
//----
|
||||
// _1 -> httpAdapter
|
||||
// _2 -> httpRequest
|
||||
// _3 -> url
|
||||
// _4 -> body
|
||||
// _5 -> httpOptions
|
||||
// _6 -> httpHeaders
|
||||
(&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6);
|
||||
|
||||
// get doesn't use body, can pass additional data
|
||||
LLSD body;
|
||||
body["depth"] = recursive ? S32_MAX : depth;
|
||||
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
|
||||
_1, getFn, url, catId, body, callback, FETCHCATEGORYCHILDREN));
|
||||
|
||||
EnqueueAISCommand("FetchCategoryChildren", proc);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool recursive, completion_t callback, S32 depth)
|
||||
{
|
||||
std::string cap;
|
||||
|
||||
cap = (type == INVENTORY) ? getInvCap() : getLibCap();
|
||||
if (cap.empty())
|
||||
{
|
||||
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
std::string url = cap + std::string("/category/") + catId.asString() + "/categories";
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
url += "?depth=*";
|
||||
}
|
||||
else
|
||||
{
|
||||
url += "?depth=" + std::to_string(depth);
|
||||
}
|
||||
|
||||
invokationFn_t getFn = boost::bind(
|
||||
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
|
||||
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
||||
//----
|
||||
// _1 -> httpAdapter
|
||||
// _2 -> httpRequest
|
||||
// _3 -> url
|
||||
// _4 -> body
|
||||
// _5 -> httpOptions
|
||||
// _6 -> httpHeaders
|
||||
(&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6);
|
||||
|
||||
// get doesn't use body, can pass additional data
|
||||
LLSD body;
|
||||
body["depth"] = depth;
|
||||
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
|
||||
_1, getFn, url, catId, body, callback, FETCHCATEGORYCATEGORIES));
|
||||
|
||||
EnqueueAISCommand("FetchCategoryCategories", proc);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc)
|
||||
{
|
||||
|
|
@ -422,6 +544,28 @@ void AISAPI::onIdle(void *userdata)
|
|||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body)
|
||||
{
|
||||
LLTimer timer;
|
||||
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
|
||||
{
|
||||
dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
|
||||
}
|
||||
bool is_fetch = (type == FETCHITEM)
|
||||
|| (type == FETCHCATEGORYCHILDREN)
|
||||
|| (type == FETCHCATEGORYCATEGORIES);
|
||||
// parse update llsd into stuff to do or parse received items.
|
||||
S32 depth = 0;
|
||||
if (is_fetch && request_body.has("depth"))
|
||||
{
|
||||
depth = request_body["depth"].asInteger();
|
||||
}
|
||||
AISUpdate ais_update(update, is_fetch, depth);
|
||||
ais_update.doUpdate(); // execute the updates in the appropriate order.
|
||||
LL_INFOS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter,
|
||||
invokationFn_t invoke, std::string url,
|
||||
|
|
@ -431,7 +575,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
|
||||
LLCore::HttpHeaders::ptr_t httpHeaders;
|
||||
|
||||
httpOptions->setTimeout(LLCoreHttpUtil::HTTP_REQUEST_EXPIRY_SECS);
|
||||
httpOptions->setTimeout(180);
|
||||
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
|
||||
|
|
@ -479,23 +623,42 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (status.getType() == 403)
|
||||
{
|
||||
if (type == FETCHCATEGORYCHILDREN)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Fetch failed, content is over imit" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL;
|
||||
LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("Inventory") << result << LL_ENDL;
|
||||
gInventory.onAISUpdateReceived("AISCommand", result);
|
||||
onUpdateReceived("AISCommand", result, type, body);
|
||||
|
||||
if (callback && !callback.empty())
|
||||
{
|
||||
{
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: Catznip-3.7
|
||||
uuid_list_t ids;
|
||||
switch (type)
|
||||
{
|
||||
case COPYLIBRARYCATEGORY:
|
||||
case FETCHCATEGORYCATEGORIES:
|
||||
case FETCHCATEGORYCHILDREN:
|
||||
if (result.has("category_id"))
|
||||
{
|
||||
ids.insert(result["category_id"]);
|
||||
ids.emplace(result["category_id"]);
|
||||
}
|
||||
break;
|
||||
case FETCHITEM:
|
||||
if (result.has("linked_id"))
|
||||
{
|
||||
ids.emplace(result["linked_id"]);
|
||||
}
|
||||
else if (result.has("item_id"))
|
||||
{
|
||||
ids.emplace(result["item_id"]);
|
||||
}
|
||||
break;
|
||||
case COPYINVENTORY:
|
||||
|
|
@ -514,48 +677,80 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
|
|||
break;
|
||||
}
|
||||
|
||||
if (!ids.empty())
|
||||
// Call callback at least once regardless of failure.
|
||||
if (ids.empty())
|
||||
{
|
||||
for (const auto& id : ids)
|
||||
callback(id);
|
||||
ids.emplace(LLUUID::null);
|
||||
}
|
||||
|
||||
for (const auto& id : ids)
|
||||
{
|
||||
callback(id);
|
||||
}
|
||||
|
||||
// [/SL:KB]
|
||||
// LLUUID id(LLUUID::null);
|
||||
//
|
||||
// if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
|
||||
// {
|
||||
// id = result["category_id"];
|
||||
// callback(id);
|
||||
// }
|
||||
// if (type == CREATEINVENTORY)
|
||||
// {
|
||||
// if (result.has("_created_categories"))
|
||||
// {
|
||||
// LLSD& cats = result["_created_categories"];
|
||||
// LLSD::array_const_iterator cat_iter;
|
||||
// for (cat_iter = cats.beginArray(); cat_iter != cats.endArray(); ++cat_iter)
|
||||
// {
|
||||
// LLUUID cat_id = *cat_iter;
|
||||
// callback(cat_id);
|
||||
// }
|
||||
// }
|
||||
// if (result.has("_created_items"))
|
||||
// {
|
||||
// LLSD& items = result["_created_items"];
|
||||
// LLSD::array_const_iterator item_iter;
|
||||
// for (item_iter = items.beginArray(); item_iter != items.endArray(); ++item_iter)
|
||||
// {
|
||||
// LLUUID item_id = *item_iter;
|
||||
// callback(item_id);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// bool needs_callback = true;
|
||||
// LLUUID id(LLUUID::null);
|
||||
|
||||
// if ( ( (type == COPYLIBRARYCATEGORY)
|
||||
// || (type == FETCHCATEGORYCATEGORIES)
|
||||
// || (type == FETCHCATEGORYCHILDREN))
|
||||
// && result.has("category_id"))
|
||||
// {
|
||||
// id = result["category_id"];
|
||||
// }
|
||||
// if (type == FETCHITEM)
|
||||
// {
|
||||
// if (result.has("item_id"))
|
||||
// {
|
||||
// id = result["item_id"];
|
||||
// }
|
||||
// if (result.has("linked_id"))
|
||||
// {
|
||||
// id = result["linked_id"];
|
||||
// }
|
||||
// }
|
||||
//if (type == CREATEINVENTORY)
|
||||
//{
|
||||
// // CREATEINVENTORY can have multiple callbacks
|
||||
// if (result.has("_created_categories"))
|
||||
// {
|
||||
// LLSD& cats = result["_created_categories"];
|
||||
// LLSD::array_const_iterator cat_iter;
|
||||
// for (cat_iter = cats.beginArray(); cat_iter != cats.endArray(); ++cat_iter)
|
||||
// {
|
||||
// LLUUID cat_id = *cat_iter;
|
||||
// callback(cat_id);
|
||||
// needs_callback = false;
|
||||
// }
|
||||
// }
|
||||
// if (result.has("_created_items"))
|
||||
// {
|
||||
// LLSD& items = result["_created_items"];
|
||||
// LLSD::array_const_iterator item_iter;
|
||||
// for (item_iter = items.beginArray(); item_iter != items.endArray(); ++item_iter)
|
||||
// {
|
||||
// LLUUID item_id = *item_iter;
|
||||
// callback(item_id);
|
||||
// needs_callback = false;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// if (needs_callback)
|
||||
// {
|
||||
// // Call callback at least once regardless of failure.
|
||||
// // UPDATEITEM doesn't expect an id
|
||||
// callback(id);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
AISUpdate::AISUpdate(const LLSD& update)
|
||||
AISUpdate::AISUpdate(const LLSD& update, bool fetch, S32 depth)
|
||||
: mFetch(fetch)
|
||||
, mFetchDepth(depth)
|
||||
{
|
||||
parseUpdate(update);
|
||||
}
|
||||
|
|
@ -672,13 +867,13 @@ void AISUpdate::parseContent(const LLSD& update)
|
|||
|
||||
if (update.has("category_id"))
|
||||
{
|
||||
parseCategory(update);
|
||||
parseCategory(update, mFetchDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update.has("_embedded"))
|
||||
{
|
||||
parseEmbedded(update["_embedded"]);
|
||||
parseEmbedded(update["_embedded"], mFetchDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -696,7 +891,12 @@ void AISUpdate::parseItem(const LLSD& item_map)
|
|||
BOOL rv = new_item->unpackMessage(item_map);
|
||||
if (rv)
|
||||
{
|
||||
if (curr_item)
|
||||
if (mFetch)
|
||||
{
|
||||
mItemsCreated[item_id] = new_item;
|
||||
mCatDescendentDeltas[new_item->getParentUUID()];
|
||||
}
|
||||
else if (curr_item)
|
||||
{
|
||||
mItemsUpdated[item_id] = new_item;
|
||||
// This statement is here to cause a new entry with 0
|
||||
|
|
@ -731,7 +931,19 @@ void AISUpdate::parseLink(const LLSD& link_map)
|
|||
if (rv)
|
||||
{
|
||||
const LLUUID& parent_id = new_link->getParentUUID();
|
||||
if (curr_link)
|
||||
if (mFetch)
|
||||
{
|
||||
LLPermissions default_perms;
|
||||
default_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
|
||||
default_perms.initMasks(PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
|
||||
new_link->setPermissions(default_perms);
|
||||
LLSaleInfo default_sale_info;
|
||||
new_link->setSaleInfo(default_sale_info);
|
||||
//LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << LL_ENDL;
|
||||
mItemsCreated[item_id] = new_link;
|
||||
mCatDescendentDeltas[parent_id];
|
||||
}
|
||||
else if (curr_link)
|
||||
{
|
||||
mItemsUpdated[item_id] = new_link;
|
||||
// This statement is here to cause a new entry with 0
|
||||
|
|
@ -760,9 +972,27 @@ void AISUpdate::parseLink(const LLSD& link_map)
|
|||
}
|
||||
|
||||
|
||||
void AISUpdate::parseCategory(const LLSD& category_map)
|
||||
void AISUpdate::parseCategory(const LLSD& category_map, S32 depth)
|
||||
{
|
||||
LLUUID category_id = category_map["category_id"].asUUID();
|
||||
LLUUID category_id = category_map["category_id"].asUUID();
|
||||
S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN;
|
||||
|
||||
if (category_map.has("version"))
|
||||
{
|
||||
version = category_map["version"].asInteger();
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id);
|
||||
|
||||
if (curr_cat
|
||||
&& curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN
|
||||
&& version > LLViewerInventoryCategory::VERSION_UNKNOWN
|
||||
&& version < curr_cat->getVersion())
|
||||
{
|
||||
LL_WARNS() << "Got stale folder, known: " << curr_cat->getVersion()
|
||||
<< ", received: " << version << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check descendent count first, as it may be needed
|
||||
// to populate newly created categories
|
||||
|
|
@ -772,7 +1002,6 @@ void AISUpdate::parseCategory(const LLSD& category_map)
|
|||
}
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat;
|
||||
LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id);
|
||||
if (curr_cat)
|
||||
{
|
||||
// Default to current values where not provided.
|
||||
|
|
@ -792,13 +1021,33 @@ void AISUpdate::parseCategory(const LLSD& category_map)
|
|||
}
|
||||
BOOL rv = new_cat->unpackMessage(category_map);
|
||||
// *NOTE: unpackMessage does not unpack version or descendent count.
|
||||
//if (category_map.has("version"))
|
||||
//{
|
||||
// mCatVersionsUpdated[category_id] = category_map["version"].asInteger();
|
||||
//}
|
||||
if (rv)
|
||||
{
|
||||
if (curr_cat)
|
||||
if (mFetch)
|
||||
{
|
||||
// set version only if previous one was already known
|
||||
// or if we are sure this update has full data and embeded items (depth 0+)
|
||||
// since bulk fetch uses this to decide what still needs fetching
|
||||
if (version > LLViewerInventoryCategory::VERSION_UNKNOWN
|
||||
&& (depth >= 0 || (curr_cat && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN)))
|
||||
{
|
||||
// Set version/descendents for newly fetched categories.
|
||||
LL_DEBUGS("Inventory") << "Setting version to " << version
|
||||
<< " for category " << category_id << LL_ENDL;
|
||||
new_cat->setVersion(version);
|
||||
}
|
||||
uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id);
|
||||
if (mCatDescendentsKnown.end() != lookup_it)
|
||||
{
|
||||
S32 descendent_count = lookup_it->second;
|
||||
LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count
|
||||
<< " for category " << category_id << LL_ENDL;
|
||||
new_cat->setDescendentCount(descendent_count);
|
||||
}
|
||||
mCategoriesCreated[category_id] = new_cat;
|
||||
mCatDescendentDeltas[new_cat->getParentUUID()];
|
||||
}
|
||||
else if (curr_cat)
|
||||
{
|
||||
mCategoriesUpdated[category_id] = new_cat;
|
||||
// This statement is here to cause a new entry with 0
|
||||
|
|
@ -839,7 +1088,7 @@ void AISUpdate::parseCategory(const LLSD& category_map)
|
|||
// Check for more embedded content.
|
||||
if (category_map.has("_embedded"))
|
||||
{
|
||||
parseEmbedded(category_map["_embedded"]);
|
||||
parseEmbedded(category_map["_embedded"], depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -856,7 +1105,7 @@ void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embe
|
|||
}
|
||||
}
|
||||
|
||||
void AISUpdate::parseEmbedded(const LLSD& embedded)
|
||||
void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth)
|
||||
{
|
||||
if (embedded.has("links")) // _embedded in a category
|
||||
{
|
||||
|
|
@ -872,11 +1121,11 @@ void AISUpdate::parseEmbedded(const LLSD& embedded)
|
|||
}
|
||||
if (embedded.has("categories")) // _embedded in a category
|
||||
{
|
||||
parseEmbeddedCategories(embedded["categories"]);
|
||||
parseEmbeddedCategories(embedded["categories"], depth);
|
||||
}
|
||||
if (embedded.has("category")) // _embedded in a link
|
||||
{
|
||||
parseEmbeddedCategory(embedded["category"]);
|
||||
parseEmbeddedCategory(embedded["category"], depth);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -901,7 +1150,7 @@ void AISUpdate::parseEmbeddedLinks(const LLSD& links)
|
|||
{
|
||||
const LLUUID link_id((*linkit).first);
|
||||
const LLSD& link_map = (*linkit).second;
|
||||
if (mItemIds.end() == mItemIds.find(link_id))
|
||||
if (!mFetch && mItemIds.end() == mItemIds.find(link_id))
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Ignoring link not in items list " << link_id << LL_ENDL;
|
||||
}
|
||||
|
|
@ -917,7 +1166,7 @@ void AISUpdate::parseEmbeddedItem(const LLSD& item)
|
|||
// a single item (_embedded in a link)
|
||||
if (item.has("item_id"))
|
||||
{
|
||||
if (mItemIds.end() != mItemIds.find(item["item_id"].asUUID()))
|
||||
if (mFetch || mItemIds.end() != mItemIds.find(item["item_id"].asUUID()))
|
||||
{
|
||||
parseItem(item);
|
||||
}
|
||||
|
|
@ -933,7 +1182,7 @@ void AISUpdate::parseEmbeddedItems(const LLSD& items)
|
|||
{
|
||||
const LLUUID item_id((*itemit).first);
|
||||
const LLSD& item_map = (*itemit).second;
|
||||
if (mItemIds.end() == mItemIds.find(item_id))
|
||||
if (!mFetch && mItemIds.end() == mItemIds.find(item_id))
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Ignoring item not in items list " << item_id << LL_ENDL;
|
||||
}
|
||||
|
|
@ -944,19 +1193,19 @@ void AISUpdate::parseEmbeddedItems(const LLSD& items)
|
|||
}
|
||||
}
|
||||
|
||||
void AISUpdate::parseEmbeddedCategory(const LLSD& category)
|
||||
void AISUpdate::parseEmbeddedCategory(const LLSD& category, S32 depth)
|
||||
{
|
||||
// a single category (_embedded in a link)
|
||||
if (category.has("category_id"))
|
||||
{
|
||||
if (mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID()))
|
||||
if (mFetch || mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID()))
|
||||
{
|
||||
parseCategory(category);
|
||||
parseCategory(category, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
|
||||
void AISUpdate::parseEmbeddedCategories(const LLSD& categories, S32 depth)
|
||||
{
|
||||
// a map of categories (_embedded in a category)
|
||||
for(LLSD::map_const_iterator categoryit = categories.beginMap(),
|
||||
|
|
@ -965,13 +1214,13 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
|
|||
{
|
||||
const LLUUID category_id((*categoryit).first);
|
||||
const LLSD& category_map = (*categoryit).second;
|
||||
if (mCategoryIds.end() == mCategoryIds.find(category_id))
|
||||
if (!mFetch && mCategoryIds.end() == mCategoryIds.find(category_id))
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Ignoring category not in categories list " << category_id << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
parseCategory(category_map);
|
||||
parseCategory(category_map, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@
|
|||
class AISAPI
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
INVENTORY,
|
||||
LIBRARY
|
||||
} ITEM_TYPE;
|
||||
|
||||
typedef boost::function<void(const LLUUID &invItem)> completion_t;
|
||||
|
||||
static bool isAvailable();
|
||||
|
|
@ -50,6 +55,9 @@ public:
|
|||
static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t());
|
||||
static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t());
|
||||
static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t());
|
||||
static void FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback = completion_t());
|
||||
static void FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
|
||||
static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
|
||||
static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
|
||||
|
||||
private:
|
||||
|
|
@ -62,7 +70,10 @@ private:
|
|||
UPDATECATEGORY,
|
||||
UPDATEITEM,
|
||||
COPYLIBRARYCATEGORY,
|
||||
CREATEINVENTORY
|
||||
CREATEINVENTORY,
|
||||
FETCHITEM,
|
||||
FETCHCATEGORYCHILDREN,
|
||||
FETCHCATEGORYCATEGORIES,
|
||||
} COMMAND_TYPE;
|
||||
|
||||
static const std::string INVENTORY_CAP_NAME;
|
||||
|
|
@ -73,6 +84,7 @@ private:
|
|||
|
||||
static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc);
|
||||
static void onIdle(void *userdata); // launches postponed AIS commands
|
||||
static void onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body);
|
||||
|
||||
static std::string getInvCap();
|
||||
static std::string getLibCap();
|
||||
|
|
@ -88,7 +100,7 @@ private:
|
|||
class AISUpdate
|
||||
{
|
||||
public:
|
||||
AISUpdate(const LLSD& update);
|
||||
AISUpdate(const LLSD& update, bool fetch, S32 depth);
|
||||
void parseUpdate(const LLSD& update);
|
||||
void parseMeta(const LLSD& update);
|
||||
void parseContent(const LLSD& update);
|
||||
|
|
@ -98,14 +110,14 @@ public:
|
|||
// void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
void parseLink(const LLSD& link_map);
|
||||
void parseItem(const LLSD& link_map);
|
||||
void parseCategory(const LLSD& link_map);
|
||||
void parseCategory(const LLSD& link_map, S32 depth);
|
||||
void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
|
||||
void parseEmbedded(const LLSD& embedded);
|
||||
void parseEmbedded(const LLSD& embedded, S32 depth);
|
||||
void parseEmbeddedLinks(const LLSD& links);
|
||||
void parseEmbeddedItems(const LLSD& items);
|
||||
void parseEmbeddedCategories(const LLSD& categories);
|
||||
void parseEmbeddedCategories(const LLSD& categories, S32 depth);
|
||||
void parseEmbeddedItem(const LLSD& item);
|
||||
void parseEmbeddedCategory(const LLSD& category);
|
||||
void parseEmbeddedCategory(const LLSD& category, S32 depth);
|
||||
void doUpdate();
|
||||
private:
|
||||
void clearParseResults();
|
||||
|
|
@ -127,6 +139,8 @@ private:
|
|||
uuid_list_t mObjectsDeletedIds;
|
||||
uuid_list_t mItemIds;
|
||||
uuid_list_t mCategoryIds;
|
||||
bool mFetch;
|
||||
S32 mFetchDepth;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1777,12 +1777,17 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds
|
|||
}
|
||||
// USES UDP PATH
|
||||
// D567 needs to carry over thumbnail info
|
||||
LLUUID subfolder_id = gInventory.createNewCategory( parent_id,
|
||||
LLFolderType::FT_NONE,
|
||||
src_cat->getName());
|
||||
shallowCopyCategoryContents(src_id, subfolder_id, cb);
|
||||
gInventory.createNewCategory(
|
||||
parent_id,
|
||||
LLFolderType::FT_NONE,
|
||||
src_cat->getName(),
|
||||
[src_id, cb](const LLUUID &new_id)
|
||||
{
|
||||
LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_id, new_id, cb);
|
||||
|
||||
gInventory.notifyObservers();
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
|
||||
|
|
@ -3103,21 +3108,27 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap
|
|||
|
||||
// UDP PATH
|
||||
// D567 needs to carry over thumbnail info if present
|
||||
LLUUID new_cat_id = gInventory.createNewCategory(
|
||||
gInventory.createNewCategory(
|
||||
pid,
|
||||
LLFolderType::FT_NONE,
|
||||
name);
|
||||
name,
|
||||
[cat_id, append](const LLUUID& new_cat_id)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
gInventory.getDirectDescendentsOf(cat_id, cats, items);
|
||||
// Create a CopyMgr that will copy items, manage its own destruction
|
||||
new LLCallAfterInventoryCopyMgr(
|
||||
*items, new_cat_id, std::string("wear_inventory_category_callback"),
|
||||
boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar,
|
||||
LLAppearanceMgr::getInstance(),
|
||||
gInventory.getCategory(new_cat_id),
|
||||
append));
|
||||
|
||||
// Create a CopyMgr that will copy items, manage its own destruction
|
||||
new LLCallAfterInventoryCopyMgr(
|
||||
*items, new_cat_id, std::string("wear_inventory_category_callback"),
|
||||
boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar,
|
||||
LLAppearanceMgr::getInstance(),
|
||||
gInventory.getCategory(new_cat_id),
|
||||
append));
|
||||
|
||||
// BAP fixes a lag in display of created dir.
|
||||
gInventory.notifyObservers();
|
||||
// BAP fixes a lag in display of created dir.
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3607,7 +3618,7 @@ void LLAppearanceMgr::copyLibraryGestures()
|
|||
|
||||
// Copy gestures
|
||||
LLUUID lib_gesture_cat_id =
|
||||
gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE,false);
|
||||
gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE);
|
||||
if (lib_gesture_cat_id.isNull())
|
||||
{
|
||||
LL_WARNS() << "Unable to copy gestures, source category not found" << LL_ENDL;
|
||||
|
|
@ -4502,31 +4513,17 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
|
|||
|
||||
// First, make a folder in the My Outfits directory.
|
||||
const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
// D567 replace with coros
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
// cap-based category creation was buggy until recently. use
|
||||
// existence of AIS as an indicator the fix is present. Does
|
||||
// not actually use AIS to create the category.
|
||||
inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
|
||||
|
||||
// D567 copy thumbnail info from source folder
|
||||
gInventory.createNewCategory(
|
||||
parent_id,
|
||||
LLFolderType::FT_OUTFIT,
|
||||
new_folder_name,
|
||||
func);
|
||||
}
|
||||
else
|
||||
{
|
||||
// UDP PATH, should remove
|
||||
// D567 copy thumbnail info from source folder
|
||||
LLUUID folder_id = gInventory.createNewCategory(
|
||||
parent_id,
|
||||
LLFolderType::FT_OUTFIT,
|
||||
new_folder_name);
|
||||
onOutfitFolderCreated(folder_id, show_panel);
|
||||
}
|
||||
// UDP PATH, should remove
|
||||
// D567 copy thumbnail info from source folder
|
||||
gInventory.createNewCategory(
|
||||
parent_id,
|
||||
LLFolderType::FT_OUTFIT,
|
||||
new_folder_name,
|
||||
[show_panel](const LLUUID &new_cat_id)
|
||||
{
|
||||
LLAppearanceMgr::getInstance()->onOutfitFolderCreated(new_cat_id, show_panel);
|
||||
});
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::wearBaseOutfit()
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons
|
|||
}
|
||||
else if (mInventoryItem)
|
||||
{
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
LLUUID parent_id = mInventoryItem->getParentUUID();
|
||||
if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ BOOL LLFloaterGesture::postBuild()
|
|||
getChildView("play_btn")->setVisible( true);
|
||||
getChildView("stop_btn")->setVisible( false);
|
||||
setDefaultBtn("play_btn");
|
||||
mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false);
|
||||
mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
|
||||
|
||||
uuid_vec_t folders;
|
||||
folders.push_back(mGestureFolderID);
|
||||
|
|
|
|||
|
|
@ -381,8 +381,8 @@ BOOL LLFloaterLinkReplace::tick()
|
|||
void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items)
|
||||
{
|
||||
const LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
|
||||
const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||
const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
|
||||
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -231,18 +231,31 @@ void LLPanelMarketplaceListings::onTabChange()
|
|||
|
||||
void LLPanelMarketplaceListings::onAddButtonClicked()
|
||||
{
|
||||
// Find active panel
|
||||
LLInventoryPanel* panel = (LLInventoryPanel*)getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel();
|
||||
if (panel)
|
||||
{
|
||||
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
llassert(marketplacelistings_id.notNull());
|
||||
LLFolderType::EType preferred_type = LLFolderType::lookup("category");
|
||||
LLUUID category = gInventory.createNewCategory(marketplacelistings_id, preferred_type, LLStringUtil::null);
|
||||
gInventory.notifyObservers();
|
||||
panel->setSelectionByID(category, TRUE);
|
||||
panel->getRootFolder()->setNeedsAutoRename(TRUE);
|
||||
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
llassert(marketplacelistings_id.notNull());
|
||||
LLFolderType::EType preferred_type = LLFolderType::lookup("category");
|
||||
LLHandle<LLPanel> handle = getHandle();
|
||||
gInventory.createNewCategory(
|
||||
marketplacelistings_id,
|
||||
preferred_type,
|
||||
LLStringUtil::null,
|
||||
[handle](const LLUUID &new_cat_id)
|
||||
{
|
||||
// Find active panel
|
||||
LLPanel *marketplace_panel = handle.get();
|
||||
if (!marketplace_panel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLInventoryPanel* panel = (LLInventoryPanel*)marketplace_panel->getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel();
|
||||
if (panel)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
panel->setSelectionByID(new_cat_id, TRUE);
|
||||
panel->getRootFolder()->setNeedsAutoRename(TRUE);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void LLPanelMarketplaceListings::onAuditButtonClicked()
|
||||
|
|
@ -363,6 +376,7 @@ LLFloaterMarketplaceListings::LLFloaterMarketplaceListings(const LLSD& key)
|
|||
, mInventoryTitle(NULL)
|
||||
, mPanelListings(NULL)
|
||||
, mPanelListingsSet(false)
|
||||
, mRootFolderCreating(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -448,15 +462,39 @@ void LLFloaterMarketplaceListings::setRootFolder()
|
|||
// If we are *not* a merchant or we have no market place connection established yet, do nothing
|
||||
return;
|
||||
}
|
||||
if (!gInventory.isInventoryUsable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLFolderType::EType preferred_type = LLFolderType::FT_MARKETPLACE_LISTINGS;
|
||||
// We are a merchant. Get the Marketplace listings folder, create it if needs be.
|
||||
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true);
|
||||
if (marketplacelistings_id.isNull())
|
||||
{
|
||||
// We should never get there unless the inventory fails badly
|
||||
LL_ERRS("SLM") << "Inventory problem: failure to create the marketplace listings folder for a merchant!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(preferred_type);
|
||||
|
||||
if (marketplacelistings_id.isNull())
|
||||
{
|
||||
if (!mRootFolderCreating)
|
||||
{
|
||||
mRootFolderCreating = true;
|
||||
gInventory.createNewCategory(
|
||||
gInventory.getRootFolderID(),
|
||||
preferred_type,
|
||||
LLStringUtil::null,
|
||||
[](const LLUUID &new_cat_id)
|
||||
{
|
||||
LLFloaterMarketplaceListings *marketplace = LLFloaterReg::findTypedInstance<LLFloaterMarketplaceListings>("marketplace_listings");
|
||||
if (marketplace)
|
||||
{
|
||||
// will call setRootFolder again
|
||||
marketplace->updateView();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mRootFolderCreating = false;
|
||||
|
||||
// No longer need to observe new category creation
|
||||
if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
|
||||
|
|
@ -474,6 +512,7 @@ void LLFloaterMarketplaceListings::setRootFolder()
|
|||
}
|
||||
|
||||
mRootFolderId = marketplacelistings_id;
|
||||
mRootFolderCreating = true;
|
||||
}
|
||||
|
||||
void LLFloaterMarketplaceListings::setPanels()
|
||||
|
|
@ -544,6 +583,11 @@ void LLFloaterMarketplaceListings::updateView()
|
|||
{
|
||||
setRootFolder();
|
||||
}
|
||||
if (mRootFolderCreating)
|
||||
{
|
||||
// waiting for callback
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the bottom initializing status and progress dial if we are initializing or if we're a merchant and still loading
|
||||
if ((mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) || (is_merchant && (data_fetched <= MarketplaceFetchCodes::MARKET_FETCH_LOADING)) )
|
||||
|
|
@ -860,14 +904,17 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key)
|
|||
LLUUID cat_id(key.asUUID());
|
||||
if (cat_id.isNull())
|
||||
{
|
||||
cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
}
|
||||
|
||||
// Validates the folder
|
||||
if (cat_id.notNull())
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
validate_marketplacelistings(cat, boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), false);
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
cat_id,
|
||||
NULL,
|
||||
boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3),
|
||||
false);
|
||||
}
|
||||
|
||||
// Handle the listing folder being processed
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ private:
|
|||
LLTextBox * mInventoryTitle;
|
||||
|
||||
LLUUID mRootFolderId;
|
||||
bool mRootFolderCreating;
|
||||
LLPanelMarketplaceListings * mPanelListings;
|
||||
bool mPanelListingsSet;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -182,35 +182,11 @@ void LLFloaterOpenObject::moveToInventory(bool wear, bool replace)
|
|||
|
||||
inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear,replace);
|
||||
// D567 copy thumbnail info
|
||||
LLUUID category_id = gInventory.createNewCategory(parent_category_id,
|
||||
LLFolderType::FT_NONE,
|
||||
name,
|
||||
func);
|
||||
|
||||
//If we get a null category ID, we are using a capability in createNewCategory and we will
|
||||
//handle the following in the callbackCreateInventoryCategory routine.
|
||||
// D567 review
|
||||
if ( category_id.notNull() )
|
||||
{
|
||||
LLCatAndWear* data = new LLCatAndWear;
|
||||
data->mCatID = category_id;
|
||||
data->mWear = wear;
|
||||
data->mFolderResponded = false;
|
||||
data->mReplace = replace;
|
||||
|
||||
// Copy and/or move the items into the newly created folder.
|
||||
// Ignore any "you're going to break this item" messages.
|
||||
BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
|
||||
callbackMoveInventory,
|
||||
(void*)data);
|
||||
if (!success)
|
||||
{
|
||||
delete data;
|
||||
data = NULL;
|
||||
|
||||
LLNotificationsUtil::add("OpenObjectCannotCopy");
|
||||
}
|
||||
}
|
||||
gInventory.createNewCategory(
|
||||
parent_category_id,
|
||||
LLFolderType::FT_NONE,
|
||||
name,
|
||||
func);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "llfloaterreg.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llstatusbar.h" // can_afford_transaction()
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llagent.h"
|
||||
|
|
@ -47,8 +48,7 @@ const S32 LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN = 64;
|
|||
|
||||
// Thumbnail posting coro
|
||||
|
||||
static const std::string THUMBNAIL_ITEM_UPLOAD_CAP = "InventoryItemThumbnailUpload";
|
||||
static const std::string THUMBNAIL_CATEGORY_UPLOAD_CAP = "InventoryCategoryThumbnailUpload";
|
||||
static const std::string THUMBNAIL_UPLOAD_CAP = "InventoryThumbnailUpload";
|
||||
|
||||
void post_thumbnail_image_coro(std::string cap_url, std::string path_to_image, LLSD first_data)
|
||||
{
|
||||
|
|
@ -132,8 +132,27 @@ void post_thumbnail_image_coro(std::string cap_url, std::string path_to_image, L
|
|||
return;
|
||||
}
|
||||
|
||||
// todo: issue an inventory udpate?
|
||||
//return result["new_asset"].asUUID();
|
||||
if (first_data.has("category_id"))
|
||||
{
|
||||
LLUUID cat_id = first_data["category_id"].asUUID();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
if (cat)
|
||||
{
|
||||
cat->setThumbnailUUID(result["new_asset"].asUUID());
|
||||
}
|
||||
gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat_id);
|
||||
}
|
||||
if (first_data.has("item_id"))
|
||||
{
|
||||
LLUUID item_id = first_data["item_id"].asUUID();
|
||||
LLViewerInventoryItem* item = gInventory.getItem(item_id);
|
||||
if (item)
|
||||
{
|
||||
item->setThumbnailUUID(result["new_asset"].asUUID());
|
||||
}
|
||||
// Are we supposed to get BulkUpdateInventory?
|
||||
gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
|
||||
}
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -346,6 +365,7 @@ void LLFloaterSimpleSnapshot::onSend()
|
|||
if (previewp->createUploadFile(temp_file, THUMBNAIL_SNAPSHOT_DIM_MAX, THUMBNAIL_SNAPSHOT_DIM_MIN))
|
||||
{
|
||||
uploadImageUploadFile(temp_file, mInventoryId, mTaskId);
|
||||
closeFloater();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -380,31 +400,27 @@ void LLFloaterSimpleSnapshot::uploadThumbnail(const std::string &file_path, cons
|
|||
// static
|
||||
void LLFloaterSimpleSnapshot::uploadImageUploadFile(const std::string &temp_file, const LLUUID &inventory_id, const LLUUID &task_id)
|
||||
{
|
||||
std::string cap_name;
|
||||
LLSD data;
|
||||
|
||||
if (task_id.notNull())
|
||||
{
|
||||
cap_name = THUMBNAIL_ITEM_UPLOAD_CAP;
|
||||
data["item_id"] = inventory_id;
|
||||
data["task_id"] = task_id;
|
||||
}
|
||||
else if (gInventory.getCategory(inventory_id))
|
||||
{
|
||||
cap_name = THUMBNAIL_CATEGORY_UPLOAD_CAP;
|
||||
data["category_id"] = inventory_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
cap_name = THUMBNAIL_ITEM_UPLOAD_CAP;
|
||||
data["item_id"] = inventory_id;
|
||||
}
|
||||
|
||||
std::string cap_url = gAgent.getRegionCapability(cap_name);
|
||||
std::string cap_url = gAgent.getRegionCapability(THUMBNAIL_UPLOAD_CAP);
|
||||
if (cap_url.empty())
|
||||
{
|
||||
LLSD args;
|
||||
args["CAPABILITY"] = cap_url;
|
||||
args["CAPABILITY"] = THUMBNAIL_UPLOAD_CAP;
|
||||
LLNotificationsUtil::add("RegionCapabilityRequestError", args);
|
||||
LL_WARNS("Thumbnail") << "Failed to upload profile image for item " << inventory_id << " " << task_id << ", no cap found" << LL_ENDL;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -478,14 +478,24 @@ void LLFriendCardsManager::ensureFriendsFolderExists()
|
|||
LL_WARNS() << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << LL_ENDL;
|
||||
}
|
||||
|
||||
friends_folder_ID = gInventory.createNewCategory(calling_cards_folder_ID,
|
||||
LLFolderType::FT_CALLINGCARD, get_friend_folder_name());
|
||||
|
||||
gInventory.createNewCategory(friends_folder_ID,
|
||||
LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
|
||||
|
||||
// Now when we have all needed folders we can sync their contents with buddies list.
|
||||
syncFriendsFolder();
|
||||
gInventory.createNewCategory(
|
||||
calling_cards_folder_ID,
|
||||
LLFolderType::FT_CALLINGCARD,
|
||||
get_friend_folder_name(),
|
||||
[](const LLUUID &new_category_id)
|
||||
{
|
||||
gInventory.createNewCategory(
|
||||
new_category_id,
|
||||
LLFolderType::FT_CALLINGCARD,
|
||||
get_friend_all_subfolder_name(),
|
||||
[](const LLUUID &new_category_id)
|
||||
{
|
||||
// Now when we have all needed folders we can sync their contents with buddies list.
|
||||
LLFriendCardsManager::getInstance()->syncFriendsFolder();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -510,11 +520,16 @@ void LLFriendCardsManager::ensureFriendsAllFolderExists()
|
|||
LL_WARNS() << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << LL_ENDL;
|
||||
}
|
||||
|
||||
friends_all_folder_ID = gInventory.createNewCategory(friends_folder_ID,
|
||||
LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
|
||||
|
||||
// Now when we have all needed folders we can sync their contents with buddies list.
|
||||
syncFriendsFolder();
|
||||
gInventory.createNewCategory(
|
||||
friends_folder_ID,
|
||||
LLFolderType::FT_CALLINGCARD,
|
||||
get_friend_all_subfolder_name(),
|
||||
[](const LLUUID &new_cat_id)
|
||||
{
|
||||
// Now when we have all needed folders we can sync their contents with buddies list.
|
||||
LLFriendCardsManager::getInstance()->syncFriendsFolder();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ BOOL LLInvFVBridge::cutToClipboard()
|
|||
const LLInventoryObject* obj = gInventory.getObject(mUUID);
|
||||
if (obj && isItemMovable() && isItemRemovable())
|
||||
{
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const BOOL cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id);
|
||||
|
||||
if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) ||
|
||||
|
|
@ -1404,7 +1404,7 @@ bool LLInvFVBridge::isItemInOutfits() const
|
|||
const LLInventoryModel* model = getInventoryModel();
|
||||
if(!model) return false;
|
||||
|
||||
const LLUUID my_outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID my_outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
|
||||
return isCOFFolder() || (my_outfits_cat == mUUID) || model->isObjectDescendentOf(mUUID, my_outfits_cat);
|
||||
}
|
||||
|
|
@ -1489,7 +1489,7 @@ BOOL LLInvFVBridge::isLockedFolder(bool ignore_setting /*= false*/) const
|
|||
// *TODO : Suppress isInboxFolder() once Merchant Outbox is fully deprecated
|
||||
BOOL LLInvFVBridge::isInboxFolder() const
|
||||
{
|
||||
const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false);
|
||||
const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
|
||||
|
||||
if (inbox_id.isNull())
|
||||
{
|
||||
|
|
@ -1501,7 +1501,7 @@ BOOL LLInvFVBridge::isInboxFolder() const
|
|||
|
||||
BOOL LLInvFVBridge::isMarketplaceListingsFolder() const
|
||||
{
|
||||
const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
|
||||
if (folder_id.isNull())
|
||||
{
|
||||
|
|
@ -1801,7 +1801,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const
|
|||
{
|
||||
std::string error_msg;
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (marketplacelistings_id.notNull())
|
||||
{
|
||||
LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id);
|
||||
|
|
@ -1959,7 +1959,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
{
|
||||
LLInventoryItem* itemp = model->getItem(mUUID);
|
||||
if (!itemp) return;
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
// Note: For a single item, if it's not a copy, then it's a move
|
||||
move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action));
|
||||
}
|
||||
|
|
@ -2621,6 +2621,16 @@ LLFontGL::StyleFlags LLFolderBridge::getLabelStyle() const
|
|||
return LLFontGL::NORMAL;
|
||||
}
|
||||
|
||||
const LLUUID& LLFolderBridge::getThumbnailUUID() const
|
||||
{
|
||||
LLViewerInventoryCategory* cat = getCategory();
|
||||
if (cat)
|
||||
{
|
||||
return cat->getThumbnailUUID();
|
||||
}
|
||||
return LLUUID::null;
|
||||
}
|
||||
|
||||
void LLFolderBridge::update()
|
||||
{
|
||||
// we know we have children but haven't fetched them (doesn't obey filter)
|
||||
|
|
@ -2866,8 +2876,8 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
if (!filter) return false;
|
||||
|
||||
const LLUUID &cat_id = inv_cat->getUUID();
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const LLUUID from_folder_uuid = inv_cat->getParentUUID();
|
||||
|
||||
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
||||
|
|
@ -2885,11 +2895,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
|
||||
if (is_agent_inventory)
|
||||
{
|
||||
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
|
||||
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
// <FS:Ansariel> FIRE-1392: Allow dragging all asset types into Landmarks folder
|
||||
//const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND, false);
|
||||
//const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
|
||||
const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
|
||||
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
|
||||
|
|
@ -3184,7 +3194,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))
|
||||
if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX)))
|
||||
{
|
||||
set_dad_inbox_object(cat_id);
|
||||
}
|
||||
|
|
@ -3214,11 +3224,16 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid);
|
||||
if (version_folder_id.notNull())
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id);
|
||||
if (!validate_marketplacelistings(cat,NULL))
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
version_folder_id,
|
||||
[version_folder_id](bool result)
|
||||
{
|
||||
LLMarketplaceData::instance().activateListing(version_folder_id,false);
|
||||
if (!result)
|
||||
{
|
||||
LLMarketplaceData::instance().activateListing(version_folder_id, false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
// In all cases, update the listing we moved from so suffix are updated
|
||||
update_marketplace_category(from_folder_uuid);
|
||||
|
|
@ -3696,18 +3711,26 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
if (depth_nesting_in_marketplace(mUUID) == 1)
|
||||
{
|
||||
LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(mUUID);
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id);
|
||||
mMessage = "";
|
||||
if (!validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3)))
|
||||
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
version_folder_id,
|
||||
[this](bool result)
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = mMessage;
|
||||
LLNotificationsUtil::add("MerchantListingFailed", subs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMarketplaceData::instance().activateListing(mUUID,true);
|
||||
}
|
||||
// todo: might need to ensure bridge/mUUID exists or this will cause crashes
|
||||
if (!result)
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = mMessage;
|
||||
LLNotificationsUtil::add("MerchantListingFailed", subs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMarketplaceData::instance().activateListing(mUUID, true);
|
||||
}
|
||||
},
|
||||
boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3)
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -3715,18 +3738,27 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
{
|
||||
if (depth_nesting_in_marketplace(mUUID) == 2)
|
||||
{
|
||||
LLInventoryCategory* category = gInventory.getCategory(mUUID);
|
||||
mMessage = "";
|
||||
if (!validate_marketplacelistings(category,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false,2))
|
||||
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
mUUID,
|
||||
[this](bool result)
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = mMessage;
|
||||
LLNotificationsUtil::add("MerchantFolderActivationFailed", subs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID);
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = mMessage;
|
||||
LLNotificationsUtil::add("MerchantFolderActivationFailed", subs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLInventoryCategory* category = gInventory.getCategory(mUUID);
|
||||
LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID);
|
||||
}
|
||||
},
|
||||
boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),
|
||||
false,
|
||||
2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -3749,29 +3781,44 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
}
|
||||
else if ("marketplace_create_listing" == action)
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(mUUID);
|
||||
mMessage = "";
|
||||
bool validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false);
|
||||
if (!validates)
|
||||
|
||||
// first run vithout fix_hierarchy, second run with fix_hierarchy
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
mUUID,
|
||||
[this](bool result)
|
||||
{
|
||||
mMessage = "";
|
||||
validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),true);
|
||||
if (validates)
|
||||
if (!result)
|
||||
{
|
||||
LLNotificationsUtil::add("MerchantForceValidateListing");
|
||||
mMessage = "";
|
||||
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
mUUID,
|
||||
[this](bool result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
LLNotificationsUtil::add("MerchantForceValidateListing");
|
||||
LLMarketplaceData::instance().createListing(mUUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = mMessage;
|
||||
LLNotificationsUtil::add("MerchantListingFailed", subs);
|
||||
}
|
||||
},
|
||||
boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),
|
||||
true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMarketplaceData::instance().createListing(mUUID);
|
||||
}
|
||||
},
|
||||
boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),
|
||||
false);
|
||||
|
||||
if (!validates)
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = mMessage;
|
||||
LLNotificationsUtil::add("MerchantListingFailed", subs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMarketplaceData::instance().createListing(mUUID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if ("marketplace_disassociate_listing" == action)
|
||||
|
|
@ -3830,7 +3877,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
{
|
||||
LLInventoryCategory * cat = gInventory.getCategory(mUUID);
|
||||
if (!cat) return;
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action)));
|
||||
}
|
||||
// <FS:Ansariel> FIRE-29342: Protect folder option
|
||||
|
|
@ -4134,7 +4181,7 @@ void LLFolderBridge::pasteFromClipboard()
|
|||
LLInventoryModel* model = getInventoryModel();
|
||||
if (model && isClipboardPasteable())
|
||||
{
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const BOOL paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
|
||||
|
||||
BOOL cut_from_marketplacelistings = FALSE;
|
||||
|
|
@ -4195,11 +4242,11 @@ void LLFolderBridge::perform_pasteFromClipboard()
|
|||
LLInventoryModel* model = getInventoryModel();
|
||||
if (model && isClipboardPasteable())
|
||||
{
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND, false);
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
|
||||
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
||||
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
|
||||
|
|
@ -4479,9 +4526,9 @@ void LLFolderBridge::pasteLinkFromClipboard()
|
|||
LLInventoryModel* model = getInventoryModel();
|
||||
if(model)
|
||||
{
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
|
||||
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
||||
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
|
||||
|
|
@ -4551,8 +4598,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
|
||||
const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
|
||||
const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
|
||||
// <FS:Ansariel> FIRE-11628: Option to delete broken links from AO folder
|
||||
if (mUUID == AOEngine::instance().getAOFolder())
|
||||
|
|
@ -5535,7 +5582,7 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
|
|||
{
|
||||
if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT))
|
||||
{
|
||||
const LLUUID &my_outifts_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID &my_outifts_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
if(mUUID != my_outifts_id)
|
||||
{
|
||||
LLFloaterOutfitPhotoPreview* photo_preview = LLFloaterReg::showTypedInstance<LLFloaterOutfitPhotoPreview>("outfit_photo_preview", inv_item->getUUID());
|
||||
|
|
@ -5654,12 +5701,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
|||
LLInventoryFilter* filter = getInventoryFilter();
|
||||
if (!filter) return false;
|
||||
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
|
||||
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
|
||||
const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
|
||||
// <FS:Ansariel> FIRE-1392: Allow dragging all asset types into Landmarks folder
|
||||
//const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
//const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
|
||||
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
const LLUUID from_folder_uuid = inv_item->getParentUUID();
|
||||
|
||||
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
|
||||
|
|
@ -5680,7 +5727,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
|||
LLViewerObject* object = NULL;
|
||||
if(LLToolDragAndDrop::SOURCE_AGENT == source)
|
||||
{
|
||||
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
|
||||
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
|
||||
const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
|
||||
const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID());
|
||||
|
|
@ -5864,7 +5911,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
|||
else
|
||||
{
|
||||
// set up observer to select item once drag and drop from inbox is complete
|
||||
if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))
|
||||
if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX)))
|
||||
{
|
||||
set_dad_inbox_object(inv_item->getUUID());
|
||||
}
|
||||
|
|
@ -5882,11 +5929,15 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
|||
LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid);
|
||||
if (version_folder_id.notNull())
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id);
|
||||
if (!validate_marketplacelistings(cat,NULL))
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
|
||||
version_folder_id,
|
||||
[version_folder_id](bool result)
|
||||
{
|
||||
LLMarketplaceData::instance().activateListing(version_folder_id,false);
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
LLMarketplaceData::instance().activateListing(version_folder_id, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -317,6 +317,7 @@ public:
|
|||
static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
|
||||
virtual std::string getLabelSuffix() const;
|
||||
virtual LLFontGL::StyleFlags getLabelStyle() const;
|
||||
virtual const LLUUID& getThumbnailUUID() const;
|
||||
|
||||
void setShowDescendantsCount(bool show_count) {mShowDescendantsCount = show_count;}
|
||||
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
|
|||
{
|
||||
// At the moment background fetch only cares about VERSION_UNKNOWN,
|
||||
// so do not check isCategoryComplete that compares descendant count
|
||||
LLInventoryModelBackgroundFetch::instance().start(folder_id);
|
||||
LLInventoryModelBackgroundFetch::instance().start(folder_id, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ void update_all_marketplace_count(const LLUUID& cat_id)
|
|||
void update_all_marketplace_count()
|
||||
{
|
||||
// Get the marketplace root and launch the recursive exploration
|
||||
const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (!marketplace_listings_uuid.isNull())
|
||||
{
|
||||
update_all_marketplace_count(marketplace_listings_uuid);
|
||||
|
|
@ -933,7 +933,7 @@ void show_item_original(const LLUUID& item_uuid)
|
|||
{
|
||||
if(main_inventory->isSingleFolderMode())
|
||||
{
|
||||
main_inventory->onViewModeClick();
|
||||
main_inventory->toggleViewMode();
|
||||
}
|
||||
// <FS:Ansariel> FIRE-31037: "Recent" inventory filter gets reset when using "Show Original"
|
||||
//main_inventory->resetFilters();
|
||||
|
|
@ -992,22 +992,6 @@ void open_marketplace_listings()
|
|||
LLFloaterReg::showInstance("marketplace_listings");
|
||||
}
|
||||
|
||||
// Create a new folder in destFolderId with the same name as the item name and return the uuid of the new folder
|
||||
// Note: this is used locally in various situation where we need to wrap an item into a special folder
|
||||
LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId)
|
||||
{
|
||||
llassert(item);
|
||||
llassert(destFolderId.notNull());
|
||||
|
||||
LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName());
|
||||
gInventory.notifyObservers();
|
||||
|
||||
// *TODO : Create different notifications for the various cases
|
||||
LLNotificationsUtil::add("OutboxFolderCreated");
|
||||
|
||||
return created_folder_id;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
// Marketplace functions
|
||||
//
|
||||
|
|
@ -1022,7 +1006,7 @@ S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
|
|||
// Todo: findCategoryUUIDForType is somewhat expensive with large
|
||||
// flat root folders yet we use depth_nesting_in_marketplace at
|
||||
// every turn, find a way to correctly cache this id.
|
||||
const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (marketplace_listings_uuid.isNull())
|
||||
{
|
||||
return -1;
|
||||
|
|
@ -1494,6 +1478,7 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn
|
|||
return accept;
|
||||
}
|
||||
|
||||
// Can happen asynhroneously!!!
|
||||
bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy)
|
||||
{
|
||||
// Get the marketplace listings depth of the destination folder, exit with error if not under marketplace
|
||||
|
|
@ -1533,53 +1518,64 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
|
|||
if (can_move_to_marketplace(inv_item, error_msg, true))
|
||||
{
|
||||
// When moving an isolated item, we might need to create the folder structure to support it
|
||||
|
||||
LLUUID item_id = inv_item->getUUID();
|
||||
std::function<void(const LLUUID&)> callback_create_stock = [copy, item_id](const LLUUID& new_cat_id)
|
||||
{
|
||||
// Verify we can have this item in that destination category
|
||||
LLViewerInventoryCategory* dest_cat = gInventory.getCategory(new_cat_id);
|
||||
LLViewerInventoryItem * viewer_inv_item = gInventory.getItem(item_id);
|
||||
if (!dest_cat->acceptItem(viewer_inv_item))
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted");
|
||||
LLNotificationsUtil::add("MerchantPasteFailed", subs);
|
||||
}
|
||||
|
||||
if (copy)
|
||||
{
|
||||
// Copy the item
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, new_cat_id));
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
viewer_inv_item->getPermissions().getOwner(),
|
||||
viewer_inv_item->getUUID(),
|
||||
new_cat_id,
|
||||
std::string(),
|
||||
cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reparent the item
|
||||
gInventory.changeItemParent(viewer_inv_item, new_cat_id, true);
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(const LLUUID&)> callback_dest_create = [item_id, callback_create_stock](const LLUUID& new_cat_id)
|
||||
{
|
||||
LLViewerInventoryCategory* dest_cat = gInventory.getCategory(new_cat_id);
|
||||
LLViewerInventoryItem * viewer_inv_item = gInventory.getItem(item_id);
|
||||
if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) &&
|
||||
(dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK))
|
||||
{
|
||||
// We need to create a stock folder to move a no copy item
|
||||
gInventory.createNewCategory(new_cat_id, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName(), callback_create_stock);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback_create_stock(new_cat_id);
|
||||
}
|
||||
};
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
// We need a listing folder
|
||||
dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName());
|
||||
depth++;
|
||||
gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName(), callback_dest_create);
|
||||
}
|
||||
if (depth == 1)
|
||||
{
|
||||
// We need a version folder
|
||||
dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName());
|
||||
depth++;
|
||||
}
|
||||
LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder);
|
||||
if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) &&
|
||||
(dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK))
|
||||
{
|
||||
// We need to create a stock folder to move a no copy item
|
||||
dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName());
|
||||
dest_cat = gInventory.getCategory(dest_folder);
|
||||
depth++;
|
||||
}
|
||||
|
||||
// Verify we can have this item in that destination category
|
||||
if (!dest_cat->acceptItem(viewer_inv_item))
|
||||
{
|
||||
LLSD subs;
|
||||
subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted");
|
||||
LLNotificationsUtil::add("MerchantPasteFailed", subs);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (copy)
|
||||
{
|
||||
// Copy the item
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder));
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
viewer_inv_item->getPermissions().getOwner(),
|
||||
viewer_inv_item->getUUID(),
|
||||
dest_folder,
|
||||
std::string(),
|
||||
cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reparent the item
|
||||
gInventory.changeItemParent(viewer_inv_item, dest_folder, true);
|
||||
gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName(), callback_dest_create);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1627,7 +1623,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
|
|||
// Reparent the folder
|
||||
gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false);
|
||||
// Check the destination folder recursively for no copy items and promote the including folders if any
|
||||
validate_marketplacelistings(dest_cat);
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(dest_folder);
|
||||
}
|
||||
|
||||
// Update the modified folders
|
||||
|
|
@ -1652,32 +1648,23 @@ bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCa
|
|||
return cat1->getName().compare(cat2->getName()) < 0;
|
||||
}
|
||||
|
||||
void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level)
|
||||
{
|
||||
LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << LL_ENDL;
|
||||
}
|
||||
|
||||
// Make all relevant business logic checks on the marketplace listings starting with the folder as argument.
|
||||
// This function does no deletion of listings but a mere audit and raises issues to the user (through the
|
||||
// optional callback cb). It also returns a boolean, true if things validate, false if issues are raised.
|
||||
// optional callback cb).
|
||||
// The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders.
|
||||
bool validate_marketplacelistings(
|
||||
// @pending_callbacks - how many callbacks we are waiting for, must be inited before use
|
||||
// @result - true if things validate, false if issues are raised, must be inited before use
|
||||
typedef boost::function<void(S32 pending_callbacks, bool result)> validation_result_callback_t;
|
||||
void validate_marketplacelistings(
|
||||
LLInventoryCategory* cat,
|
||||
validation_callback_t cb,
|
||||
validation_result_callback_t cb_result,
|
||||
LLMarketplaceValidator::validation_msg_callback_t cb_msg,
|
||||
bool fix_hierarchy,
|
||||
S32 depth,
|
||||
bool notify_observers)
|
||||
bool notify_observers,
|
||||
S32 &pending_callbacks,
|
||||
bool &result)
|
||||
{
|
||||
#if 0
|
||||
// Used only for debug
|
||||
if (!cb)
|
||||
{
|
||||
cb = boost::bind(&dump_trace, _1, _2, _3);
|
||||
}
|
||||
#endif
|
||||
// Folder is valid unless issue is raised
|
||||
bool result = true;
|
||||
|
||||
// Get the type and the depth of the folder
|
||||
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat);
|
||||
const LLFolderType::EType folder_type = cat->getPreferredType();
|
||||
|
|
@ -1709,10 +1696,10 @@ bool validate_marketplacelistings(
|
|||
if (!can_move_folder_to_marketplace(cat, cat, cat, message, 0, fix_hierarchy))
|
||||
{
|
||||
result = false;
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + message;
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1722,26 +1709,42 @@ bool validate_marketplacelistings(
|
|||
{
|
||||
if (fix_hierarchy)
|
||||
{
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning") + " " + LLTrans::getString("Marketplace Validation Warning Stock");
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
cb_msg(message,depth,LLError::LEVEL_WARN);
|
||||
}
|
||||
|
||||
// Nest the stock folder one level deeper in a normal folder and restart from there
|
||||
pending_callbacks++;
|
||||
LLUUID parent_uuid = cat->getParentUUID();
|
||||
LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName());
|
||||
LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid);
|
||||
gInventory.changeCategoryParent(viewer_cat, folder_uuid, false);
|
||||
result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1, notify_observers);
|
||||
return result;
|
||||
LLUUID cat_uuid = cat->getUUID();
|
||||
gInventory.createNewCategory(parent_uuid,
|
||||
LLFolderType::FT_NONE,
|
||||
cat->getName(),
|
||||
[cat_uuid, cb_result, cb_msg, fix_hierarchy, depth, notify_observers](const LLUUID &new_cat_id)
|
||||
{
|
||||
LLInventoryCategory * move_cat = gInventory.getCategory(cat_uuid);
|
||||
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *)(move_cat);
|
||||
LLInventoryCategory * new_cat = gInventory.getCategory(new_cat_id);
|
||||
gInventory.changeCategoryParent(viewer_cat, new_cat_id, false);
|
||||
S32 pending = 0;
|
||||
bool result = true;
|
||||
// notify_observers probably should be true in such case?
|
||||
validate_marketplacelistings(new_cat, cb_result, cb_msg, fix_hierarchy, depth + 1, notify_observers, pending, result);
|
||||
cb_result(pending, result);
|
||||
}
|
||||
);
|
||||
result = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + LLTrans::getString("Marketplace Validation Warning Stock");
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1772,10 +1775,10 @@ bool validate_marketplacelistings(
|
|||
if (!can_move_to_marketplace(item, error_msg, false))
|
||||
{
|
||||
has_bad_items = true;
|
||||
if (cb && fix_hierarchy)
|
||||
if (cb_msg && fix_hierarchy)
|
||||
{
|
||||
std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg;
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1806,35 +1809,35 @@ bool validate_marketplacelistings(
|
|||
if (depth == 2)
|
||||
{
|
||||
// If this is an empty version folder, warn only (listing won't be delivered by AIS, but only AIS should unlist)
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Version");
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
cb_msg(message,depth,LLError::LEVEL_WARN);
|
||||
}
|
||||
}
|
||||
else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2))
|
||||
{
|
||||
// If this is a legit but empty stock folder, warn only (listing must stay searchable when out of stock)
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Stock");
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
cb_msg(message,depth,LLError::LEVEL_WARN);
|
||||
}
|
||||
}
|
||||
else if (cb)
|
||||
else if (cb_msg)
|
||||
{
|
||||
// We warn if there's nothing in a regular folder (may be it's an under construction listing)
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning Empty");
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
cb_msg(message,depth,LLError::LEVEL_WARN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Done with that folder : Print out the folder name unless we already found an error here
|
||||
if (cb && result && (depth >= 1))
|
||||
if (cb_msg && result && (depth >= 1))
|
||||
{
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log");
|
||||
cb(message,depth,LLError::LEVEL_INFO);
|
||||
cb_msg(message,depth,LLError::LEVEL_INFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1842,10 +1845,10 @@ bool validate_marketplacelistings(
|
|||
else if ((count == 1) && !has_bad_items && (((unique_key == default_key) && (depth > 1)) || ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2) && (cat_array->size() == 0))))
|
||||
{
|
||||
// Done with that folder : Print out the folder name unless we already found an error here
|
||||
if (cb && result && (depth >= 1))
|
||||
if (cb_msg && result && (depth >= 1))
|
||||
{
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log");
|
||||
cb(message,depth,LLError::LEVEL_INFO);
|
||||
cb_msg(message,depth,LLError::LEVEL_INFO);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1867,11 +1870,11 @@ bool validate_marketplacelistings(
|
|||
while (items_vector_it != items_vector.end())
|
||||
{
|
||||
// Create a new folder
|
||||
LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID());
|
||||
const LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID());
|
||||
LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back());
|
||||
std::string folder_name = (depth >= 1 ? viewer_cat->getName() : viewer_inv_item->getName());
|
||||
LLFolderType::EType new_folder_type = (items_vector_it->first == default_key ? LLFolderType::FT_NONE : LLFolderType::FT_MARKETPLACE_STOCK);
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string message = "";
|
||||
if (new_folder_type == LLFolderType::FT_MARKETPLACE_STOCK)
|
||||
|
|
@ -1882,30 +1885,46 @@ bool validate_marketplacelistings(
|
|||
{
|
||||
message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Version");
|
||||
}
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
cb_msg(message,depth,LLError::LEVEL_WARN);
|
||||
}
|
||||
LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, new_folder_type, folder_name);
|
||||
|
||||
// Move each item to the new folder
|
||||
while (!items_vector_it->second.empty())
|
||||
|
||||
pending_callbacks++;
|
||||
std::vector<LLUUID> uuid_vector = items_vector_it->second; // needs to be a copy for lambda
|
||||
gInventory.createNewCategory(
|
||||
parent_uuid,
|
||||
new_folder_type,
|
||||
folder_name,
|
||||
[uuid_vector, cb_result, cb_msg, depth, parent_uuid, notify_observers](const LLUUID &new_category_id)
|
||||
{
|
||||
LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back());
|
||||
if (cb)
|
||||
// Move each item to the new folder
|
||||
std::vector<LLUUID>::const_reverse_iterator iter = uuid_vector.rbegin();
|
||||
while (iter != uuid_vector.rend())
|
||||
{
|
||||
std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move");
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(*iter);
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string indent;
|
||||
for (int i = 1; i < depth; i++)
|
||||
{
|
||||
indent += " ";
|
||||
}
|
||||
std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move");
|
||||
cb_msg(message, depth, LLError::LEVEL_WARN);
|
||||
}
|
||||
gInventory.changeItemParent(viewer_inv_item, new_category_id, true);
|
||||
iter++;
|
||||
}
|
||||
gInventory.changeItemParent(viewer_inv_item, folder_uuid, true);
|
||||
items_vector_it->second.pop_back();
|
||||
}
|
||||
|
||||
// Next type
|
||||
update_marketplace_category(parent_uuid);
|
||||
update_marketplace_category(folder_uuid);
|
||||
if (notify_observers)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
|
||||
// Next type
|
||||
update_marketplace_category(parent_uuid);
|
||||
update_marketplace_category(new_category_id);
|
||||
if (notify_observers)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
cb_result(0, true);
|
||||
}
|
||||
);
|
||||
items_vector_it++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1919,11 +1938,11 @@ bool validate_marketplacelistings(
|
|||
{
|
||||
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (*iter);
|
||||
gInventory.changeCategoryParent(viewer_cat, parent_uuid, false);
|
||||
result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth, false);
|
||||
validate_marketplacelistings(viewer_cat, cb_result, cb_msg, fix_hierarchy, depth, false, pending_callbacks, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cb)
|
||||
else if (cb_msg)
|
||||
{
|
||||
// We are not fixing the hierarchy but reporting problems, report everything we can find
|
||||
// Print the folder name
|
||||
|
|
@ -1934,20 +1953,20 @@ bool validate_marketplacelistings(
|
|||
// Report if a stock folder contains a mix of items
|
||||
result = false;
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Mixed Stock");
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (cat_array->size() != 0))
|
||||
{
|
||||
// Report if a stock folder contains subfolders
|
||||
result = false;
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Subfolder In Stock");
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simply print the folder name
|
||||
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log");
|
||||
cb(message,depth,LLError::LEVEL_INFO);
|
||||
cb_msg(message,depth,LLError::LEVEL_INFO);
|
||||
}
|
||||
}
|
||||
// Scan each item and report if there's a problem
|
||||
|
|
@ -1962,21 +1981,21 @@ bool validate_marketplacelistings(
|
|||
// Report items that shouldn't be there to start with
|
||||
result = false;
|
||||
std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg;
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
else if ((!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) && (folder_type != LLFolderType::FT_MARKETPLACE_STOCK))
|
||||
{
|
||||
// Report stock items that are misplaced
|
||||
result = false;
|
||||
std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error Stock Item");
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
else if (depth == 1)
|
||||
{
|
||||
// Report items not wrapped in version folder
|
||||
result = false;
|
||||
std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Unwrapped Item");
|
||||
cb(message,depth,LLError::LEVEL_ERROR);
|
||||
cb_msg(message,depth,LLError::LEVEL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1985,17 +2004,18 @@ bool validate_marketplacelistings(
|
|||
if (viewer_cat->getDescendentCount() == 0)
|
||||
{
|
||||
// Remove the current folder if it ends up empty
|
||||
if (cb)
|
||||
if (cb_msg)
|
||||
{
|
||||
std::string message = indent + viewer_cat->getName() + LLTrans::getString("Marketplace Validation Warning Delete");
|
||||
cb(message,depth,LLError::LEVEL_WARN);
|
||||
cb_msg(message,depth,LLError::LEVEL_WARN);
|
||||
}
|
||||
gInventory.removeCategory(cat->getUUID());
|
||||
if (notify_observers)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
return result && !has_bad_items;
|
||||
result &=!has_bad_items;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2008,15 +2028,15 @@ bool validate_marketplacelistings(
|
|||
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
|
||||
{
|
||||
LLInventoryCategory* category = *iter;
|
||||
result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1, false);
|
||||
validate_marketplacelistings(category, cb_result, cb_msg, fix_hierarchy, depth + 1, false, pending_callbacks, result);
|
||||
}
|
||||
|
||||
|
||||
update_marketplace_category(cat->getUUID(), true, true);
|
||||
if (notify_observers)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
return result && !has_bad_items;
|
||||
result &= !has_bad_items;
|
||||
}
|
||||
|
||||
void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
|
||||
|
|
@ -2116,9 +2136,92 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st
|
|||
|
||||
inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids);
|
||||
gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func);
|
||||
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLMarketplaceValidator implementations
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
|
||||
LLMarketplaceValidator::LLMarketplaceValidator()
|
||||
{
|
||||
}
|
||||
LLMarketplaceValidator::~LLMarketplaceValidator()
|
||||
{
|
||||
}
|
||||
|
||||
void LLMarketplaceValidator::validateMarketplaceListings(
|
||||
const LLUUID &category_id,
|
||||
LLMarketplaceValidator::validation_done_callback_t cb_done,
|
||||
LLMarketplaceValidator::validation_msg_callback_t cb_msg,
|
||||
bool fix_hierarchy,
|
||||
S32 depth)
|
||||
{
|
||||
|
||||
mValidationQueue.emplace(category_id, cb_done, cb_msg, fix_hierarchy, depth);
|
||||
if (!mValidationInProgress)
|
||||
{
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void LLMarketplaceValidator::start()
|
||||
{
|
||||
if (mValidationQueue.empty())
|
||||
{
|
||||
mValidationInProgress = false;
|
||||
return;
|
||||
}
|
||||
mValidationInProgress = true;
|
||||
mPendingCallbacks = 1; // do '1' in case something decides ro callback immediately
|
||||
const ValidationRequest &first = mValidationQueue.front();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(first.mCategoryId);
|
||||
|
||||
validation_result_callback_t result_callback = [](S32 pending, bool result)
|
||||
{
|
||||
LLMarketplaceValidator* validator = LLMarketplaceValidator::getInstance();
|
||||
validator->mPendingCallbacks--; // we just got a callback
|
||||
validator->mPendingCallbacks += pending;
|
||||
validator->mPendingResult &= result;
|
||||
if (validator->mPendingCallbacks <= 0)
|
||||
{
|
||||
llassert(validator->mPendingCallbacks == 0); // shouldn't be below 0
|
||||
const ValidationRequest &first = validator->mValidationQueue.front();
|
||||
if (first.mCbDone)
|
||||
{
|
||||
first.mCbDone(validator->mPendingResult);
|
||||
}
|
||||
validator->mValidationQueue.pop(); // done;
|
||||
validator->start();
|
||||
}
|
||||
};
|
||||
|
||||
validate_marketplacelistings(
|
||||
cat,
|
||||
result_callback,
|
||||
first.mCbMsg,
|
||||
first.mFixHierarchy,
|
||||
first.mDepth,
|
||||
true,
|
||||
mPendingCallbacks,
|
||||
mPendingResult);
|
||||
|
||||
result_callback(mPendingCallbacks, mPendingResult);
|
||||
}
|
||||
|
||||
LLMarketplaceValidator::ValidationRequest::ValidationRequest(
|
||||
LLUUID category_id,
|
||||
validation_done_callback_t cb_done,
|
||||
validation_msg_callback_t cb_msg,
|
||||
bool fix_hierarchy,
|
||||
S32 depth)
|
||||
: mCategoryId(category_id)
|
||||
, mCbDone(cb_done)
|
||||
, mCbMsg(cb_msg)
|
||||
, mFixHierarchy(fix_hierarchy)
|
||||
, mDepth(depth)
|
||||
{}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLInventoryCollectFunctor implementations
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -2665,7 +2768,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
|
|||
{
|
||||
// <FS:Ansariel> Undo delete item confirmation per-session annoyance
|
||||
//static bool sDisplayedAtSession = false;
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
bool marketplacelistings_item = false;
|
||||
LLAllDescendentsPassedFilter f;
|
||||
for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it)
|
||||
|
|
@ -2923,7 +3026,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
|
|||
if (action == "wear" || action == "wear_add")
|
||||
{
|
||||
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
std::copy_if(selected_uuid_set.begin(),
|
||||
selected_uuid_set.end(),
|
||||
std::back_inserter(ids),
|
||||
|
|
@ -3203,7 +3306,7 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root)
|
|||
// target listing *and* the original listing. So we need to keep track of both.
|
||||
// Note: do not however put the marketplace listings root itself in this list or the whole marketplace data will be rebuilt.
|
||||
sMarketplaceFolders.clear();
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (marketplacelistings_id.isNull())
|
||||
{
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -88,13 +88,12 @@ void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryMode
|
|||
// Generates a string containing the path to the item specified by item_id.
|
||||
void append_path(const LLUUID& id, std::string& path);
|
||||
|
||||
typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t;
|
||||
|
||||
bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);
|
||||
bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false);
|
||||
bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false);
|
||||
bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false);
|
||||
bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1, bool notify_observers = true);
|
||||
|
||||
S32 depth_nesting_in_marketplace(LLUUID cur_uuid);
|
||||
LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
|
||||
S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);
|
||||
|
|
@ -109,6 +108,50 @@ bool is_only_items_selected(const uuid_vec_t& selected_uuids);
|
|||
** **
|
||||
*******************************************************************************/
|
||||
|
||||
class LLMarketplaceValidator: public LLSingleton<LLMarketplaceValidator>
|
||||
{
|
||||
LLSINGLETON(LLMarketplaceValidator);
|
||||
~LLMarketplaceValidator();
|
||||
LOG_CLASS(LLMarketplaceValidator);
|
||||
public:
|
||||
|
||||
typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_msg_callback_t;
|
||||
typedef boost::function<void(bool result)> validation_done_callback_t;
|
||||
|
||||
void validateMarketplaceListings(
|
||||
const LLUUID &category_id,
|
||||
validation_done_callback_t cb_done = NULL,
|
||||
validation_msg_callback_t cb_msg = NULL,
|
||||
bool fix_hierarchy = true,
|
||||
S32 depth = -1);
|
||||
|
||||
private:
|
||||
void start();
|
||||
|
||||
class ValidationRequest
|
||||
{
|
||||
public:
|
||||
ValidationRequest(
|
||||
LLUUID category_id,
|
||||
validation_done_callback_t cb_done,
|
||||
validation_msg_callback_t cb_msg,
|
||||
bool fix_hierarchy,
|
||||
S32 depth);
|
||||
LLUUID mCategoryId;
|
||||
validation_done_callback_t mCbDone;
|
||||
validation_msg_callback_t mCbMsg;
|
||||
bool mFixHierarchy;
|
||||
S32 mDepth;
|
||||
};
|
||||
|
||||
bool mValidationInProgress;
|
||||
S32 mPendingCallbacks;
|
||||
bool mPendingResult;
|
||||
// todo: might be a good idea to memorize requests by id and
|
||||
// filter out ones that got multiple validation requests
|
||||
std::queue<ValidationRequest> mValidationQueue;
|
||||
};
|
||||
|
||||
/********************************************************************************
|
||||
** **
|
||||
** INVENTORY COLLECTOR FUNCTIONS
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "llinventorypanel.h"
|
||||
#include "llinventorybridge.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventorymodelbackgroundfetch.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llinventorypanel.h"
|
||||
#include "llfloaterpreviewtrash.h"
|
||||
|
|
@ -209,6 +210,7 @@ public:
|
|||
titem->unpackMessage(item);
|
||||
LL_DEBUGS("Inventory") << "unpacked item '" << titem->getName() << "' in "
|
||||
<< titem->getParentUUID() << LL_ENDL;
|
||||
// callback id might be no longer supported
|
||||
U32 callback_id = item["callback_id"].asInteger();
|
||||
|
||||
if (titem->getUUID().notNull())
|
||||
|
|
@ -454,6 +456,7 @@ LLInventoryModel::LLInventoryModel()
|
|||
mIsNotifyObservers(FALSE),
|
||||
mModifyMask(LLInventoryObserver::ALL),
|
||||
mChangedItemIDs(),
|
||||
mBulckFecthCallbackSlot(),
|
||||
mObservers(),
|
||||
mProtectedCategoriesChangedCallbackConnection(), // <FS:Ansariel> FIRE-29342: Protect folder option
|
||||
mHttpRequestFG(NULL),
|
||||
|
|
@ -493,6 +496,11 @@ void LLInventoryModel::cleanupInventory()
|
|||
mObservers.erase(iter);
|
||||
delete observer;
|
||||
}
|
||||
|
||||
if (mBulckFecthCallbackSlot.connected())
|
||||
{
|
||||
mBulckFecthCallbackSlot.disconnect();
|
||||
}
|
||||
mObservers.clear();
|
||||
|
||||
// Run down HTTP transport
|
||||
|
|
@ -872,10 +880,63 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E
|
|||
}
|
||||
}
|
||||
|
||||
void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred_type)
|
||||
{
|
||||
LLUUID rv = LLUUID::null;
|
||||
LLUUID root_id = gInventory.getRootFolderID();
|
||||
if (LLFolderType::FT_ROOT_INVENTORY == preferred_type)
|
||||
{
|
||||
rv = root_id;
|
||||
}
|
||||
else if (root_id.notNull())
|
||||
{
|
||||
cat_array_t* cats = NULL;
|
||||
cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
|
||||
if (cats)
|
||||
{
|
||||
S32 count = cats->size();
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
LLViewerInventoryCategory* p_cat = cats->at(i);
|
||||
if (p_cat && p_cat->getPreferredType() == preferred_type)
|
||||
{
|
||||
const LLUUID& folder_id = cats->at(i)->getUUID();
|
||||
if (rv.isNull() || folder_id < rv)
|
||||
{
|
||||
rv = folder_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rv.isNull() && root_id.notNull())
|
||||
{
|
||||
|
||||
if (isInventoryUsable())
|
||||
{
|
||||
createNewCategory(
|
||||
root_id,
|
||||
preferred_type,
|
||||
LLStringUtil::null,
|
||||
[preferred_type](const LLUUID &new_cat_id)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "Created category: " << new_cat_id
|
||||
<< " for type: " << preferred_type << LL_ENDL;
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Inventory") << "Can't create requested folder, type " << preferred_type
|
||||
<< " because inventory is not usable" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
|
||||
LLFolderType::EType preferred_type,
|
||||
bool create_folder,
|
||||
const LLUUID& root_id)
|
||||
const LLUUID& root_id) const
|
||||
{
|
||||
LLUUID rv = LLUUID::null;
|
||||
if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
|
||||
|
|
@ -904,18 +965,14 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
|
|||
}
|
||||
}
|
||||
|
||||
if(rv.isNull() && create_folder && root_id.notNull())
|
||||
if(rv.isNull() && root_id.notNull() && preferred_type != LLFolderType::FT_MARKETPLACE_LISTINGS)
|
||||
{
|
||||
|
||||
if (isInventoryUsable())
|
||||
{
|
||||
return createNewCategory(root_id, preferred_type, LLStringUtil::null);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Inventory") << "Can't create requested folder, type " << preferred_type
|
||||
<< " because inventory is not usable" << LL_ENDL;
|
||||
}
|
||||
// if it does not exists, it should either be added
|
||||
// to createCommonSystemCategories or server should
|
||||
// have set it
|
||||
llassert(false);
|
||||
LL_WARNS("Inventory") << "Tried to find folder, type " << preferred_type
|
||||
<< " but category does not exist" << LL_ENDL;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -924,12 +981,12 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
|
|||
// 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) const
|
||||
{
|
||||
return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getRootFolderID());
|
||||
return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getRootFolderID());
|
||||
}
|
||||
|
||||
const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type)
|
||||
const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const
|
||||
{
|
||||
LLUUID cat_id;
|
||||
switch (preferred_type)
|
||||
|
|
@ -960,14 +1017,14 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
|
|||
|
||||
if (cat_id.isNull() || !getCategory(cat_id))
|
||||
{
|
||||
cat_id = findCategoryUUIDForTypeInRoot(preferred_type, true, getRootFolderID());
|
||||
cat_id = findCategoryUUIDForTypeInRoot(preferred_type, getRootFolderID());
|
||||
}
|
||||
return cat_id;
|
||||
}
|
||||
|
||||
const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder)
|
||||
const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type) const
|
||||
{
|
||||
return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getLibraryRootFolderID());
|
||||
return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID());
|
||||
}
|
||||
|
||||
LLUUID LLInventoryModel::findCategoryByName(std::string name)
|
||||
|
|
@ -995,27 +1052,31 @@ LLUUID LLInventoryModel::findCategoryByName(std::string name)
|
|||
// Convenience function to create a new category. You could call
|
||||
// updateCategory() with a newly generated UUID category, but this
|
||||
// version will take care of details like what the name should be
|
||||
// based on preferred type. Returns the UUID of the new category.
|
||||
//
|
||||
// On failure, returns a null UUID.
|
||||
// FIXME: callers do not check for or handle a null results currently.
|
||||
LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
||||
// based on preferred type.
|
||||
void LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
||||
LLFolderType::EType preferred_type,
|
||||
const std::string& pname,
|
||||
inventory_func_type callback)
|
||||
{
|
||||
LLUUID id; // Initially null.
|
||||
if (!isInventoryUsable())
|
||||
{
|
||||
LL_WARNS(LOG_INV) << "Inventory is not usable; can't create requested category of type "
|
||||
<< preferred_type << LL_ENDL;
|
||||
return id;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup())
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL;
|
||||
return id;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (preferred_type != LLFolderType::FT_NONE)
|
||||
|
|
@ -1031,33 +1092,64 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
|||
{
|
||||
name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
|
||||
}
|
||||
|
||||
#ifdef USE_AIS_FOR_NC
|
||||
// D567 currently this doesn't really work due to limitations in
|
||||
// AIS3, also violates the common caller assumption that we can
|
||||
// assign the id and return immediately.
|
||||
if (callback)
|
||||
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
// D567 note that we no longer assign the UUID in the viewer, so various workflows need to change.
|
||||
LLSD new_inventory = LLSD::emptyMap();
|
||||
new_inventory["categories"] = LLSD::emptyArray();
|
||||
LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID());
|
||||
LLSD cat_sd = cat.asLLSD();
|
||||
new_inventory["categories"].append(cat_sd);
|
||||
AISAPI::CreateInventory(parent_id, new_inventory, callback);
|
||||
AISAPI::CreateInventory(
|
||||
parent_id,
|
||||
new_inventory,
|
||||
[this, callback, parent_id, preferred_type, name] (const LLUUID& new_category)
|
||||
{
|
||||
if (new_category.isNull())
|
||||
{
|
||||
if (callback)
|
||||
{
|
||||
callback(new_category);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return LLUUID::null;
|
||||
LLViewerInventoryCategory* folderp = gInventory.getCategory(new_category);
|
||||
if (!folderp)
|
||||
{
|
||||
// Add the category to the internal representation
|
||||
LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(
|
||||
new_category,
|
||||
parent_id,
|
||||
preferred_type,
|
||||
name,
|
||||
gAgent.getID());
|
||||
|
||||
LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
|
||||
accountForUpdate(update);
|
||||
|
||||
cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
|
||||
cat->setDescendentCount(0);
|
||||
updateCategory(cat);
|
||||
}
|
||||
|
||||
if (callback)
|
||||
{
|
||||
callback(new_category);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
#else
|
||||
|
||||
LLViewerRegion* viewer_region = gAgent.getRegion();
|
||||
std::string url;
|
||||
if ( viewer_region )
|
||||
url = viewer_region->getCapability("CreateInventoryCategory");
|
||||
|
||||
if (!url.empty() && callback)
|
||||
if (!url.empty())
|
||||
{
|
||||
//Let's use the new capability.
|
||||
|
||||
LLUUID id;
|
||||
id.generate();
|
||||
LLSD request, body;
|
||||
body["folder_id"] = id;
|
||||
|
|
@ -1071,48 +1163,13 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
|||
LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL;
|
||||
LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro",
|
||||
boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback));
|
||||
|
||||
return LLUUID::null;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (!gMessageSystem)
|
||||
{
|
||||
return LLUUID::null;
|
||||
return;
|
||||
}
|
||||
|
||||
// D567 FIXME this UDP code path needs to be removed. Requires
|
||||
// reworking many of the callers to use callbacks rather than
|
||||
// assuming instant success.
|
||||
|
||||
// Add the category to the internal representation
|
||||
LL_WARNS() << "D567 need to remove this usage" << LL_ENDL;
|
||||
|
||||
id.generate();
|
||||
LLPointer<LLViewerInventoryCategory> cat =
|
||||
new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID());
|
||||
cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
|
||||
cat->setDescendentCount(0);
|
||||
LLCategoryUpdate update(cat->getParentUUID(), 1);
|
||||
accountForUpdate(update);
|
||||
updateCategory(cat);
|
||||
|
||||
LL_DEBUGS(LOG_INV) << "Creating category via UDP message CreateInventoryFolder, type " << preferred_type << LL_ENDL;
|
||||
|
||||
// Create the category on the server. We do this to prevent people
|
||||
// from munging their protected folders.
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessage("CreateInventoryFolder");
|
||||
msg->nextBlock("AgentData");
|
||||
msg->addUUID("AgentID", gAgent.getID());
|
||||
msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlock("FolderData");
|
||||
cat->packMessage(msg);
|
||||
gAgent.sendReliableMessage();
|
||||
|
||||
// return the folder id of the newly created folder
|
||||
return id;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null); // Notify about failure
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inventory_func_type callback)
|
||||
|
|
@ -1136,12 +1193,20 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
|
|||
if (!status)
|
||||
{
|
||||
LL_WARNS() << "HTTP failure attempting to create category." << LL_ENDL;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.has("folder_id"))
|
||||
{
|
||||
LL_WARNS() << "Malformed response contents" << ll_pretty_print_sd(result) << LL_ENDL;
|
||||
if (callback)
|
||||
{
|
||||
callback(LLUUID::null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1707,7 +1772,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32
|
|||
mask |= LLInventoryObserver::LABEL;
|
||||
}
|
||||
// Under marketplace, category labels are quite complex and need extra upate
|
||||
const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id))
|
||||
{
|
||||
mask |= LLInventoryObserver::LABEL;
|
||||
|
|
@ -1870,17 +1935,13 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
|
|||
notifyObservers();
|
||||
}
|
||||
|
||||
void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update)
|
||||
void LLInventoryModel::rebuildBrockenLinks()
|
||||
{
|
||||
LLTimer timer;
|
||||
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
|
||||
{
|
||||
dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update);
|
||||
}
|
||||
|
||||
AISUpdate ais_update(update); // parse update llsd into stuff to do.
|
||||
ais_update.doUpdate(); // execute the updates in the appropriate order.
|
||||
LL_INFOS(LOG_INV) << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL;
|
||||
for (LLUUID link_id : mPossiblyBrockenLinks)
|
||||
{
|
||||
addChangedMask(LLInventoryObserver::REBUILD, link_id);
|
||||
}
|
||||
mPossiblyBrockenLinks.clear();
|
||||
}
|
||||
|
||||
// Does not appear to be used currently.
|
||||
|
|
@ -2516,9 +2577,34 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
|
|||
// The item will show up as a broken link.
|
||||
if (item->getIsBrokenLink())
|
||||
{
|
||||
LL_INFOS(LOG_INV) << "Adding broken link [ name: " << item->getName()
|
||||
<< " itemID: " << item->getUUID()
|
||||
<< " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL;
|
||||
if (!LLInventoryModelBackgroundFetch::getInstance()->isEverythingFetched())
|
||||
{
|
||||
// isEverythingFetched is actually 'initial' fetch only.
|
||||
// Schedule this link for a recheck once inventory gets loaded
|
||||
mPossiblyBrockenLinks.insert(item->getUUID());
|
||||
if (!mBulckFecthCallbackSlot.connected())
|
||||
{
|
||||
// Links might take a while to update this way, and there
|
||||
// might be a lot of them. A better option might be to check
|
||||
// links periodically with final check on fetch completion.
|
||||
mBulckFecthCallbackSlot =
|
||||
LLInventoryModelBackgroundFetch::getInstance()->setAllFoldersFetchedCallback(
|
||||
[]()
|
||||
{
|
||||
gInventory.rebuildBrockenLinks();
|
||||
});
|
||||
}
|
||||
LL_DEBUGS(LOG_INV) << "Scheduling a link to be rebuilt later [ name: " << item->getName()
|
||||
<< " itemID: " << item->getUUID()
|
||||
<< " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS(LOG_INV) << "Adding broken link [ name: " << item->getName()
|
||||
<< " itemID: " << item->getUUID()
|
||||
<< " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (item->getIsLinkType())
|
||||
{
|
||||
|
|
@ -3127,7 +3213,7 @@ void LLInventoryModel::buildParentChildMap()
|
|||
}
|
||||
}
|
||||
|
||||
const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null);
|
||||
const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) != LLUUID::null);
|
||||
sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
|
||||
|
||||
|
||||
|
|
@ -3383,14 +3469,14 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,
|
|||
|
||||
void LLInventoryModel::createCommonSystemCategories()
|
||||
{
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH,true);
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true);
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true);
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, true);
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, true); // folder should exist before user tries to 'landmark this'
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS, true);
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MY_OUTFITS);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_LANDMARK); // folder should exist before user tries to 'landmark this'
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_SETTINGS);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_INBOX);
|
||||
}
|
||||
|
||||
struct LLUUIDAndName
|
||||
|
|
@ -3614,9 +3700,6 @@ void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
|
|||
msg->setHandlerFuncFast(_PREHASH_RemoveInventoryItem,
|
||||
processRemoveInventoryItem,
|
||||
NULL);
|
||||
msg->setHandlerFuncFast(_PREHASH_UpdateInventoryFolder,
|
||||
processUpdateInventoryFolder,
|
||||
NULL);
|
||||
msg->setHandlerFuncFast(_PREHASH_RemoveInventoryFolder,
|
||||
processRemoveInventoryFolder,
|
||||
NULL);
|
||||
|
|
@ -3764,66 +3847,6 @@ void LLInventoryModel::processRemoveInventoryItem(LLMessageSystem* msg, void**)
|
|||
gInventory.notifyObservers();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg,
|
||||
void**)
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "LLInventoryModel::processUpdateInventoryFolder()" << LL_ENDL;
|
||||
LLUUID agent_id, folder_id, parent_id;
|
||||
//char name[DB_INV_ITEM_NAME_BUF_SIZE];
|
||||
msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_AgentID, agent_id);
|
||||
if(agent_id != gAgent.getID())
|
||||
{
|
||||
LL_WARNS(LOG_INV) << "Got an UpdateInventoryFolder for the wrong agent."
|
||||
<< LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLPointer<LLViewerInventoryCategory> lastfolder; // hack
|
||||
cat_array_t folders;
|
||||
update_map_t update;
|
||||
S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
{
|
||||
LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
|
||||
lastfolder = tfolder;
|
||||
tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
|
||||
// make sure it's not a protected folder
|
||||
tfolder->setPreferredType(LLFolderType::FT_NONE);
|
||||
folders.push_back(tfolder);
|
||||
// examine update for changes.
|
||||
LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
|
||||
if(folderp)
|
||||
{
|
||||
if(tfolder->getParentUUID() == folderp->getParentUUID())
|
||||
{
|
||||
update[tfolder->getParentUUID()];
|
||||
}
|
||||
else
|
||||
{
|
||||
++update[tfolder->getParentUUID()];
|
||||
--update[folderp->getParentUUID()];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++update[tfolder->getParentUUID()];
|
||||
}
|
||||
}
|
||||
gInventory.accountForUpdate(update);
|
||||
for (cat_array_t::iterator it = folders.begin(); it != folders.end(); ++it)
|
||||
{
|
||||
gInventory.updateCategory(*it);
|
||||
}
|
||||
gInventory.notifyObservers();
|
||||
|
||||
// *HACK: Do the 'show' logic for a new item in the inventory.
|
||||
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
|
||||
if (active_panel)
|
||||
{
|
||||
active_panel->setSelection(lastfolder->getUUID(), TAKE_FOCUS_NO);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLInventoryModel::removeInventoryFolder(LLUUID agent_id,
|
||||
LLMessageSystem* msg)
|
||||
|
|
@ -4071,10 +4094,20 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
|
|||
for (cat_array_t::iterator cit = folders.begin(); cit != folders.end(); ++cit)
|
||||
{
|
||||
gInventory.updateCategory(*cit);
|
||||
|
||||
// Temporary workaround: just fetch the item using AIS to get missing fields.
|
||||
// If this works fine we might want to extract ids only from the message
|
||||
// then use AIS as a primary fetcher
|
||||
AISAPI::FetchCategoryChildren((*cit)->getUUID(), AISAPI::INVENTORY);
|
||||
}
|
||||
for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit)
|
||||
{
|
||||
gInventory.updateItem(*iit);
|
||||
|
||||
// Temporary workaround: just fetch the item using AIS to get missing fields.
|
||||
// If this works fine we might want to extract ids only from the message
|
||||
// then use AIS as a primary fetcher
|
||||
AISAPI::FetchItem((*iit)->getUUID(), AISAPI::INVENTORY);
|
||||
}
|
||||
// [SL:KB] - Patch: UI-Notifications | Checked: Catznip-6.5
|
||||
gInventory.notifyObservers(tid);
|
||||
|
|
|
|||
|
|
@ -333,24 +333,25 @@ public:
|
|||
// Find
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
|
||||
// Checks if category exists ("My Inventory" only), if it does not, creates it
|
||||
void ensureCategoryForTypeExists(LLFolderType::EType preferred_type);
|
||||
|
||||
const LLUUID findCategoryUUIDForTypeInRoot(
|
||||
LLFolderType::EType preferred_type,
|
||||
bool create_folder,
|
||||
const LLUUID& root_id);
|
||||
const LLUUID& root_id) const;
|
||||
|
||||
// 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: If create_folder is true, this will create a new inventory category
|
||||
// on the fly if one does not exist. *NOTE: if find_in_library is true it
|
||||
// will search in the user's library folder instead of "My Inventory"
|
||||
const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type,
|
||||
bool create_folder = true);
|
||||
const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type) const;
|
||||
// will search in the user's library folder instead of "My Inventory"
|
||||
const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type,
|
||||
bool create_folder = true);
|
||||
const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type) const;
|
||||
// Returns user specified category for uploads, returns default id if there are no
|
||||
// user specified one or it does not exist, creates default category if it is missing.
|
||||
const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type);
|
||||
const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const;
|
||||
|
||||
// Get whatever special folder this object is a child of, if any.
|
||||
const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
|
||||
|
|
@ -456,13 +457,14 @@ public:
|
|||
const LLUUID& new_parent_id,
|
||||
BOOL restamp);
|
||||
|
||||
// Marks links from a "possibly" broken list for a rebuild
|
||||
// clears the list
|
||||
void rebuildBrockenLinks();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Delete
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
|
||||
// Update model after an AISv3 update received for any operation.
|
||||
void onAISUpdateReceived(const std::string& context, const LLSD& update);
|
||||
|
||||
// Update model after an item is confirmed as removed from
|
||||
// server. Works for categories or items.
|
||||
|
|
@ -527,7 +529,7 @@ public:
|
|||
LLUUID findCategoryByName(std::string name);
|
||||
// Returns the UUID of the new category. If you want to use the default
|
||||
// name based on type, pass in a NULL to the 'name' parameter.
|
||||
LLUUID createNewCategory(const LLUUID& parent_id,
|
||||
void createNewCategory(const LLUUID& parent_id,
|
||||
LLFolderType::EType preferred_type,
|
||||
const std::string& name,
|
||||
inventory_func_type callback = NULL);
|
||||
|
|
@ -633,6 +635,8 @@ private:
|
|||
U32 mModifyMaskBacklog;
|
||||
changed_items_t mChangedItemIDsBacklog;
|
||||
changed_items_t mAddedItemIDsBacklog;
|
||||
changed_items_t mPossiblyBrockenLinks;
|
||||
boost::signals2::connection mBulckFecthCallbackSlot;
|
||||
|
||||
// [SL:KB] - Patch: UI-Notifications | Checked: Catznip-6.5
|
||||
LLUUID mTransactionId;
|
||||
|
|
@ -725,7 +729,6 @@ public:
|
|||
static void processUpdateCreateInventoryItem(LLMessageSystem* msg, void**);
|
||||
static void removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg, const char* msg_label);
|
||||
static void processRemoveInventoryItem(LLMessageSystem* msg, void**);
|
||||
static void processUpdateInventoryFolder(LLMessageSystem* msg, void**);
|
||||
static void removeInventoryFolder(LLUUID agent_id, LLMessageSystem* msg);
|
||||
static void processRemoveInventoryFolder(LLMessageSystem* msg, void**);
|
||||
static void processRemoveInventoryObjects(LLMessageSystem* msg, void**);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llinventorymodelbackgroundfetch.h"
|
||||
|
||||
#include "llaisapi.h"
|
||||
#include "llagent.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llcallbacklist.h"
|
||||
|
|
@ -188,12 +189,12 @@ const char * const LOG_INV("Inventory");
|
|||
///----------------------------------------------------------------------------
|
||||
|
||||
LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch():
|
||||
mBackgroundFetchActive(FALSE),
|
||||
mBackgroundFetchActive(false),
|
||||
mFolderFetchActive(false),
|
||||
mFetchCount(0),
|
||||
mAllFoldersFetched(FALSE),
|
||||
mRecursiveInventoryFetchStarted(FALSE),
|
||||
mRecursiveLibraryFetchStarted(FALSE),
|
||||
mAllFoldersFetched(false),
|
||||
mRecursiveInventoryFetchStarted(false),
|
||||
mRecursiveLibraryFetchStarted(false),
|
||||
mMinTimeBetweenFetches(0.3f)
|
||||
{}
|
||||
|
||||
|
|
@ -245,17 +246,19 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const
|
|||
return mFolderFetchActive;
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category)
|
||||
void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, bool recursive, bool is_category)
|
||||
{
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, recursive, is_category));
|
||||
ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE;
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, recursion_type, is_category));
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category)
|
||||
void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, bool recursive, bool is_category)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo(id, recursive, is_category));
|
||||
ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE;
|
||||
mFetchQueue.push_back(FetchQueueInfo(id, recursion_type, is_category));
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
|
||||
void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive)
|
||||
{
|
||||
LLViewerInventoryCategory * cat(gInventory.getCategory(id));
|
||||
|
||||
|
|
@ -264,31 +267,52 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
|
|||
// it's a folder, do a bulk fetch
|
||||
LL_DEBUGS(LOG_INV) << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
|
||||
|
||||
mBackgroundFetchActive = TRUE;
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE;
|
||||
if (id.isNull())
|
||||
{
|
||||
if (! mRecursiveInventoryFetchStarted)
|
||||
{
|
||||
mRecursiveInventoryFetchStarted |= recursive;
|
||||
mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));
|
||||
if (recursive && AISAPI::isAvailable())
|
||||
{
|
||||
// Not only root folder can be massive, but
|
||||
// most system folders will be requested independently
|
||||
// so request root folder and content separately
|
||||
mFetchQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), RT_CONTENT));
|
||||
}
|
||||
else
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursion_type));
|
||||
}
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
if (! mRecursiveLibraryFetchStarted)
|
||||
{
|
||||
mRecursiveLibraryFetchStarted |= recursive;
|
||||
mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));
|
||||
mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursion_type));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Specific folder requests go to front of queue.
|
||||
if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)
|
||||
{
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, recursive));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)
|
||||
{
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
// On AIS make sure root goes to the top and follow up recursive
|
||||
// fetches, not individual requests
|
||||
mFetchQueue.push_back(FetchQueueInfo(id, recursion_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Specific folder requests go to front of queue.
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, recursion_type));
|
||||
}
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
|
||||
if (id == gInventory.getLibraryRootFolderID())
|
||||
{
|
||||
mRecursiveLibraryFetchStarted |= recursive;
|
||||
|
|
@ -303,9 +327,9 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
|
|||
{
|
||||
if (! itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id))
|
||||
{
|
||||
mBackgroundFetchActive = TRUE;
|
||||
mBackgroundFetchActive = true;
|
||||
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, false, false));
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, RT_NONE, false));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -313,9 +337,9 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
|
|||
|
||||
void LLInventoryModelBackgroundFetch::findLostItems()
|
||||
{
|
||||
mBackgroundFetchActive = TRUE;
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE));
|
||||
mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, RT_RECURSIVE));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -324,15 +348,23 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
|
|||
if (mRecursiveInventoryFetchStarted &&
|
||||
mRecursiveLibraryFetchStarted)
|
||||
{
|
||||
mAllFoldersFetched = TRUE;
|
||||
mAllFoldersFetched = true;
|
||||
//LL_INFOS(LOG_INV) << "All folders fetched, validating" << LL_ENDL;
|
||||
//gInventory.validate();
|
||||
|
||||
// For now only informs about initial fetch being done
|
||||
mAllFoldersFetchedSignal();
|
||||
}
|
||||
mFolderFetchActive = false;
|
||||
mBackgroundFetchActive = false;
|
||||
LL_INFOS(LOG_INV) << "Inventory background fetch completed" << LL_ENDL;
|
||||
}
|
||||
|
||||
boost::signals2::connection LLInventoryModelBackgroundFetch::setAllFoldersFetchedCallback(folders_fetched_callback_t cb)
|
||||
{
|
||||
return mAllFoldersFetchedSignal.connect(cb);
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().backgroundFetch();
|
||||
|
|
@ -348,7 +380,15 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
|
|||
if (use_http_inventory())
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
bulkFetch();
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
bulkFetchViaAis();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
|
||||
bulkFetch();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -517,8 +557,163 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching)
|
|||
}
|
||||
}
|
||||
|
||||
void ais_simple_callback(const LLUUID& inv_id)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::onAISCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion)
|
||||
{
|
||||
incrFetchCount(-1);
|
||||
if (response_id.isNull()) // Failure
|
||||
{
|
||||
if (recursion == RT_RECURSIVE)
|
||||
{
|
||||
// A full recursive request failed.
|
||||
// Try requesting folder and nested content separately
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
mFetchQueue.push_front(FetchQueueInfo(request_id, RT_CONTENT));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (recursion == RT_CONTENT)
|
||||
{
|
||||
// Got the folder, now recursively request content
|
||||
LLInventoryModel::cat_array_t * categories(NULL);
|
||||
LLInventoryModel::item_array_t * items(NULL);
|
||||
gInventory.getDirectDescendentsOf(request_id, categories, items);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchQueue.push_front(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE));
|
||||
}
|
||||
if (!mFetchQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_BULK_FETCH("Bulk Fetch");
|
||||
|
||||
void LLInventoryModelBackgroundFetch::bulkFetchViaAis()
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_BULK_FETCH);
|
||||
//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
|
||||
if (gDisconnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static const S32 max_concurrent_fetches(50);
|
||||
|
||||
if (mFetchCount >= max_concurrent_fetches)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't loop for too long (in case of large, fully loaded inventory)
|
||||
F64 curent_time = LLTimer::getTotalSeconds();
|
||||
const F64 max_time = 0.006f; // 6 ms
|
||||
const F64 end_time = curent_time + max_time;
|
||||
|
||||
while (!mFetchQueue.empty() && mFetchCount < max_concurrent_fetches && curent_time < end_time)
|
||||
{
|
||||
const FetchQueueInfo & fetch_info(mFetchQueue.front());
|
||||
bulkFetchViaAis(fetch_info);
|
||||
mFetchQueue.pop_front();
|
||||
curent_time = LLTimer::getTotalSeconds();
|
||||
}
|
||||
|
||||
if (isBulkFetchProcessingComplete())
|
||||
{
|
||||
setAllFoldersFetched();
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetch_info)
|
||||
{
|
||||
if (fetch_info.mIsCategory)
|
||||
{
|
||||
const LLUUID & cat_id(fetch_info.mUUID);
|
||||
if (cat_id.isNull()) // Lost and found
|
||||
{
|
||||
AISAPI::FetchCategoryChildren(LLUUID::null, AISAPI::INVENTORY, false, ais_simple_callback);
|
||||
mFetchCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id));
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
{
|
||||
AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mRecursive == RT_RECURSIVE, ais_simple_callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID cat_id = cat->getUUID();
|
||||
ERecursionType type = fetch_info.mRecursive;
|
||||
AISAPI::FetchCategoryChildren(
|
||||
cat_id,
|
||||
AISAPI::INVENTORY,
|
||||
type == RT_RECURSIVE,
|
||||
[cat_id, type](const LLUUID &response_id)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().onAISCalback(cat_id, response_id, type);
|
||||
});
|
||||
}
|
||||
mFetchCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Already fetched, check if anything inside needs fetching
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
LLInventoryModel::cat_array_t * categories(NULL);
|
||||
LLInventoryModel::item_array_t * items(NULL);
|
||||
gInventory.getDirectDescendentsOf(cat_id, categories, items);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
// not push_front to not cause an infinite loop
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // else?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerInventoryItem * itemp(gInventory.getItem(fetch_info.mUUID));
|
||||
|
||||
if (itemp)
|
||||
{
|
||||
if (itemp->getPermissions().getOwner() == gAgent.getID())
|
||||
{
|
||||
AISAPI::FetchItem(itemp->getUUID(), AISAPI::INVENTORY, ais_simple_callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
AISAPI::FetchItem(itemp->getUUID(), AISAPI::LIBRARY, ais_simple_callback);
|
||||
}
|
||||
mFetchCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bundle up a bunch of requests to send all at once.
|
||||
void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
{
|
||||
|
|
@ -538,13 +733,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
|||
// inventory more quickly.
|
||||
static const U32 max_batch_size(10);
|
||||
static const S32 max_concurrent_fetches(12); // Outstanding requests, not connections
|
||||
static const F32 new_min_time(0.05f); // *HACK: Clean this up when old code goes away entirely.
|
||||
|
||||
mMinTimeBetweenFetches = new_min_time;
|
||||
if (mMinTimeBetweenFetches < new_min_time)
|
||||
{
|
||||
mMinTimeBetweenFetches = new_min_time; // *HACK: See above.
|
||||
}
|
||||
|
||||
if (mFetchCount)
|
||||
{
|
||||
|
|
@ -564,8 +752,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
|||
// </FS:Ansariel>
|
||||
}
|
||||
|
||||
if ((mFetchCount > max_concurrent_fetches) ||
|
||||
(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
|
||||
if (mFetchCount > max_concurrent_fetches)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -591,60 +778,61 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
|||
if (fetch_info.mIsCategory)
|
||||
{
|
||||
const LLUUID & cat_id(fetch_info.mUUID);
|
||||
if (cat_id.isNull()) //DEV-17797
|
||||
if (cat_id.isNull()) //DEV-17797 Lost and found
|
||||
{
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = LLUUID::null.asString();
|
||||
folder_sd["owner_id"] = gAgent.getID();
|
||||
folder_sd["sort_order"] = LLSD::Integer(sort_order);
|
||||
folder_sd["fetch_folders"] = LLSD::Boolean(FALSE);
|
||||
folder_sd["fetch_items"] = LLSD::Boolean(TRUE);
|
||||
folder_sd["fetch_folders"] = LLSD::Boolean(false);
|
||||
folder_sd["fetch_items"] = LLSD::Boolean(true);
|
||||
folder_request_body["folders"].append(folder_sd);
|
||||
folder_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id));
|
||||
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = cat->getUUID();
|
||||
folder_sd["owner_id"] = cat->getOwnerID();
|
||||
folder_sd["sort_order"] = LLSD::Integer(sort_order);
|
||||
folder_sd["fetch_folders"] = LLSD::Boolean(TRUE); //(LLSD::Boolean)sFullFetchStarted;
|
||||
folder_sd["fetch_items"] = LLSD::Boolean(TRUE);
|
||||
const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id));
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = cat->getUUID();
|
||||
folder_sd["owner_id"] = cat->getOwnerID();
|
||||
folder_sd["sort_order"] = LLSD::Integer(sort_order);
|
||||
folder_sd["fetch_folders"] = LLSD::Boolean(true); //(LLSD::Boolean)sFullFetchStarted;
|
||||
folder_sd["fetch_items"] = LLSD::Boolean(true);
|
||||
|
||||
// <FS:Beq> correct library owner for OpenSim (Rye)
|
||||
// if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
if (gInventory.getLibraryOwnerID() == cat->getOwnerID())
|
||||
// </FS:Beq>
|
||||
{
|
||||
folder_request_body_lib["folders"].append(folder_sd);
|
||||
}
|
||||
else
|
||||
{
|
||||
folder_request_body["folders"].append(folder_sd);
|
||||
}
|
||||
folder_count++;
|
||||
}
|
||||
|
||||
// May already have this folder, but append child folders to list.
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
LLInventoryModel::cat_array_t * categories(NULL);
|
||||
LLInventoryModel::item_array_t * items(NULL);
|
||||
gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
|
||||
}
|
||||
}
|
||||
}
|
||||
// <FS:Beq> correct library owner for OpenSim (Rye)
|
||||
// if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
if (gInventory.getLibraryOwnerID() == cat->getOwnerID())
|
||||
// </FS:Beq>
|
||||
{
|
||||
folder_request_body_lib["folders"].append(folder_sd);
|
||||
}
|
||||
else
|
||||
{
|
||||
folder_request_body["folders"].append(folder_sd);
|
||||
}
|
||||
folder_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// May already have this folder, but append child folders to list.
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
LLInventoryModel::cat_array_t * categories(NULL);
|
||||
LLInventoryModel::item_array_t * items(NULL);
|
||||
gInventory.getDirectDescendentsOf(cat_id, categories, items);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
// Start and stop background breadth-first fetching of inventory contents.
|
||||
// This gets triggered when performing a filter-search.
|
||||
void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE);
|
||||
void start(const LLUUID& cat_id = LLUUID::null, bool recursive = true);
|
||||
|
||||
BOOL folderFetchActive() const;
|
||||
bool isEverythingFetched() const; // completing the fetch once per session should be sufficient
|
||||
|
|
@ -68,10 +68,36 @@ public:
|
|||
bool isBulkFetchProcessingComplete() const;
|
||||
void setAllFoldersFetched();
|
||||
|
||||
void addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category);
|
||||
void addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category);
|
||||
typedef boost::function<void()> folders_fetched_callback_t;
|
||||
boost::signals2::connection setAllFoldersFetchedCallback(folders_fetched_callback_t cb);
|
||||
|
||||
void addRequestAtFront(const LLUUID & id, bool recursive, bool is_category);
|
||||
void addRequestAtBack(const LLUUID & id, bool recursive, bool is_category);
|
||||
|
||||
protected:
|
||||
|
||||
typedef enum {
|
||||
RT_NONE = 0,
|
||||
RT_CONTENT, // request content recursively
|
||||
RT_RECURSIVE, // request everything recursively
|
||||
} ERecursionType;
|
||||
struct FetchQueueInfo
|
||||
{
|
||||
FetchQueueInfo(const LLUUID& id, ERecursionType recursive, bool is_category = true)
|
||||
: mUUID(id),
|
||||
mIsCategory(is_category),
|
||||
mRecursive(recursive)
|
||||
{}
|
||||
|
||||
LLUUID mUUID;
|
||||
bool mIsCategory;
|
||||
ERecursionType mRecursive;
|
||||
};
|
||||
typedef std::deque<FetchQueueInfo> fetch_queue_t;
|
||||
|
||||
void onAISCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion);
|
||||
void bulkFetchViaAis();
|
||||
void bulkFetchViaAis(const FetchQueueInfo& fetch_info);
|
||||
void bulkFetch();
|
||||
|
||||
void backgroundFetch();
|
||||
|
|
@ -80,37 +106,26 @@ protected:
|
|||
bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;
|
||||
|
||||
private:
|
||||
BOOL mRecursiveInventoryFetchStarted;
|
||||
BOOL mRecursiveLibraryFetchStarted;
|
||||
BOOL mAllFoldersFetched;
|
||||
bool mRecursiveInventoryFetchStarted;
|
||||
bool mRecursiveLibraryFetchStarted;
|
||||
bool mAllFoldersFetched;
|
||||
typedef boost::signals2::signal<void()> folders_fetched_signal_t;
|
||||
folders_fetched_signal_t mAllFoldersFetchedSignal;
|
||||
|
||||
BOOL mBackgroundFetchActive;
|
||||
bool mBackgroundFetchActive;
|
||||
bool mFolderFetchActive;
|
||||
S32 mFetchCount;
|
||||
|
||||
LLFrameTimer mFetchTimer;
|
||||
F32 mMinTimeBetweenFetches;
|
||||
|
||||
fetch_queue_t mFetchQueue;
|
||||
|
||||
// <FS:ND> For legacy inventory
|
||||
BOOL mTimelyFetchPending;
|
||||
S32 mNumFetchRetries;
|
||||
F32 mMaxTimeBetweenFetches;
|
||||
// </FS:ND>
|
||||
|
||||
struct FetchQueueInfo
|
||||
{
|
||||
FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true)
|
||||
: mUUID(id),
|
||||
mIsCategory(is_category),
|
||||
mRecursive(recursive)
|
||||
{}
|
||||
|
||||
LLUUID mUUID;
|
||||
bool mIsCategory;
|
||||
BOOL mRecursive;
|
||||
};
|
||||
typedef std::deque<FetchQueueInfo> fetch_queue_t;
|
||||
fetch_queue_t mFetchQueue;
|
||||
};
|
||||
|
||||
#endif // LL_LLINVENTORYMODELBACKGROUNDFETCH_H
|
||||
|
|
|
|||
|
|
@ -817,7 +817,7 @@ LLUUID LLInventoryPanel::getRootFolderID()
|
|||
LLStringExplicit label(mParams.start_folder.name());
|
||||
setLabel(label);
|
||||
|
||||
root_id = gInventory.findCategoryUUIDForType(preferred_type, false);
|
||||
root_id = gInventory.findCategoryUUIDForType(preferred_type);
|
||||
if (root_id.isNull())
|
||||
{
|
||||
LL_WARNS() << "Could not find folder of type " << preferred_type << LL_ENDL;
|
||||
|
|
@ -2081,7 +2081,7 @@ void LLInventoryPanel::setSFViewAndOpenFolder(const LLInventoryPanel* panel, con
|
|||
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
|
||||
if (main_inventory && panel->hasAncestor(main_inventory) && !main_inventory->isSingleFolderMode())
|
||||
{
|
||||
main_inventory->onViewModeClick();
|
||||
main_inventory->toggleViewMode();
|
||||
main_inventory->setSingleFolderViewRoot(folder_id, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -701,10 +701,9 @@ void LLMarketplaceInventoryObserver::onIdleProcessQueue(void *userdata)
|
|||
// If it's a folder known to the marketplace, let's check it's in proper shape
|
||||
if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it))
|
||||
{
|
||||
LLInventoryCategory* cat = (LLInventoryCategory*)(obj);
|
||||
// can trigger notifyObservers
|
||||
// can cause more structural changes
|
||||
validate_marketplacelistings(cat);
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(obj->getUUID());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -898,7 +897,7 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot
|
|||
// Get/Post/Put requests to the SLM Server using the SLM API
|
||||
void LLMarketplaceData::getSLMListings()
|
||||
{
|
||||
const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
setUpdating(marketplaceFolderId, true);
|
||||
|
||||
LLCoros::instance().launch("getSLMListings",
|
||||
|
|
@ -1805,7 +1804,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth)
|
|||
}
|
||||
else
|
||||
{
|
||||
const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
std::set<LLUUID>::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid);
|
||||
if (it != mPendingUpdateSet.end())
|
||||
{
|
||||
|
|
@ -1849,8 +1848,7 @@ void LLMarketplaceData::decrementValidationWaiting(const LLUUID& folder_id, S32
|
|||
if (found->second <= 0)
|
||||
{
|
||||
mValidationWaitingList.erase(found);
|
||||
LLInventoryCategory *cat = gInventory.getCategory(folder_id);
|
||||
validate_marketplacelistings(cat);
|
||||
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(folder_id);
|
||||
update_marketplace_category(folder_id);
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -550,8 +550,33 @@ void LLPanelMainInventory::newWindow()
|
|||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLPanelMainInventory::newFolderWindow(LLUUID folder_id, LLUUID item_to_select)
|
||||
{
|
||||
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
|
||||
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();)
|
||||
{
|
||||
LLFloaterSidePanelContainer* inventory_container = dynamic_cast<LLFloaterSidePanelContainer*>(*iter++);
|
||||
if (inventory_container)
|
||||
{
|
||||
LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(inventory_container->findChild<LLPanel>("main_panel", true));
|
||||
if (sidepanel_inventory)
|
||||
{
|
||||
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
|
||||
if (main_inventory && main_inventory->isSingleFolderMode()
|
||||
&& (main_inventory->getSingleFolderViewRoot() == folder_id))
|
||||
{
|
||||
main_inventory->setFocus(true);
|
||||
if(item_to_select.notNull())
|
||||
{
|
||||
sidepanel_inventory->getActivePanel()->setSelection(item_to_select, TAKE_FOCUS_YES);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 instance_num = get_instance_num();
|
||||
|
||||
LLFloaterSidePanelContainer* inventory_container = LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
|
||||
|
|
@ -563,7 +588,7 @@ void LLPanelMainInventory::newFolderWindow(LLUUID folder_id, LLUUID item_to_sele
|
|||
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
|
||||
if (main_inventory)
|
||||
{
|
||||
main_inventory->onViewModeClick();
|
||||
main_inventory->toggleViewMode();
|
||||
if(folder_id.notNull())
|
||||
{
|
||||
main_inventory->setSingleFolderViewRoot(folder_id);
|
||||
|
|
@ -1031,7 +1056,7 @@ void LLPanelMainInventory::updateFilterDropdown(const LLInventoryFilter* filter)
|
|||
void LLPanelMainInventory::onFilterSelected()
|
||||
{
|
||||
// Find my index
|
||||
mActivePanel = (LLInventoryPanel*)getChild<LLTabContainer>("inventory filter tabs")->getCurrentPanel();
|
||||
mActivePanel = mSingleFolderMode ? getChild<LLInventoryPanel>("single_folder_inv") : (LLInventoryPanel*)getChild<LLTabContainer>("inventory filter tabs")->getCurrentPanel();
|
||||
|
||||
if (!mActivePanel)
|
||||
{
|
||||
|
|
@ -1057,6 +1082,14 @@ void LLPanelMainInventory::onFilterSelected()
|
|||
if (finder)
|
||||
{
|
||||
finder->changeFilter(&filter);
|
||||
if (mSingleFolderMode)
|
||||
{
|
||||
const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot());
|
||||
if (cat)
|
||||
{
|
||||
finder->setTitle(cat->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filter.isActive())
|
||||
{
|
||||
|
|
@ -1262,6 +1295,15 @@ void LLPanelMainInventory::toggleFindOptions()
|
|||
parent_floater->addDependentFloater(mFinderHandle);
|
||||
// start background fetch of folders
|
||||
LLInventoryModelBackgroundFetch::instance().start();
|
||||
|
||||
if (mSingleFolderMode)
|
||||
{
|
||||
const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot());
|
||||
if (cat)
|
||||
{
|
||||
finder->setTitle(cat->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1766,7 +1808,7 @@ void LLPanelMainInventory::onAddButtonClick()
|
|||
}
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::onViewModeClick()
|
||||
void LLPanelMainInventory::toggleViewMode()
|
||||
{
|
||||
mSingleFolderMode = !mSingleFolderMode;
|
||||
|
||||
|
|
@ -1780,6 +1822,7 @@ void LLPanelMainInventory::onViewModeClick()
|
|||
|
||||
mActivePanel = mSingleFolderMode ? getChild<LLInventoryPanel>("single_folder_inv") : (LLInventoryPanel*)getChild<LLTabContainer>("inventory filter tabs")->getCurrentPanel();
|
||||
updateTitle();
|
||||
onFilterSelected();
|
||||
|
||||
LLSidepanelInventory* sidepanel_inventory = getParentSidepanelInventory();
|
||||
if (sidepanel_inventory)
|
||||
|
|
@ -1793,7 +1836,61 @@ void LLPanelMainInventory::onViewModeClick()
|
|||
sidepanel_inventory->toggleInbox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::onViewModeClick()
|
||||
{
|
||||
LLUUID selected_folder;
|
||||
LLUUID new_root_folder;
|
||||
if(mSingleFolderMode)
|
||||
{
|
||||
selected_folder = mSingleFolderPanelInventory->getSingleFolderRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFolderView* root = getActivePanel()->getRootFolder();
|
||||
std::set<LLFolderViewItem*> selection_set = root->getSelectionList();
|
||||
if (selection_set.size() == 1)
|
||||
{
|
||||
LLFolderViewItem* current_item = *selection_set.begin();
|
||||
if (current_item)
|
||||
{
|
||||
const LLUUID& id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();
|
||||
if(gInventory.getCategory(id) != NULL)
|
||||
{
|
||||
new_root_folder = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLViewerInventoryItem* selected_item = gInventory.getItem(id);
|
||||
if (selected_item && selected_item->getParentUUID().notNull())
|
||||
{
|
||||
new_root_folder = selected_item->getParentUUID();
|
||||
selected_folder = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleViewMode();
|
||||
|
||||
if (mSingleFolderMode && new_root_folder.notNull())
|
||||
{
|
||||
setSingleFolderViewRoot(new_root_folder, true);
|
||||
if(selected_folder.notNull())
|
||||
{
|
||||
getActivePanel()->setSelection(selected_folder, TAKE_FOCUS_YES);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(selected_folder.notNull())
|
||||
{
|
||||
selectAllItemsPanel();
|
||||
getActivePanel()->setSelection(selected_folder, TAKE_FOCUS_YES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::onUpFolderClicked()
|
||||
|
|
@ -1828,6 +1925,11 @@ void LLPanelMainInventory::setSingleFolderViewRoot(const LLUUID& folder_id, bool
|
|||
}
|
||||
}
|
||||
|
||||
LLUUID LLPanelMainInventory::getSingleFolderViewRoot()
|
||||
{
|
||||
return mSingleFolderPanelInventory->getSingleFolderRoot();
|
||||
}
|
||||
|
||||
void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
|
||||
{
|
||||
if (menu)
|
||||
|
|
@ -1837,8 +1939,7 @@ void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_v
|
|||
LLView* spawning_view = getChild<LLView> (spawning_view_name);
|
||||
S32 menu_x, menu_y;
|
||||
//show menu in co-ordinates of panel
|
||||
spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
|
||||
menu_y += menu->getRect().getHeight();
|
||||
spawning_view->localPointToOtherView(0, 0, &menu_x, &menu_y, this);
|
||||
LLMenuGL::showPopup(this, menu, menu_x, menu_y);
|
||||
}
|
||||
}
|
||||
|
|
@ -2468,6 +2569,11 @@ void LLPanelMainInventory::updateTitle()
|
|||
if (cat)
|
||||
{
|
||||
inventory_floater->setTitle(cat->getName());
|
||||
LLFloaterInventoryFinder *finder = getFinder();
|
||||
if (finder)
|
||||
{
|
||||
finder->setTitle(cat->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -107,10 +107,12 @@ public:
|
|||
|
||||
void resetFilters();
|
||||
void onViewModeClick();
|
||||
void toggleViewMode();
|
||||
void onUpFolderClicked();
|
||||
void onBackFolderClicked();
|
||||
void onForwardFolderClicked();
|
||||
void setSingleFolderViewRoot(const LLUUID& folder_id, bool clear_nav_history = true);
|
||||
LLUUID getSingleFolderViewRoot();
|
||||
bool isSingleFolderMode() { return mSingleFolderMode; }
|
||||
|
||||
// <FS:Zi> Filter dropdown
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ BOOL LLPanelOutfitsInventory::postBuild()
|
|||
// ( This is only necessary if we want to show a warning if a user deletes an item that has a
|
||||
// a link in an outfit, see "ConfirmItemDeleteHasLinks". )
|
||||
|
||||
const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
|
||||
const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
if (outfits_cat.notNull())
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().start(outfits_cat);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
|
|||
static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
|
||||
static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
|
||||
|
||||
static bool sLoginCompleted = false;
|
||||
|
||||
bool LLSidepanelInventory::sInboxInitalized = false; // <FS:Ansariel> Inbox panel randomly shown on secondary inventory windows
|
||||
|
||||
//
|
||||
|
|
@ -204,17 +206,31 @@ BOOL LLSidepanelInventory::postBuild()
|
|||
|
||||
inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this));
|
||||
|
||||
// Get the previous inbox state from "InventoryInboxToggleState" setting.
|
||||
bool is_inbox_collapsed = !inbox_button->getToggleState();
|
||||
// For main Inventory floater: Get the previous inbox state from "InventoryInboxToggleState" setting.
|
||||
// For additional Inventory floaters: Collapsed state is default.
|
||||
bool is_inbox_collapsed = !inbox_button->getToggleState();// || sLoginCompleted; // <FS:Ansariel> Show inbox on main inventory window only
|
||||
|
||||
// Restore the collapsed inbox panel state
|
||||
mInboxLayoutPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
|
||||
inv_stack->collapsePanel(mInboxLayoutPanel, is_inbox_collapsed);
|
||||
if (!is_inbox_collapsed)
|
||||
{
|
||||
inv_stack->collapsePanel(mInboxLayoutPanel, is_inbox_collapsed);
|
||||
if (!is_inbox_collapsed)
|
||||
{
|
||||
mInboxLayoutPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));
|
||||
}
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Show inbox on main inventory window only
|
||||
//if (sLoginCompleted)
|
||||
//{
|
||||
// //save the state of Inbox panel only for main Inventory floater
|
||||
// inbox_button->removeControlVariable();
|
||||
// inbox_button->setToggleState(false);
|
||||
// updateInbox();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// // Trigger callback for after login so we can setup to track inbox changes after initial inventory load
|
||||
// LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInbox, this));
|
||||
//}
|
||||
// Set the inbox visible based on debug settings (final setting comes from http request below)
|
||||
// <FS:Ansariel> FIRE-17603: Received Items button sometimes vanishing
|
||||
//enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
|
||||
|
|
@ -224,6 +240,7 @@ BOOL LLSidepanelInventory::postBuild()
|
|||
|
||||
// Trigger callback for after login so we can setup to track inbox changes after initial inventory load
|
||||
LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInbox, this));
|
||||
// </FS:Ansariel>
|
||||
|
||||
// <FS:Ansariel> Optional hiding of Received Items folder aka Inbox
|
||||
gSavedSettings.getControl("FSShowInboxFolder")->getSignal()->connect(boost::bind(&LLSidepanelInventory::refreshInboxVisibility, this));
|
||||
|
|
@ -240,10 +257,11 @@ BOOL LLSidepanelInventory::postBuild()
|
|||
|
||||
void LLSidepanelInventory::updateInbox()
|
||||
{
|
||||
sLoginCompleted = true;
|
||||
//
|
||||
// Track inbox folder changes
|
||||
//
|
||||
const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
|
||||
const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
|
||||
|
||||
// Set up observer to listen for creation of inbox if it doesn't exist
|
||||
if (inbox_id.isNull())
|
||||
|
|
|
|||
|
|
@ -2653,6 +2653,7 @@ bool idle_startup()
|
|||
LLNotificationsUtil::add("InventoryUnusable");
|
||||
}
|
||||
|
||||
LLInventoryModelBackgroundFetch::instance().start();
|
||||
gInventory.createCommonSystemCategories();
|
||||
|
||||
// It's debatable whether this flag is a good idea - sets all
|
||||
|
|
@ -3696,7 +3697,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
|
|||
// Not going through the processAgentInitialWearables path, so need to set this here.
|
||||
LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
|
||||
// Initiate creation of COF, since we're also bypassing that.
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT);
|
||||
|
||||
ESex gender;
|
||||
if (gender_name == "male")
|
||||
|
|
@ -3873,6 +3874,11 @@ void reset_login()
|
|||
LLFloaterReg::hideVisibleInstances();
|
||||
LLStartUp::setStartupState( STATE_BROWSER_INIT );
|
||||
|
||||
if (LLVoiceClient::instanceExists())
|
||||
{
|
||||
LLVoiceClient::getInstance()->terminate();
|
||||
}
|
||||
|
||||
// Clear any verified certs and verify them again on next login
|
||||
// to ensure cert matches server instead of just getting reused
|
||||
LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
|
||||
|
|
|
|||
|
|
@ -773,7 +773,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
|
|||
if (!handled)
|
||||
{
|
||||
// Disallow drag and drop to 3D from the marketplace
|
||||
const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (marketplacelistings_id.notNull())
|
||||
{
|
||||
for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
|
||||
|
|
@ -1780,7 +1780,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
|
|||
return ACCEPT_NO;
|
||||
}
|
||||
|
||||
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
||||
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX);
|
||||
if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id))
|
||||
{
|
||||
// Legacy
|
||||
|
|
@ -2254,7 +2254,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
|
|||
return ACCEPT_NO;
|
||||
}
|
||||
|
||||
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
|
||||
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX);
|
||||
if(gInventory.isObjectDescendentOf(category->getUUID(), outbox_id))
|
||||
{
|
||||
// Legacy
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
// [RLVa:KB] - Checked: 2014-11-02 (RLVa-1.4.11)
|
||||
#include "rlvcommon.h"
|
||||
// [/RLVa:KB]
|
||||
#include "llviewernetwork.h"
|
||||
|
||||
// do-nothing ops for use in callbacks.
|
||||
void no_op_inventory_func(const LLUUID&) {}
|
||||
|
|
@ -457,48 +458,66 @@ void LLViewerInventoryItem::fetchFromServer(void) const
|
|||
{
|
||||
if(!mIsComplete)
|
||||
{
|
||||
std::string url;
|
||||
if (AISAPI::isAvailable()) // AIS v 3
|
||||
{
|
||||
if (gAgent.getID() != mPermissions.getOwner())
|
||||
{
|
||||
AISAPI::FetchItem(mUUID, AISAPI::LIBRARY);
|
||||
}
|
||||
else
|
||||
{
|
||||
AISAPI::FetchItem(mUUID, AISAPI::INVENTORY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string url;
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
// we have to check region. It can be null after region was destroyed. See EXT-245
|
||||
if (region)
|
||||
{
|
||||
if (gAgent.getID() != mPermissions.getOwner())
|
||||
{
|
||||
url = region->getCapability("FetchLib2");
|
||||
}
|
||||
else
|
||||
{
|
||||
url = region->getCapability("FetchInventory2");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL;
|
||||
}
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
// we have to check region. It can be null after region was destroyed. See EXT-245
|
||||
if (region)
|
||||
{
|
||||
if (gAgent.getID() != mPermissions.getOwner())
|
||||
{
|
||||
url = region->getCapability("FetchLib2");
|
||||
}
|
||||
else
|
||||
{
|
||||
url = region->getCapability("FetchInventory2");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL;
|
||||
}
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"][0]["owner_id"] = mPermissions.getOwner();
|
||||
body["items"][0]["item_id"] = mUUID;
|
||||
if (!url.empty())
|
||||
{
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"][0]["owner_id"] = mPermissions.getOwner();
|
||||
body["items"][0]["item_id"] = mUUID;
|
||||
|
||||
LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body));
|
||||
gInventory.requestPost(true, url, body, handler, "Inventory Item");
|
||||
}
|
||||
else
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessage("FetchInventory");
|
||||
msg->nextBlock("AgentData");
|
||||
msg->addUUID("AgentID", gAgent.getID());
|
||||
msg->addUUID("SessionID", gAgent.getSessionID());
|
||||
msg->nextBlock("InventoryData");
|
||||
msg->addUUID("OwnerID", mPermissions.getOwner());
|
||||
msg->addUUID("ItemID", mUUID);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body));
|
||||
gInventory.requestPost(true, url, body, handler, "Inventory Item");
|
||||
}
|
||||
// </FS:Ansariel> OpenSim compatibility
|
||||
#ifdef OPENSIM
|
||||
else if (LLGridManager::instance().isInOpenSim()) // no cap
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessage("FetchInventory");
|
||||
msg->nextBlock("AgentData");
|
||||
msg->addUUID("AgentID", gAgent.getID());
|
||||
msg->addUUID("SessionID", gAgent.getSessionID());
|
||||
msg->nextBlock("InventoryData");
|
||||
msg->addUUID("OwnerID", mPermissions.getOwner());
|
||||
msg->addUUID("ItemID", mUUID);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
#endif
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -715,7 +734,7 @@ bool LLViewerInventoryCategory::fetch()
|
|||
{
|
||||
LL_WARNS(LOG_INV) << "agent region is null" << LL_ENDL;
|
||||
}
|
||||
if (!url.empty()) //Capability found. Build up LLSD and use it.
|
||||
if (!url.empty() || AISAPI::isAvailable())
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().start(mUUID, false);
|
||||
}
|
||||
|
|
@ -1100,13 +1119,18 @@ void create_notecard_cb(const LLUUID& inv_item)
|
|||
|
||||
LLInventoryCallbackManager gInventoryCallbacks;
|
||||
|
||||
void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
|
||||
const LLUUID& parent, const LLTransactionID& transaction_id,
|
||||
const std::string& name,
|
||||
const std::string& desc, LLAssetType::EType asset_type,
|
||||
LLInventoryType::EType inv_type, U8 subtype,
|
||||
U32 next_owner_perm,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
void create_inventory_item(
|
||||
const LLUUID& agent_id,
|
||||
const LLUUID& session_id,
|
||||
const LLUUID& parent_id,
|
||||
const LLTransactionID& transaction_id,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
LLAssetType::EType asset_type,
|
||||
LLInventoryType::EType inv_type,
|
||||
U8 subtype,
|
||||
U32 next_owner_perm,
|
||||
LLPointer<LLInventoryCallback> cb)
|
||||
{
|
||||
//check if name is equal to one of special inventory items names
|
||||
//EXT-5839
|
||||
|
|
@ -1127,6 +1151,54 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_AIS_FOR_NC
|
||||
// D567 18.03.2023 not yet implemented within AIS3
|
||||
if (AISAPI::isAvailable())
|
||||
{
|
||||
LLSD new_inventory = LLSD::emptyMap();
|
||||
new_inventory["items"] = LLSD::emptyArray();
|
||||
|
||||
LLPermissions perms;
|
||||
perms.init(
|
||||
gAgentID,
|
||||
gAgentID,
|
||||
LLUUID::null,
|
||||
LLUUID::null);
|
||||
perms.initMasks(
|
||||
PERM_ALL,
|
||||
PERM_ALL,
|
||||
PERM_NONE,
|
||||
PERM_NONE,
|
||||
next_owner_perm);
|
||||
|
||||
LLUUID null_id;
|
||||
LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
|
||||
null_id, /*don't know yet*/
|
||||
parent_id,
|
||||
perms,
|
||||
null_id, /*don't know yet*/
|
||||
asset_type,
|
||||
inv_type,
|
||||
server_name,
|
||||
desc,
|
||||
LLSaleInfo(),
|
||||
0,
|
||||
0 /*don't know yet, whenever server creates it*/);
|
||||
LLSD item_sd = item->asLLSD();
|
||||
new_inventory["items"].append(item_sd);
|
||||
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
|
||||
AISAPI::CreateInventory(
|
||||
parent_id,
|
||||
new_inventory,
|
||||
cr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "AIS v3 not available" << LL_ENDL;
|
||||
}
|
||||
#endif
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_CreateInventoryItem);
|
||||
msg->nextBlock(_PREHASH_AgentData);
|
||||
|
|
@ -1134,7 +1206,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
|
|||
msg->addUUIDFast(_PREHASH_SessionID, session_id);
|
||||
msg->nextBlock(_PREHASH_InventoryBlock);
|
||||
msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
|
||||
msg->addUUIDFast(_PREHASH_FolderID, parent);
|
||||
msg->addUUIDFast(_PREHASH_FolderID, parent_id);
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
|
||||
msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm);
|
||||
msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
|
||||
|
|
@ -1584,7 +1656,9 @@ void remove_inventory_item(
|
|||
gInventory.onObjectDeletedFromServer(item_id);
|
||||
}
|
||||
}
|
||||
else // no cap
|
||||
// </FS:Ansariel> OpenSim compatibility
|
||||
#ifdef OPENSIM
|
||||
else if (LLGridManager::instance().isInOpenSim()) // no cap
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_RemoveInventoryItem);
|
||||
|
|
@ -1603,6 +1677,12 @@ void remove_inventory_item(
|
|||
cb->fire(item_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// </FS:Ansariel>
|
||||
else
|
||||
{
|
||||
LL_WARNS(LOG_INV) << "Tried to use inventory without AIS API" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1769,7 +1849,9 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
|
|||
AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
|
||||
AISAPI::PurgeDescendents(id, cr);
|
||||
}
|
||||
else // no cap
|
||||
// </FS:Ansariel> OpenSim compatibility
|
||||
#ifdef OPENSIM
|
||||
else if (LLGridManager::instance().isInOpenSim()) // no cap
|
||||
{
|
||||
// Fast purge
|
||||
LL_DEBUGS(LOG_INV) << "purge_descendents_of fast case " << cat->getName() << LL_ENDL;
|
||||
|
|
@ -1791,6 +1873,12 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
|
|||
cb->fire(id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// </FS:Ansariel>
|
||||
else
|
||||
{
|
||||
LL_WARNS(LOG_INV) << "Tried to use inventory without AIS API" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2066,9 +2154,21 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
|
|||
parent_id = gInventory.getRootFolderID();
|
||||
}
|
||||
|
||||
LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);
|
||||
gInventory.notifyObservers();
|
||||
panel->setSelectionByID(category, TRUE);
|
||||
LLHandle<LLPanel> handle = panel->getHandle();
|
||||
gInventory.createNewCategory(
|
||||
parent_id,
|
||||
preferred_type,
|
||||
LLStringUtil::null,
|
||||
[handle](const LLUUID &new_category_id)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
LLInventoryPanel* panel = static_cast<LLInventoryPanel*>(handle.get());
|
||||
if (panel)
|
||||
{
|
||||
panel->setSelectionByID(new_category_id, TRUE);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else if ("lsl" == type_name)
|
||||
{
|
||||
|
|
@ -2271,11 +2371,13 @@ const LLUUID& LLViewerInventoryItem::getThumbnailUUID() const
|
|||
}
|
||||
if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK)
|
||||
{
|
||||
return gInventory.getItem(getLinkedUUID())->getThumbnailUUID();
|
||||
LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
|
||||
return linked_item ? linked_item->getThumbnailUUID() : LLUUID::null;
|
||||
}
|
||||
if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK_FOLDER)
|
||||
{
|
||||
return gInventory.getCategory(getLinkedUUID())->getThumbnailUUID();
|
||||
LLViewerInventoryCategory *linked_cat = gInventory.getCategory(mAssetUUID);
|
||||
return linked_cat ? linked_cat->getThumbnailUUID() : LLUUID::null;
|
||||
}
|
||||
return mThumbnailUUID;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -483,14 +483,14 @@ void set_merchant_SLM_menu()
|
|||
LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
|
||||
gToolBarView->enableCommand(command->id(), true);
|
||||
|
||||
const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
if (marketplacelistings_id.isNull())
|
||||
{
|
||||
U32 mkt_status = LLMarketplaceData::instance().getSLMStatus();
|
||||
bool is_merchant = (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) || (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT);
|
||||
if (is_merchant)
|
||||
{
|
||||
gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true);
|
||||
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
LL_WARNS("SLM") << "Creating the marketplace listings folder for a merchant" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7561,42 +7561,47 @@ void container_inventory_arrived(LLViewerObject* object,
|
|||
{
|
||||
// create a new inventory category to put this in
|
||||
LLUUID cat_id;
|
||||
cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(),
|
||||
LLFolderType::FT_NONE,
|
||||
LLTrans::getString("AcquiredItems"));
|
||||
gInventory.createNewCategory(
|
||||
gInventory.getRootFolderID(),
|
||||
LLFolderType::FT_NONE,
|
||||
LLTrans::getString("AcquiredItems"),
|
||||
[inventory](const LLUUID &new_cat_id)
|
||||
{
|
||||
LLInventoryObject::object_list_t::const_iterator it = inventory->begin();
|
||||
LLInventoryObject::object_list_t::const_iterator end = inventory->end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if ((*it)->getType() != LLAssetType::AT_CATEGORY)
|
||||
{
|
||||
LLInventoryObject* obj = (LLInventoryObject*)(*it);
|
||||
LLInventoryItem* item = (LLInventoryItem*)(obj);
|
||||
LLUUID item_id;
|
||||
item_id.generate();
|
||||
time_t creation_date_utc = time_corrected();
|
||||
LLPointer<LLViewerInventoryItem> new_item
|
||||
= new LLViewerInventoryItem(item_id,
|
||||
new_cat_id,
|
||||
item->getPermissions(),
|
||||
item->getAssetUUID(),
|
||||
item->getType(),
|
||||
item->getInventoryType(),
|
||||
item->getName(),
|
||||
item->getDescription(),
|
||||
LLSaleInfo::DEFAULT,
|
||||
item->getFlags(),
|
||||
creation_date_utc);
|
||||
new_item->updateServer(TRUE);
|
||||
gInventory.updateItem(new_item);
|
||||
}
|
||||
}
|
||||
gInventory.notifyObservers();
|
||||
|
||||
LLInventoryObject::object_list_t::const_iterator it = inventory->begin();
|
||||
LLInventoryObject::object_list_t::const_iterator end = inventory->end();
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
if ((*it)->getType() != LLAssetType::AT_CATEGORY)
|
||||
{
|
||||
LLInventoryObject* obj = (LLInventoryObject*)(*it);
|
||||
LLInventoryItem* item = (LLInventoryItem*)(obj);
|
||||
LLUUID item_id;
|
||||
item_id.generate();
|
||||
time_t creation_date_utc = time_corrected();
|
||||
LLPointer<LLViewerInventoryItem> new_item
|
||||
= new LLViewerInventoryItem(item_id,
|
||||
cat_id,
|
||||
item->getPermissions(),
|
||||
item->getAssetUUID(),
|
||||
item->getType(),
|
||||
item->getInventoryType(),
|
||||
item->getName(),
|
||||
item->getDescription(),
|
||||
LLSaleInfo::DEFAULT,
|
||||
item->getFlags(),
|
||||
creation_date_utc);
|
||||
new_item->updateServer(TRUE);
|
||||
gInventory.updateItem(new_item);
|
||||
}
|
||||
}
|
||||
gInventory.notifyObservers();
|
||||
if(active_panel)
|
||||
{
|
||||
active_panel->setSelection(cat_id, TAKE_FOCUS_NO);
|
||||
}
|
||||
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
|
||||
if (active_panel)
|
||||
{
|
||||
active_panel->setSelection(new_cat_id, TAKE_FOCUS_NO);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (inventory->size() == 2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3258,8 +3258,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
|
||||
capabilityNames.append("InterestList");
|
||||
|
||||
capabilityNames.append("InventoryCategoryThumbnailUpload");
|
||||
capabilityNames.append("InventoryItemThumbnailUpload");
|
||||
capabilityNames.append("InventoryThumbnailUpload");
|
||||
capabilityNames.append("GetDisplayNames");
|
||||
capabilityNames.append("GetExperiences");
|
||||
capabilityNames.append("AgentExperiences");
|
||||
|
|
|
|||
|
|
@ -538,9 +538,19 @@ void ParticleEditor::onInjectButtonClicked()
|
|||
// if no #Firestorm folder was found, create one
|
||||
if (categoryID.isNull())
|
||||
{
|
||||
categoryID = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER);
|
||||
gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER, [this](const LLUUID& new_cat_id)
|
||||
{
|
||||
createScriptInventoryItem(new_cat_id);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
createScriptInventoryItem(categoryID);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEditor::createScriptInventoryItem(LLUUID categoryID)
|
||||
{
|
||||
// if still no #Firestorm folder was found, try to find the default "Scripts" folder
|
||||
if (categoryID.isNull())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class ParticleEditor : public LLFloater
|
|||
void updateUI();
|
||||
|
||||
std::string createScript();
|
||||
void createScriptInventoryItem(LLUUID categoryID);
|
||||
|
||||
void onParameterChange();
|
||||
void onCopyButtonClicked();
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class FSSettingsCollector : public LLInventoryCollectFunctor
|
|||
public:
|
||||
FSSettingsCollector()
|
||||
{
|
||||
mMarketplaceFolderUUID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
|
||||
mMarketplaceFolderUUID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
|
||||
}
|
||||
|
||||
virtual ~FSSettingsCollector() {}
|
||||
|
|
|
|||
|
|
@ -479,12 +479,7 @@ void RlvRenameOnWearObserver::doneIdle()
|
|||
{
|
||||
// "No modify" item with a non-renameable parent: create a new folder named and move the item into it
|
||||
inventory_func_type f = boost::bind(RlvRenameOnWearObserver::onCategoryCreate, _1, pItem->getUUID());
|
||||
LLUUID idFolder = gInventory.createNewCategory(pFolder->getUUID(), LLFolderType::FT_NONE, strFolderName, f);
|
||||
if (idFolder.notNull())
|
||||
{
|
||||
// Not using the new 'CreateInventoryCategory' cap so manually invoke the callback
|
||||
RlvRenameOnWearObserver::onCategoryCreate(idFolder, pItem->getUUID());
|
||||
}
|
||||
gInventory.createNewCategory(pFolder->getUUID(), LLFolderType::FT_NONE, strFolderName, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -532,9 +527,7 @@ bool RlvGiveToRLVOffer::createDestinationFolder(const std::string& strPath)
|
|||
else
|
||||
{
|
||||
inventory_func_type f = boost::bind(RlvGiveToRLVOffer::onCategoryCreateCallback, _1, this);
|
||||
const LLUUID idTemp = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, RLV_ROOT_FOLDER, f);
|
||||
if (idTemp.notNull())
|
||||
onCategoryCreateCallback(idTemp, this);
|
||||
gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, RLV_ROOT_FOLDER, f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -567,9 +560,7 @@ void RlvGiveToRLVOffer::onCategoryCreateCallback(LLUUID idFolder, RlvGiveToRLVOf
|
|||
{
|
||||
LLInventoryObject::correctInventoryName(strFolder);
|
||||
inventory_func_type f = boost::bind(RlvGiveToRLVOffer::onCategoryCreateCallback, _1, pInstance);
|
||||
const LLUUID idTemp = gInventory.createNewCategory(idFolder, LLFolderType::FT_NONE, strFolder, f);
|
||||
if (idTemp.notNull())
|
||||
onCategoryCreateCallback(idTemp, pInstance);
|
||||
gInventory.createNewCategory(idFolder, LLFolderType::FT_NONE, strFolder, f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -809,7 +809,9 @@
|
|||
show_item_link_overlays="true"
|
||||
top="16"
|
||||
width="288"
|
||||
scroll.reserve_scroll_corner="false"/>
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<folder double_click_override="true"/>
|
||||
</inventory_panel>
|
||||
<recent_inventory_panel
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
|
|
@ -823,7 +825,9 @@
|
|||
name="Recent Items"
|
||||
show_item_link_overlays="true"
|
||||
width="288"
|
||||
scroll.reserve_scroll_corner="false"/>
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<folder double_click_override="true"/>
|
||||
</recent_inventory_panel>
|
||||
<worn_inventory_panel
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
|
|
@ -836,7 +840,9 @@
|
|||
name="Worn Items"
|
||||
show_item_link_overlays="true"
|
||||
width="288"
|
||||
scroll.reserve_scroll_corner="false"/>
|
||||
scroll.reserve_scroll_corner="false">
|
||||
<folder double_click_override="true"/>
|
||||
</worn_inventory_panel>
|
||||
</tab_container>
|
||||
</panel>
|
||||
<panel
|
||||
|
|
|
|||
|
|
@ -236,7 +236,9 @@
|
|||
sort_order_setting="InventorySortOrder"
|
||||
show_item_link_overlays="true"
|
||||
top="16"
|
||||
width="288" />
|
||||
width="288" >
|
||||
<folder double_click_override="true"/>
|
||||
</inventory_panel>
|
||||
<recent_inventory_panel
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
|
|
@ -249,7 +251,9 @@
|
|||
left_delta="0"
|
||||
name="Recent Items"
|
||||
show_item_link_overlays="true"
|
||||
width="290" />
|
||||
width="290" >
|
||||
<folder double_click_override="true"/>
|
||||
</recent_inventory_panel>
|
||||
<worn_inventory_panel
|
||||
border="false"
|
||||
bevel_style="none"
|
||||
|
|
@ -261,7 +265,9 @@
|
|||
left_delta="0"
|
||||
name="Worn Items"
|
||||
show_item_link_overlays="true"
|
||||
width="290" />
|
||||
width="290" >
|
||||
<folder double_click_override="true"/>
|
||||
</worn_inventory_panel>
|
||||
</tab_container>
|
||||
</panel>
|
||||
<panel
|
||||
|
|
|
|||
|
|
@ -120,7 +120,9 @@
|
|||
sort_order_setting="InventorySortOrder"
|
||||
show_item_link_overlays="true"
|
||||
top="16"
|
||||
width="288" />
|
||||
width="288" >
|
||||
<folder double_click_override="true"/>
|
||||
</inventory_panel>
|
||||
<recent_inventory_panel
|
||||
bevel_style="none"
|
||||
follows="all"
|
||||
|
|
@ -132,7 +134,9 @@
|
|||
left_delta="0"
|
||||
name="Recent Items"
|
||||
show_item_link_overlays="true"
|
||||
width="290" />
|
||||
width="290" >
|
||||
<folder double_click_override="true"/>
|
||||
</recent_inventory_panel>
|
||||
<worn_inventory_panel
|
||||
bevel_style="none"
|
||||
follows="all"
|
||||
|
|
@ -143,7 +147,9 @@
|
|||
left_delta="0"
|
||||
name="Worn Items"
|
||||
show_item_link_overlays="true"
|
||||
width="290" />
|
||||
width="290" >
|
||||
<folder double_click_override="true"/>
|
||||
</worn_inventory_panel>
|
||||
</tab_container>
|
||||
<panel
|
||||
follows="left|right|bottom"
|
||||
|
|
|
|||
|
|
@ -122,7 +122,9 @@
|
|||
sort_order_setting="InventorySortOrder"
|
||||
show_item_link_overlays="true"
|
||||
top="16"
|
||||
width="288" />
|
||||
width="288" >
|
||||
<folder double_click_override="true"/>
|
||||
</inventory_panel>
|
||||
<recent_inventory_panel
|
||||
bevel_style="none"
|
||||
follows="all"
|
||||
|
|
@ -134,7 +136,9 @@
|
|||
left_delta="0"
|
||||
name="Recent Items"
|
||||
show_item_link_overlays="true"
|
||||
width="290" />
|
||||
width="290" >
|
||||
<folder double_click_override="true"/>
|
||||
</recent_inventory_panel>
|
||||
<worn_inventory_panel
|
||||
bevel_style="none"
|
||||
follows="all"
|
||||
|
|
@ -145,7 +149,9 @@
|
|||
left_delta="0"
|
||||
name="Worn Items"
|
||||
show_item_link_overlays="true"
|
||||
width="290" />
|
||||
width="290" >
|
||||
<folder double_click_override="true"/>
|
||||
</worn_inventory_panel>
|
||||
</tab_container>
|
||||
<panel
|
||||
follows="left|right|bottom"
|
||||
|
|
|
|||
|
|
@ -609,7 +609,9 @@
|
|||
layout="topleft"
|
||||
name="All Items"
|
||||
sort_order_setting="InventorySortOrder"
|
||||
show_item_link_overlays="true" />
|
||||
show_item_link_overlays="true" >
|
||||
<folder double_click_override="true"/>
|
||||
</inventory_panel>
|
||||
<recent_inventory_panel
|
||||
border="true"
|
||||
bevel_style="in"
|
||||
|
|
@ -619,7 +621,9 @@
|
|||
help_topic="recent_inventory_tab"
|
||||
layout="topleft"
|
||||
name="Recent Items"
|
||||
show_item_link_overlays="true" />
|
||||
show_item_link_overlays="true" >
|
||||
<folder double_click_override="true"/>
|
||||
</recent_inventory_panel>
|
||||
<worn_inventory_panel
|
||||
border="true"
|
||||
bevel_style="in"
|
||||
|
|
@ -628,7 +632,9 @@
|
|||
help_topic="worn_inventory_tab"
|
||||
layout="topleft"
|
||||
name="Worn Items"
|
||||
show_item_link_overlays="true" />
|
||||
show_item_link_overlays="true" >
|
||||
<folder double_click_override="true"/>
|
||||
</worn_inventory_panel>
|
||||
</tab_container>
|
||||
|
||||
<text
|
||||
|
|
|
|||
Loading…
Reference in New Issue