- changed : "Give to #RLV" agent-to-agent offers can contain subfolders

-> limited to 3 levels (e.g. #RLV/~FolderA/FolderB/FolderC)
    -> #RLV folder is auto-created if it doesn't currently exist

--HG--
branch : RLVa
master
Kitty Barnett 2014-01-08 00:33:27 +01:00
parent 5d9f7c7ba8
commit 2fd30a5fe3
5 changed files with 131 additions and 21 deletions

View File

@ -86,9 +86,13 @@ public:
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
private:
// [RLVa:KB] - Checked: 2014-01-07 (RLVa-1.4.10)
// in place correction for inventory name string
void correctInventoryName(std::string& name);
static void correctInventoryName(std::string& name);
// [/RLVa:KB]
private:
// // in place correction for inventory name string
// void correctInventoryName(std::string& name);
//--------------------------------------------------------------------
// File Support

View File

@ -1573,11 +1573,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// This is an offer from an agent. In this case, the back
// end has already copied the items into your inventory,
// so we can fetch it out of our inventory.
// [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e
if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && (LLAssetType::AT_CATEGORY == mType) &&
(RlvInventory::instance().getSharedRoot()) && (mDesc.find(RLV_PUTINV_PREFIX) == 0) )
// [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0)
if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && (LLAssetType::AT_CATEGORY == mType) && (mDesc.find(RLV_PUTINV_PREFIX) == 0) )
{
RlvGiveToRLVAgentOffer* pOfferObserver = new RlvGiveToRLVAgentOffer(mObjectID);
RlvGiveToRLVAgentOffer* pOfferObserver = new RlvGiveToRLVAgentOffer(mObjectID, mDesc);
pOfferObserver->startFetch();
if (pOfferObserver->isFinished())
pOfferObserver->done();

View File

@ -101,6 +101,8 @@ const S32 RLVa_VERSION_BUILD = 0;
#define RLV_ROOT_FOLDER "#RLV"
#define RLV_CMD_PREFIX '@'
#define RLV_PUTINV_PREFIX "#RLV/~"
#define RLV_PUTINV_SEPARATOR "/"
#define RLV_PUTINV_MAXDEPTH 4
#define RLV_SETROT_OFFSET F_PI_BY_TWO // @setrot is off by 90° with the rest of SL
#define RLV_STRINGS_FILE "rlva_strings.xml"

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2011, Kitty Barnett
* Copyright (c) 2009-2014, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY;
@ -503,6 +503,82 @@ void RlvRenameOnWearObserver::onCategoryCreate(const LLSD& sdData, void* pParam)
// "Give to #RLV" helper classes
//
// Checked: 2014-01-07 (RLVa-1.4.10)
RlvGiveToRLVOffer::RlvGiveToRLVOffer(const std::string& strPath)
{
if (0 == strPath.find(RLV_PUTINV_PREFIX))
{
boost::split(m_DestPath, strPath, boost::is_any_of(std::string(RLV_PUTINV_SEPARATOR)));
}
}
// Checked: 2014-01-07 (RLVa-1.4.10)
bool RlvGiveToRLVOffer::createDestinationFolder()
{
// NOTE: derived classes will delete the instance in their onDestinationCreated override, so don't do anything after triggering the callback
if ( (m_DestPath.size() >= 2) && (m_DestPath.size() <= RLV_PUTINV_MAXDEPTH) )
{
const std::string strFolder = m_DestPath.front();
if (RLV_ROOT_FOLDER == strFolder)
{
m_DestPath.pop_front();
const LLUUID& idRlvRoot = RlvInventory::instance().getSharedRootID();
if (idRlvRoot.notNull())
{
onCategoryCreateCallback(LLSD().with("folder_id", idRlvRoot), this);
}
else
{
const LLUUID idTemp = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, RLV_ROOT_FOLDER, onCategoryCreateCallback, (void*)this);
if (idTemp.notNull())
onCategoryCreateCallback(LLSD().with("folder_id", idTemp), this);
}
return true;
}
}
m_DestPath.clear();
return false;
}
// Checked: 2014-01-07 (RLVa-1.4.10)
void RlvGiveToRLVOffer::onCategoryCreateCallback(const LLSD& sdData, void* pInstance)
{
RlvGiveToRLVOffer* pThis = (RlvGiveToRLVOffer*)pInstance;
LLUUID idFolder = sdData["folder_id"].asUUID();
if (idFolder.isNull())
{
// Problem encountered, abort move
pThis->onDestinationCreated(LLUUID::null, LLStringUtil::null);
return;
}
while (pThis->m_DestPath.size() > 1)
{
std::string strFolder = pThis->m_DestPath.front();
pThis->m_DestPath.pop_front();
LLViewerInventoryCategory* pFolder = RlvInventory::instance().getSharedFolder(idFolder, strFolder);
if (pFolder)
{
idFolder = pFolder->getUUID();
}
else
{
LLInventoryObject::correctInventoryName(strFolder);
const LLUUID idTemp = gInventory.createNewCategory(idFolder, LLFolderType::FT_NONE, strFolder, onCategoryCreateCallback, pInstance);
if (idTemp.notNull())
onCategoryCreateCallback(LLSD().with("folder_id", idTemp), pInstance);
return;
}
}
// Destination folder should exist at this point (we'll be deallocated when the function returns)
pThis->onDestinationCreated(idFolder, pThis->m_DestPath.front());
}
// Checked: 2010-04-18 (RLVa-1.2.0e) | Added: RLVa-1.2.0e
void RlvGiveToRLVTaskOffer::changed(U32 mask)
{
@ -568,7 +644,7 @@ void RlvGiveToRLVTaskOffer::doneIdle()
delete this;
}
// Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e
// Checked: 2010-04-18 (RLVa-1.2.0)
void RlvGiveToRLVAgentOffer::done()
{
gInventory.removeObserver(this);
@ -577,33 +653,42 @@ void RlvGiveToRLVAgentOffer::done()
doOnIdleOneTime(boost::bind(&RlvGiveToRLVAgentOffer::doneIdle, this));
}
// Checked: 2010-04-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0e
// Checked: 2014-01-07 (RLVa-1.4.10)
void RlvGiveToRLVAgentOffer::doneIdle()
{
const LLViewerInventoryCategory* pRlvRoot = RlvInventory::instance().getSharedRoot();
const LLViewerInventoryCategory* pFolder = (mComplete.size()) ? gInventory.getCategory(mComplete[0]) : NULL;
if ( (pRlvRoot) && (pFolder) )
if (!createDestinationFolder())
{
std::string strName = pFolder->getName();
if (strName.find(RLV_PUTINV_PREFIX) == 0)
delete this;
}
}
// Checked: 2010-04-18 (RLVa-1.2.0)
void RlvGiveToRLVAgentOffer::onDestinationCreated(const LLUUID& idFolder, const std::string& strName)
{
if (idFolder.notNull())
{
const LLViewerInventoryCategory* pTarget = gInventory.getCategory(idFolder);
const LLViewerInventoryCategory* pFolder = (mComplete.size()) ? gInventory.getCategory(mComplete[0]) : NULL;
if ( (pTarget) && (pFolder) )
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate updOldParent(pFolder->getParentUUID(), -1);
update.push_back(updOldParent);
LLInventoryModel::LLCategoryUpdate updNewParent(pRlvRoot->getUUID(), 1);
LLInventoryModel::LLCategoryUpdate updNewParent(pTarget->getUUID(), 1);
update.push_back(updNewParent);
gInventory.accountForUpdate(update);
LLPointer<LLViewerInventoryCategory> pNewFolder = new LLViewerInventoryCategory(pFolder);
pNewFolder->setParent(pRlvRoot->getUUID());
pNewFolder->setParent(pTarget->getUUID());
pNewFolder->updateParentOnServer(FALSE);
pNewFolder->rename(strName.erase(0, strName.find(RLV_FOLDER_PREFIX_PUTINV)));
pNewFolder->rename(strName);
pNewFolder->updateServer(FALSE);
gInventory.updateCategory(pNewFolder);
gInventory.notifyObservers();
}
}
delete this;
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2011, Kitty Barnett
* Copyright (c) 2009-2014, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY;
@ -118,6 +118,22 @@ protected:
// "Give to #RLV" helper classes
//
class RlvGiveToRLVOffer
{
protected:
RlvGiveToRLVOffer(const std::string& strPath);
virtual ~RlvGiveToRLVOffer() {}
protected:
bool createDestinationFolder();
virtual void onDestinationCreated(const LLUUID& idFolder, const std::string& strName) = 0;
private:
static void onCategoryCreateCallback(const LLSD& sdData, void* pInstance);
private:
std::list<std::string> m_DestPath;
};
// [See LLInventoryTransactionObserver which says it's not entirely complete?]
// NOTE: the offer may span mulitple BulkUpdateInventory messages so if we're no longer around then (ie due to "delete this") then
// we'll miss those; in this specific case we only care about the *folder* though and that will be in the very first message
@ -135,13 +151,17 @@ protected:
LLUUID m_idTransaction;
};
class RlvGiveToRLVAgentOffer : public LLInventoryFetchDescendentsObserver
class RlvGiveToRLVAgentOffer : public LLInventoryFetchDescendentsObserver, RlvGiveToRLVOffer
{
public:
RlvGiveToRLVAgentOffer(const LLUUID& idFolder) : LLInventoryFetchDescendentsObserver(idFolder) {}
RlvGiveToRLVAgentOffer(const LLUUID& idFolder, const std::string& strDestPath) : LLInventoryFetchDescendentsObserver(idFolder), RlvGiveToRLVOffer(strDestPath) {}
/*virtual*/ ~RlvGiveToRLVAgentOffer() {}
public:
/*virtual*/ void done();
protected:
void doneIdle();
void doneIdle();
/*virtual*/ void onDestinationCreated(const LLUUID& idFolder, const std::string& strName);
};
// ============================================================================