513 lines
18 KiB
C++
513 lines
18 KiB
C++
/**
|
|
* @file llfloaterlinkreplace.cpp
|
|
* @brief Allows replacing link targets in inventory links
|
|
* @author Ansariel Hiller
|
|
*
|
|
* $LicenseInfo:firstyear=2017&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2017, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llfloaterlinkreplace.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llappearancemgr.h"
|
|
#include "lllineeditor.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "llnotifications.h"
|
|
#include "lltextbox.h"
|
|
#include "llviewercontrol.h"
|
|
|
|
LLFloaterLinkReplace::LLFloaterLinkReplace(const LLSD& key)
|
|
: LLFloater(key),
|
|
LLEventTimer(gSavedSettings.getF32("LinkReplaceBatchPauseTime")),
|
|
mRemainingItems(0),
|
|
mSourceUUID(LLUUID::null),
|
|
mTargetUUID(LLUUID::null),
|
|
mBatchSize(gSavedSettings.getU32("LinkReplaceBatchSize")),
|
|
mActiveItems(0),
|
|
mDeleteOnly(false) // <FS:Ansariel> FIRE-17695 - Delete links capability
|
|
{
|
|
mEventTimer.stop();
|
|
|
|
LL_INFOS() << "Link replace settings: Batch size = " << mBatchSize << " - Pause time = " << mPeriod << LL_ENDL;
|
|
}
|
|
|
|
LLFloaterLinkReplace::~LLFloaterLinkReplace()
|
|
{
|
|
}
|
|
|
|
BOOL LLFloaterLinkReplace::postBuild()
|
|
{
|
|
childSetVisible("delete_text", false); // <FS:Beq> FIRE-17695 - Delete links capability
|
|
mStartBtn = getChild<LLButton>("btn_start");
|
|
mStartBtn->setCommitCallback(boost::bind(&LLFloaterLinkReplace::onStartClicked, this));
|
|
|
|
mRefreshBtn = getChild<LLButton>("btn_refresh");
|
|
mRefreshBtn->setCommitCallback(boost::bind(&LLFloaterLinkReplace::checkEnableStart, this));
|
|
// <FS:Beq> FIRE-17695 - Delete links capability
|
|
mDeleteOnlyToggle = getChild<LLCheckBoxCtrl>("delete_links_only");
|
|
mDeleteOnlyToggle->setCommitCallback(boost::bind(&LLFloaterLinkReplace::onDeleteOnlyToggle, this));
|
|
// </FS:Beq>
|
|
mSourceEditor = getChild<LLInventoryLinkReplaceDropTarget>("source_uuid_editor");
|
|
mTargetEditor = getChild<LLInventoryLinkReplaceDropTarget>("target_uuid_editor");
|
|
|
|
mSourceEditor->setDADCallback(boost::bind(&LLFloaterLinkReplace::onSourceItemDrop, this, _1));
|
|
mTargetEditor->setDADCallback(boost::bind(&LLFloaterLinkReplace::onTargetItemDrop, this, _1));
|
|
|
|
mStatusText = getChild<LLTextBox>("status_text");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LLFloaterLinkReplace::onOpen(const LLSD& key)
|
|
{
|
|
if (key.asUUID().notNull())
|
|
{
|
|
LLUUID item_id = key.asUUID();
|
|
LLViewerInventoryItem* item = gInventory.getItem(item_id);
|
|
mSourceEditor->setItem(item);
|
|
onSourceItemDrop(item->getLinkedUUID());
|
|
}
|
|
else
|
|
{
|
|
checkEnableStart();
|
|
}
|
|
}
|
|
|
|
void LLFloaterLinkReplace::onSourceItemDrop(const LLUUID& source_item_id)
|
|
{
|
|
mSourceUUID = source_item_id;
|
|
checkEnableStart();
|
|
}
|
|
|
|
void LLFloaterLinkReplace::onTargetItemDrop(const LLUUID& target_item_id)
|
|
{
|
|
mTargetUUID = target_item_id;
|
|
checkEnableStart();
|
|
}
|
|
|
|
// <FS:Beq> FIRE-17695 - Delete links capability
|
|
void LLFloaterLinkReplace::onDeleteOnlyToggle()
|
|
{
|
|
auto enabled = mDeleteOnlyToggle->getValue().asBoolean();
|
|
mTargetEditor->setEnabled(!enabled);
|
|
mTargetEditor->setVisible(!enabled);
|
|
childSetVisible("target_label", !enabled);
|
|
childSetVisible("delete_text", enabled);
|
|
mDeleteOnly = enabled;
|
|
if (mDeleteOnly)
|
|
{
|
|
mTargetEditor->setItem(nullptr);
|
|
mTargetUUID.setNull();
|
|
}
|
|
checkEnableStart();
|
|
}
|
|
// </FS:Beq>
|
|
|
|
void LLFloaterLinkReplace::updateFoundLinks()
|
|
{
|
|
LLInventoryModel::item_array_t items;
|
|
LLInventoryModel::cat_array_t cat_array;
|
|
LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
|
|
gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
|
|
cat_array,
|
|
items,
|
|
LLInventoryModel::INCLUDE_TRASH,
|
|
is_linked_item_match);
|
|
mRemainingItems = (U32)items.size();
|
|
|
|
LLStringUtil::format_map_t args;
|
|
args["NUM"] = llformat("%d", mRemainingItems);
|
|
mStatusText->setText(getString("ItemsFound", args));
|
|
}
|
|
|
|
void LLFloaterLinkReplace::checkEnableStart()
|
|
{
|
|
if (mSourceUUID.notNull() && mTargetUUID.notNull() && mSourceUUID == mTargetUUID)
|
|
{
|
|
mStatusText->setText(getString("ItemsIdentical"));
|
|
}
|
|
else if (mSourceUUID.notNull())
|
|
{
|
|
updateFoundLinks();
|
|
}
|
|
// <FS:Beq> FIRE-17695 - Delete links capability
|
|
// mStartBtn->setEnabled(mRemainingItems > 0 && mSourceUUID.notNull() && mTargetUUID.notNull() && mSourceUUID != mTargetUUID);
|
|
bool enable = mRemainingItems > 0 && (
|
|
(mDeleteOnly && mSourceUUID.notNull() ) ||
|
|
(mSourceUUID.notNull() && mTargetUUID.notNull() && mSourceUUID != mTargetUUID));
|
|
|
|
mStartBtn->setEnabled(enable);
|
|
// </FS:Beq>
|
|
}
|
|
|
|
void LLFloaterLinkReplace::onStartClicked()
|
|
{
|
|
LL_INFOS() << "Starting inventory link replace" << LL_ENDL;
|
|
// <FS:Beq> FIRE-17695 - option to bulk delete links.
|
|
// if (mSourceUUID.isNull() || mTargetUUID.isNull())
|
|
if (!mDeleteOnly && (mSourceUUID.isNull() || mTargetUUID.isNull()))
|
|
// </FS:Beq>
|
|
{
|
|
LL_WARNS() << "Cannot replace. Either source or target UUID is null." << LL_ENDL;
|
|
return;
|
|
}
|
|
|
|
// <FS:Beq> FIRE-17695 - option to bulk delete links.
|
|
if (!mDeleteOnly && mSourceUUID.isNull())
|
|
{
|
|
LL_WARNS() << "Cannot delete links. Source UUID is null." << LL_ENDL;
|
|
return;
|
|
}
|
|
// </FS:Beq>
|
|
|
|
if (mSourceUUID == mTargetUUID)
|
|
{
|
|
LL_WARNS() << "Cannot replace. Source and target are identical." << LL_ENDL;
|
|
return;
|
|
}
|
|
|
|
const LLUUID& source_item_id = gInventory.getLinkedItemID(mSourceUUID);
|
|
LLViewerInventoryItem *source_item = gInventory.getItem(source_item_id);
|
|
const LLUUID& target_item_id = gInventory.getLinkedItemID(mTargetUUID);
|
|
LLViewerInventoryItem *target_item = gInventory.getItem(target_item_id);
|
|
|
|
|
|
LLNotification::Params params("ConfirmReplaceLink");
|
|
params.functor.function(boost::bind(&LLFloaterLinkReplace::onStartClickedResponse, this, _1, _2));
|
|
if (source_item && source_item->isWearableType() && source_item->getWearableType() <= LLWearableType::WT_EYES)
|
|
{
|
|
if(target_item && target_item->isWearableType() && source_item->getWearableType() == target_item->getWearableType())
|
|
{
|
|
LLNotifications::instance().forceResponse(params, 0);
|
|
}
|
|
else
|
|
{
|
|
LLSD args;
|
|
args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType());
|
|
params.substitutions(args);
|
|
LLNotifications::instance().add(params);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LLNotifications::instance().forceResponse(params, 0);
|
|
}
|
|
}
|
|
|
|
void LLFloaterLinkReplace::onStartClickedResponse(const LLSD& notification, const LLSD& response)
|
|
{
|
|
|
|
if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
|
|
{
|
|
|
|
LLInventoryModel::cat_array_t cat_array;
|
|
LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
|
|
gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
|
|
cat_array,
|
|
mRemainingInventoryItems,
|
|
LLInventoryModel::INCLUDE_TRASH,
|
|
is_linked_item_match);
|
|
LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
|
|
|
|
if (mRemainingInventoryItems.size() > 0)
|
|
{
|
|
LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
|
|
// <FS:Beq> FIRE-17695 - option to bulk delete links.
|
|
//if (target_item)
|
|
if (target_item || mDeleteOnly)
|
|
// </FS:Beq>
|
|
{
|
|
mRemainingItems = (U32)mRemainingInventoryItems.size();
|
|
|
|
LLStringUtil::format_map_t args;
|
|
args["NUM"] = llformat("%d", mRemainingItems);
|
|
mStatusText->setText(getString("ItemsRemaining", args));
|
|
|
|
mStartBtn->setEnabled(FALSE);
|
|
mRefreshBtn->setEnabled(FALSE);
|
|
|
|
mEventTimer.start();
|
|
tick();
|
|
}
|
|
else
|
|
{
|
|
mStatusText->setText(getString("TargetNotFound"));
|
|
LL_WARNS() << "Link replace target not found." << LL_ENDL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// static
|
|
void LLFloaterLinkReplace::linkCreatedCallback(LLHandle<LLFloaterLinkReplace> floater_handle, const LLUUID& old_item_id, const LLUUID& target_item_id,
|
|
bool needs_wearable_ordering_update, bool needs_description_update, const LLUUID& outfit_folder_id)
|
|
{
|
|
LL_DEBUGS() << "Inventory link replace:" << LL_NEWLINE
|
|
<< " - old_item_id = " << old_item_id.asString() << LL_NEWLINE
|
|
<< " - target_item_id = " << target_item_id.asString() << LL_NEWLINE
|
|
<< " - order update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE
|
|
<< " - description update = " << (needs_description_update ? "true" : "false") << LL_NEWLINE
|
|
<< " - outfit_folder_id = " << outfit_folder_id.asString() << LL_ENDL;
|
|
|
|
// If we are replacing an object, bodypart or gesture link within an outfit folder,
|
|
// we need to change the actual description of the link itself. LLAppearanceMgr *should*
|
|
// have created COF links that will be used to save the outfit with an empty description.
|
|
// Since link_inventory_array() will set the description of the linked item for the link
|
|
// itself, this will lead to a dirty outfit state when the outfit with the replaced
|
|
// link is worn. So we have to correct this.
|
|
if (needs_description_update && outfit_folder_id.notNull())
|
|
{
|
|
LLInventoryModel::item_array_t items;
|
|
LLInventoryModel::cat_array_t cats;
|
|
LLLinkedItemIDMatches is_target_link(target_item_id);
|
|
gInventory.collectDescendentsIf(outfit_folder_id,
|
|
cats,
|
|
items,
|
|
LLInventoryModel::EXCLUDE_TRASH,
|
|
is_target_link);
|
|
|
|
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
|
|
{
|
|
LLPointer<LLViewerInventoryItem> item = *it;
|
|
|
|
if ((item->getType() == LLAssetType::AT_BODYPART ||
|
|
item->getType() == LLAssetType::AT_OBJECT ||
|
|
item->getType() == LLAssetType::AT_GESTURE)
|
|
&& !item->getActualDescription().empty())
|
|
{
|
|
LL_DEBUGS() << "Updating description for " << item->getName() << LL_ENDL;
|
|
|
|
LLSD updates;
|
|
updates["desc"] = "";
|
|
update_inventory_item(item->getUUID(), updates, LLPointer<LLInventoryCallback>(NULL));
|
|
}
|
|
}
|
|
}
|
|
|
|
LLUUID outfit_update_folder = LLUUID::null;
|
|
if (needs_wearable_ordering_update && outfit_folder_id.notNull())
|
|
{
|
|
// If a wearable item was involved in the link replace operation and replaced
|
|
// a link in an outfit folder, we need to update the clothing ordering information
|
|
// *after* the original link has been removed. LLAppearanceMgr abuses the actual link
|
|
// description to store the clothing ordering information it. We will have to update
|
|
// the clothing ordering information or the outfit will be in dirty state when worn.
|
|
outfit_update_folder = outfit_folder_id;
|
|
}
|
|
|
|
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::itemRemovedCallback, floater_handle, outfit_update_folder));
|
|
remove_inventory_object(old_item_id, cb);
|
|
}
|
|
|
|
// static
|
|
void LLFloaterLinkReplace::itemRemovedCallback(LLHandle<LLFloaterLinkReplace> floater_handle, const LLUUID& outfit_folder_id)
|
|
{
|
|
if (outfit_folder_id.notNull())
|
|
{
|
|
LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(outfit_folder_id);
|
|
}
|
|
|
|
if (!floater_handle.isDead())
|
|
{
|
|
floater_handle.get()->decreaseOpenItemCount();
|
|
}
|
|
}
|
|
|
|
void LLFloaterLinkReplace::decreaseOpenItemCount()
|
|
{
|
|
mActiveItems--;
|
|
mRemainingItems--;
|
|
|
|
if (mRemainingItems == 0)
|
|
{
|
|
mStatusText->setText(getString("ReplaceFinished"));
|
|
mStartBtn->setEnabled(TRUE);
|
|
mRefreshBtn->setEnabled(TRUE);
|
|
mEventTimer.stop();
|
|
LL_INFOS() << "Inventory link replace finished." << LL_ENDL;
|
|
}
|
|
else
|
|
{
|
|
LLStringUtil::format_map_t args;
|
|
args["NUM"] = llformat("%d", mRemainingItems);
|
|
mStatusText->setText(getString("ItemsRemaining", args));
|
|
LL_DEBUGS() << "Inventory link replace: " << mRemainingItems << " links remaining..." << LL_ENDL;
|
|
}
|
|
}
|
|
|
|
BOOL LLFloaterLinkReplace::tick()
|
|
{
|
|
LL_DEBUGS() << "Calling tick - remaining items = " << mRemainingInventoryItems.size() << LL_ENDL;
|
|
|
|
LLInventoryModel::item_array_t current_batch;
|
|
|
|
for (U32 i = 0; i < mBatchSize && mActiveItems <= 250; ++i, ++mActiveItems)
|
|
{
|
|
if (!mRemainingInventoryItems.size())
|
|
{
|
|
mEventTimer.stop();
|
|
break;
|
|
}
|
|
|
|
current_batch.push_back(mRemainingInventoryItems.back());
|
|
mRemainingInventoryItems.pop_back();
|
|
}
|
|
processBatch(current_batch);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
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);
|
|
|
|
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
|
|
{
|
|
LLPointer<LLInventoryItem> source_item = *it;
|
|
|
|
if (source_item->getParentUUID() != cof_folder_id)
|
|
{
|
|
// <FS:Beq> FIRE-17695 bulk delete unwanted links
|
|
//bool is_outfit_folder = gInventory.isObjectDescendentOf(source_item->getParentUUID(), outfit_folder_id);
|
|
//// If either the new or old item in the COF is a wearable, we need to update wearable ordering after the link has been replaced
|
|
//bool needs_wearable_ordering_update = (is_outfit_folder && source_item->getType() == LLAssetType::AT_CLOTHING) || target_item->getType() == LLAssetType::AT_CLOTHING;
|
|
//// Other items in the COF need a description update (description of the actual link item must be empty)
|
|
//bool needs_description_update = is_outfit_folder && target_item->getType() != LLAssetType::AT_CLOTHING;
|
|
|
|
//LL_DEBUGS() << "is_outfit_folder = " << (is_outfit_folder ? "true" : "false") << LL_NEWLINE
|
|
// << "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE
|
|
// << "needs_description_update = " << (needs_description_update ? "true" : "false") << LL_ENDL;
|
|
|
|
//LLInventoryObject::const_object_list_t obj_array;
|
|
//obj_array.push_back(LLConstPointer<LLInventoryObject>(target_item));
|
|
//LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::linkCreatedCallback,
|
|
// getDerivedHandle<LLFloaterLinkReplace>(),
|
|
// source_item->getUUID(),
|
|
// target_item->getUUID(),
|
|
// needs_wearable_ordering_update,
|
|
// needs_description_update,
|
|
// (is_outfit_folder ? source_item->getParentUUID() : LLUUID::null) ));
|
|
//link_inventory_array(source_item->getParentUUID(), obj_array, cb);
|
|
|
|
bool is_outfit_folder = gInventory.isObjectDescendentOf(source_item->getParentUUID(), outfit_folder_id);
|
|
// If either the new or old item in the COF is a wearable, we need to update wearable ordering after the link has been replaced
|
|
bool needs_wearable_ordering_update = (is_outfit_folder && source_item->getType() == LLAssetType::AT_CLOTHING) || (!mDeleteOnly && target_item->getType() == LLAssetType::AT_CLOTHING);
|
|
// Other items in the COF need a description update (description of the actual link item must be empty)
|
|
bool needs_description_update = !mDeleteOnly && is_outfit_folder && target_item->getType() != LLAssetType::AT_CLOTHING;
|
|
|
|
LL_DEBUGS() << "is_outfit_folder = " << (is_outfit_folder ? "true" : "false") << LL_NEWLINE
|
|
<< "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE
|
|
<< "needs_description_update = " << (needs_description_update ? "true" : "false") << LL_ENDL;
|
|
|
|
if (!mDeleteOnly)
|
|
{
|
|
LLInventoryObject::const_object_list_t obj_array;
|
|
obj_array.push_back(LLConstPointer<LLInventoryObject>(target_item));
|
|
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::linkCreatedCallback,
|
|
getDerivedHandle<LLFloaterLinkReplace>(),
|
|
source_item->getUUID(),
|
|
target_item->getUUID(),
|
|
needs_wearable_ordering_update,
|
|
needs_description_update,
|
|
(is_outfit_folder ? source_item->getParentUUID() : LLUUID::null)));
|
|
link_inventory_array(source_item->getParentUUID(), obj_array, cb);
|
|
}
|
|
else
|
|
{
|
|
LLUUID outfit_update_folder_id = LLUUID::null;
|
|
if (needs_wearable_ordering_update)
|
|
{
|
|
outfit_update_folder_id = source_item->getParentUUID();
|
|
}
|
|
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::itemRemovedCallback, getDerivedHandle<LLFloaterLinkReplace>(), outfit_update_folder_id));
|
|
remove_inventory_object(source_item->getUUID(), cb);
|
|
LL_INFOS() << "Requested delete of " << source_item->getUUID() << LL_ENDL;
|
|
}
|
|
// </FS:Beq>
|
|
}
|
|
else
|
|
{
|
|
decreaseOpenItemCount();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// LLInventoryLinkReplaceDropTarget
|
|
|
|
static LLDefaultChildRegistry::Register<LLInventoryLinkReplaceDropTarget> r("inventory_link_replace_drop_target");
|
|
|
|
BOOL LLInventoryLinkReplaceDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
|
EDragAndDropType cargo_type,
|
|
void* cargo_data,
|
|
EAcceptance* accept,
|
|
std::string& tooltip_msg)
|
|
{
|
|
LLInventoryItem* item = (LLInventoryItem*)cargo_data;
|
|
|
|
if (cargo_type >= DAD_TEXTURE && cargo_type <= DAD_LINK &&
|
|
item && item->getActualType() != LLAssetType::AT_LINK_FOLDER && item->getType() != LLAssetType::AT_CATEGORY &&
|
|
(
|
|
LLAssetType::lookupCanLink(item->getType()) ||
|
|
(item->getType() == LLAssetType::AT_LINK && !gInventory.getObject(item->getLinkedUUID())) // Broken Link!
|
|
))
|
|
{
|
|
if (drop)
|
|
{
|
|
setItem(item);
|
|
if (!mDADSignal.empty())
|
|
{
|
|
mDADSignal(mItemID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*accept = ACCEPT_YES_SINGLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*accept = ACCEPT_NO;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LLInventoryLinkReplaceDropTarget::setItem(LLInventoryItem* item)
|
|
{
|
|
if (item)
|
|
{
|
|
mItemID = item->getLinkedUUID();
|
|
setText(item->getName());
|
|
}
|
|
else
|
|
{
|
|
mItemID.setNull();
|
|
setText(LLStringExplicit(""));
|
|
}
|
|
}
|