Files
SingularityViewer/indra/newview/llpanelobjectinventory.cpp
Lirusaito 0846f8a963 Fixeds and ToDones
-Color Fixies-
Fixed Gemini skin not looking as it originally did.
We now use DefaultListText to color all otherwise uncolored text in scroll list cells.
All of our dark skins have been updated to use white here, as dark skins are intended to have white text...
This includes the Dark we ship with.

LLFloaterActiveSpeakers no longer uses hard coded font colors, it uses SpeakersInactive, DefaultListText, and SpeakersGhost.

LLFloaterAvatarList no longer uses hard coded font colors, it uses DefaultListText, RadarTextChatRange, RadarTextShoutRange, and RadarTextDrawDist, in place of previously hard coded font colors
Since the tooltip defines color meaning, these new colors should only be skinned to change shade.

DefaultListText defaults to black; SpeaksInactive, gray(grey4); SpeakersGhost, Red; RadarTextChatRange, Red; RadarTextShoutRange, Yellow(yellow1); RadarTextDrawDist, Green(green2).


-Translation update and fixies-
Partial credit to viewer-development, thanks for hanging onto old strings!  Also, updated to look more like v-d in translated areas.
Punctuation strings can be used quite a lot.  Brought them all in, just in case.

AscentPrefs*:
Drag and Drop points now use CurrentlySetTo, CurrentlyNotSet, AnItemNotOnThisAccount, and NotLoggedIn. (applies, as well, to FloaterAO)
Power User message is now built from PowerUser1, PowerUser2, Unlocked:, PowerUser3, RightClick, PowerUser4 and PowerUser5; this should give translators enough space to explain any tough to translate, and make the message easier to alter in the future, if necessary.

LLCompileQueue:
Now uses translation strings from upstream
Starting, Done, Resetting, Running, and NotRunning in its xml.
CompileQueueTitle, CompileQueueStart, CompileQueueDownloadedCompiling, CompileQueueScriptNotFound, CompileQueueProblemDownloading, CompileQueueInsufficientPermDownload, CompileQueueInsufficientPermFor, CompileQueueUnknownFailure, ResetQueueTitle, ResetQueueStart, NotRunQueueTitle, and NotRunQueueStart from strings.

LLFloaterAvatarList(floater_radar) now uses has_entered, has_left, the_sim, draw_distance, shout_range, and chat_range in its xml for translatable alerts.

LLFloaterLand(floater_about_land) now uses minutes, 1_minute, 1_second, seconds, and remaining from its xml.
LLFloaterLand, LLFolderView, LLPanelDirBrowser now make use of InventoryNoMatchingItems, NoneFound, and Searching in their searches.
LLFolderView was brought closer to v-d in translation.

LLGroupNotify now uses GroupNotifyGroupNotice, GroupNotifySentBy, GroupNotifyAttached, next (also now used by LLNotify), ok, GroupNotifyGroupNotices, GroupNotifyViewPastNotices, GroupNotifyOpenAttachment, and GroupNotifySaveAttachment.

LLInventoryFilter synced with V-D for translation:
Now uses Animations, Calling Cards, Clothing, Gestures, Landmarks, Notecards, Objects, Scripts, Sounds, Textures, Snapshots, No Filters, Since Logoff, and Worn.

LLManipRotate now uses Direction_Forward, Direction_Left, Direction_Right, Direction_Back, Direction_North, Direction_South, Direction_West, Direction_East, Direction_Up, and Direction_Down, like upstream v-d.

LLPanelAvatar(panel_avatar) now uses None string in its xml for when there are no groups, also removed cruft. Though the None has not been showing up for quite some time, anyway...

LLPanelObjectInventory now uses Buy, LoadingContents and NoContents,
however the last two strings did not seem to show up anyway...
thanks to Latif Khalifa, Jean Horten, theGenius Indigo and Cubbi Bearcat for confirming this happens across many different versions and on both Windows and linux(32 and 64).

LLPreviewScript now uses CompileSuccessful, SaveComplete, ObjectOutOfRange, and CompileSuccessfulSaving.

LLScrollingPanelParam now translates Less and More.
Avatar Shape Information strings now used for customize appearance panels.

LLTextureCtrl now uses multiple_textures.

LLToolpie has been updated to use v-d include order and now uses UnmuteAvatar, MuteAvatar, UnmuteObject, and MuteObject2 strings.
LLVOAvatarSelf now uses BodyParts* strings for translation of toolpie entries pertaining to bodyparts.

LLViewerMenuFile now uses UnknownFileExtension, and UploadingCosts.

LLViewerMessage now uses Cancel(also used by LLViewerDisplay), AcquiredItems, Saved_message, IM_autoresponse_sent_item, IM_autoresponded_to, IM_announce_incoming, InvOfferDecline, InvOfferGaveYou, InvOfferOwnedByUnknownUser, InvOfferAnObjectNamed, InvOfferOwnedBy, InvOfferOwnedByUnknownGroup, and InvOfferOwnedByGroup.


-AvatarRadar Update-
AvatarRadar enhanced with code from both Cool VL Viewer and some avian corpse.
e_radar_alert_type has been reworked to allow bitwise usage in the future.

Cool stuff:
gSavedSettings for radar are now CachedControls,
entering boolean is now checked before going into the switchcase,
Style changes, yay C++ style.

Avian Flu:
Distance for shout range corrected to be 96.
handleKeyHere: If the user hits enter with an avatar on the radar selected, focus camera on selected avatar; ctrl-enter, teleport to selected avatar.

Otherwise:
Tiny spelling fixies, and a suggestive comment.
2012-08-05 20:40:02 -04:00

1993 lines
55 KiB
C++

/**
* @file llsidepanelinventory.cpp
* @brief LLPanelObjectInventory class implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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$
*/
//*****************************************************************************
//
// Implementation of the panel inventory - used to view and control a
// task's inventory.
//
// *****************************************************************************
#include "llviewerprecompiledheaders.h"
#include "llpanelobjectinventory.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
#include "roles_constants.h"
#include "llagent.h"
#include "llcallbacklist.h"
#include "llfloaterbuycontents.h"
#include "llfloaterbuycurrency.h"
#include "llfolderview.h"
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfilter.h"
#include "llinventoryfunctions.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
#include "llpreviewscript.h"
#include "llpreviewsound.h"
#include "llpreviewtexture.h"
#include "llscrollcontainer.h"
#include "llselectmgr.h"
#include "llstatusbar.h"
#include "lltooldraganddrop.h"
#include "lltrans.h"
#include "llviewerassettype.h"
#include "llviewerinventory.h"
#include "llviewerregion.h"
#include "llviewerobjectlist.h"
#include "llviewermessage.h"
// [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.2.0b)
#include "rlvhandler.h"
#include "rlvlocks.h"
// [/RLVa:KB]
#include "hippogridmanager.h"
///----------------------------------------------------------------------------
/// Class LLTaskInvFVBridge
///----------------------------------------------------------------------------
class LLTaskInvFVBridge : public LLFolderViewEventListener
{
protected:
LLUUID mUUID;
std::string mName;
mutable std::string mDisplayName;
LLPanelObjectInventory* mPanel;
U32 mFlags;
LLAssetType::EType mAssetType;
LLInventoryType::EType mInventoryType;
LLInventoryObject* findInvObject() const;
LLInventoryItem* findItem() const;
public:
LLTaskInvFVBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name,
U32 flags=0);
virtual ~LLTaskInvFVBridge( ) {}
virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }
virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
static LLTaskInvFVBridge* createObjectBridge(LLPanelObjectInventory* panel,
LLInventoryObject* object);
void showProperties();
void buyItem();
S32 getPrice();
static bool commitBuyItem(const LLSD& notification, const LLSD& response);
// LLFolderViewEventListener functionality
virtual const std::string& getName() const;
virtual const std::string& getDisplayName() const;
virtual PermissionMask getPermissionMask() const { return PERM_NONE; }
/*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; }
virtual const LLUUID& getUUID() const { return mUUID; }
virtual time_t getCreationDate() const;
virtual LLUIImagePtr getIcon() const;
virtual void openItem();
virtual BOOL canOpenItem() const { return FALSE; }
virtual void closeItem() {}
virtual void previewItem();
virtual void selectItem() {}
virtual BOOL isItemRenameable() const;
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL isItemMovable() const;
virtual BOOL isItemRemovable() const;
virtual BOOL removeItem();
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
virtual void move(LLFolderViewEventListener* parent_listener);
virtual BOOL isItemCopyable() const;
virtual BOOL copyToClipboard() const;
virtual void cutToClipboard();
virtual BOOL isClipboardPasteable() const;
virtual void pasteFromClipboard();
virtual void pasteLinkFromClipboard();
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual void performAction(LLInventoryModel* model, std::string action);
virtual BOOL isUpToDate() const { return TRUE; }
virtual BOOL hasChildren() const { return FALSE; }
virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }
virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
// LLDragAndDropBridge functionality
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data);
// virtual void dropped();
};
LLTaskInvFVBridge::LLTaskInvFVBridge(
LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name,
U32 flags):
mUUID(uuid),
mName(name),
mPanel(panel),
mFlags(flags),
mAssetType(LLAssetType::AT_NONE),
mInventoryType(LLInventoryType::IT_NONE)
{
const LLInventoryItem *item = findItem();
if (item)
{
mAssetType = item->getType();
mInventoryType = item->getInventoryType();
}
}
LLInventoryObject* LLTaskInvFVBridge::findInvObject() const
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if (object)
{
return object->getInventoryObject(mUUID);
}
return NULL;
}
LLInventoryItem* LLTaskInvFVBridge::findItem() const
{
return dynamic_cast<LLInventoryItem*>(findInvObject());
}
void LLTaskInvFVBridge::showProperties()
{
if(!LLFloaterProperties::show(mUUID, mPanel->getTaskUUID()))
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PropertiesRect");
rect.translate( left - rect.mLeft, top - rect.mTop );
LLFloaterProperties* floater = new LLFloaterProperties("obj item properties",
rect,
"Object Inventory Item Properties",
mUUID,
mPanel->getTaskUUID());
floater->open(); /*Flawfinder: ignore*/
}
}
struct LLBuyInvItemData
{
LLUUID mTaskID;
LLUUID mItemID;
LLAssetType::EType mType;
LLBuyInvItemData(const LLUUID& task,
const LLUUID& item,
LLAssetType::EType type) :
mTaskID(task), mItemID(item), mType(type)
{}
};
void LLTaskInvFVBridge::buyItem()
{
llinfos << "LLTaskInvFVBridge::buyItem()" << llendl;
LLInventoryItem* item = findItem();
if(!item || !item->getSaleInfo().isForSale()) return;
LLBuyInvItemData* inv = new LLBuyInvItemData(mPanel->getTaskUUID(),
mUUID,
item->getType());
const LLSaleInfo& sale_info = item->getSaleInfo();
const LLPermissions& perm = item->getPermissions();
const std::string owner_name; // no owner name currently... FIXME?
LLViewerObject* obj;
if( ( obj = gObjectList.findObject( mPanel->getTaskUUID() ) ) && obj->isAttachment() )
{
LLNotificationsUtil::add("Cannot_Purchase_an_Attachment");
llinfos << "Attempt to purchase an attachment" << llendl;
delete inv;
}
else
{
LLSD args;
args["PRICE"] = llformat("%d",sale_info.getSalePrice());
args["OWNER"] = owner_name;
if (sale_info.getSaleType() != LLSaleInfo::FS_CONTENTS)
{
U32 next_owner_mask = perm.getMaskNextOwner();
args["MODIFYPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_MODIFY) ? "PermYes" : "PermNo");
args["COPYPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_COPY) ? "PermYes" : "PermNo");
args["RESELLPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_TRANSFER) ? "PermYes" : "PermNo");
}
std::string alertdesc;
switch(sale_info.getSaleType())
{
case LLSaleInfo::FS_ORIGINAL:
alertdesc = owner_name.empty() ? "BuyOriginalNoOwner" : "BuyOriginal";
break;
case LLSaleInfo::FS_CONTENTS:
alertdesc = owner_name.empty() ? "BuyContentsNoOwner" : "BuyContents";
break;
case LLSaleInfo::FS_COPY:
default:
alertdesc = owner_name.empty() ? "BuyCopyNoOwner" : "BuyCopy";
break;
}
LLSD payload;
payload["task_id"] = inv->mTaskID;
payload["item_id"] = inv->mItemID;
payload["type"] = inv->mType;
LLNotificationsUtil::add(alertdesc, args, payload, LLTaskInvFVBridge::commitBuyItem);
}
}
S32 LLTaskInvFVBridge::getPrice()
{
LLInventoryItem* item = findItem();
if(item)
{
return item->getSaleInfo().getSalePrice();
}
else
{
return -1;
}
}
// static
bool LLTaskInvFVBridge::commitBuyItem(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(0 == option)
{
LLViewerObject* object = gObjectList.findObject(notification["payload"]["task_id"].asUUID());
if(!object || !object->getRegion()) return false;
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_BuyObjectInventory);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_Data);
msg->addUUIDFast(_PREHASH_ObjectID, notification["payload"]["task_id"].asUUID());
msg->addUUIDFast(_PREHASH_ItemID, notification["payload"]["item_id"].asUUID());
msg->addUUIDFast(_PREHASH_FolderID,
//"type" should be LLAssetType::AssetType, not LLFolderType::EType
gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType((LLAssetType::EType)notification["payload"]["type"].asInteger())));
msg->sendReliable(object->getRegion()->getHost());
}
return false;
}
const std::string& LLTaskInvFVBridge::getName() const
{
return mName;
}
const std::string& LLTaskInvFVBridge::getDisplayName() const
{
LLInventoryItem* item = findItem();
if(item)
{
mDisplayName.assign(item->getName());
const LLPermissions& perm(item->getPermissions());
BOOL copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE);
BOOL mod = gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE);
BOOL xfer = gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE);
if(!copy)
{
mDisplayName.append(LLTrans::getString("no_copy"));
}
if(!mod)
{
mDisplayName.append(LLTrans::getString("no_modify"));
}
if(!xfer)
{
mDisplayName.append(LLTrans::getString("no_transfer"));
}
}
return mDisplayName;
}
// BUG: No creation dates for task inventory
time_t LLTaskInvFVBridge::getCreationDate() const
{
return 0;
}
LLUIImagePtr LLTaskInvFVBridge::getIcon() const
{
const BOOL item_is_multi = (mFlags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS);
return LLInventoryIcon::getIcon(mAssetType, mInventoryType, 0, item_is_multi );
}
void LLTaskInvFVBridge::openItem()
{
// no-op.
lldebugs << "LLTaskInvFVBridge::openItem()" << llendl;
}
void LLTaskInvFVBridge::previewItem()
{
openItem();
}
BOOL LLTaskInvFVBridge::isItemRenameable() const
{
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachment(object->getRootEdit())) )
{
return FALSE;
}
// [/RLVa:KB]
if(gAgent.isGodlike()) return TRUE;
// LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
LLInventoryItem* item = (LLInventoryItem*)(object->getInventoryObject(mUUID));
if(item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
GP_OBJECT_MANIPULATE, GOD_LIKE))
{
return TRUE;
}
}
return FALSE;
}
BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name)
{
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachment(object->getRootEdit())) )
{
return FALSE;
}
// [/RLVa:KB]
// LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
LLViewerInventoryItem* item = NULL;
item = (LLViewerInventoryItem*)object->getInventoryObject(mUUID);
if(item && (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
GP_OBJECT_MANIPULATE, GOD_LIKE)))
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->rename(new_name);
object->updateInventory(
new_item,
TASK_INVENTORY_ITEM_KEY,
false);
}
}
return TRUE;
}
BOOL LLTaskInvFVBridge::isItemMovable() const
{
//LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
//if(object && (object->permModify() || gAgent.isGodlike()))
//{
// return TRUE;
//}
//return FALSE;
// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-1.0.5a
if (rlv_handler_t::isEnabled())
{
const LLViewerObject* pObj = gObjectList.findObject(mPanel->getTaskUUID());
if (pObj)
{
if (gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))
{
return FALSE;
}
else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) )
{
LLVOAvatar* pAvatar = gAgentAvatarp;
if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == pObj->getRootEdit()) )
return FALSE;
}
}
}
// [/RLVa:KB]
return TRUE;
}
BOOL LLTaskInvFVBridge::isItemRemovable() const
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-1.0.5a
if ( (object) && (rlv_handler_t::isEnabled()) )
{
const LLViewerObject* pObjRoot = object->getRootEdit();
if (gRlvAttachmentLocks.isLockedAttachment(pObjRoot))
{
return FALSE;
}
else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) )
{
LLVOAvatar* pAvatar = gAgentAvatarp;
if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == pObjRoot) )
return FALSE;
}
}
// [/RLVa:KB]
if(object
&& (object->permModify() || object->permYouOwner()))
{
return TRUE;
}
return FALSE;
}
bool remove_task_inventory_callback(const LLSD& notification, const LLSD& response, LLPanelObjectInventory* panel)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLViewerObject* object = gObjectList.findObject(notification["payload"]["task_id"].asUUID());
if(option == 0 && object)
{
// yes
LLSD::array_const_iterator list_end = notification["payload"]["inventory_ids"].endArray();
for (LLSD::array_const_iterator list_it = notification["payload"]["inventory_ids"].beginArray();
list_it != list_end;
++list_it)
{
object->removeInventory(list_it->asUUID());
}
// refresh the UI.
panel->refresh();
}
return false;
}
// helper for remove
// ! REFACTOR ! two_uuids_list_t is also defined in llinventorybridge.h, but differently.
typedef std::pair<LLUUID, std::list<LLUUID> > panel_two_uuids_list_t;
typedef std::pair<LLPanelObjectInventory*, panel_two_uuids_list_t> remove_data_t;
BOOL LLTaskInvFVBridge::removeItem()
{
if(isItemRemovable() && mPanel)
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
if(object->permModify())
{
// just do it.
object->removeInventory(mUUID);
return TRUE;
}
else
{
LLSD payload;
payload["task_id"] = mPanel->getTaskUUID();
payload["inventory_ids"].append(mUUID);
LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel));
return FALSE;
}
}
}
return FALSE;
}
void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
{
if (!mPanel)
{
return;
}
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if (!object)
{
return;
}
if (!object->permModify())
{
LLSD payload;
payload["task_id"] = mPanel->getTaskUUID();
for (S32 i = 0; i < (S32)batch.size(); i++)
{
LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i];
payload["inventory_ids"].append(itemp->getUUID());
}
LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel));
}
else
{
for (S32 i = 0; i < (S32)batch.size(); i++)
{
LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i];
if(itemp->isItemRemovable())
{
// just do it.
object->removeInventory(itemp->getUUID());
}
}
}
}
void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener)
{
}
BOOL LLTaskInvFVBridge::isItemCopyable() const
{
LLInventoryItem* item = findItem();
if(!item) return FALSE;
return gAgent.allowOperation(PERM_COPY, item->getPermissions(),
GP_OBJECT_MANIPULATE);
}
BOOL LLTaskInvFVBridge::copyToClipboard() const
{
return FALSE;
}
void LLTaskInvFVBridge::cutToClipboard()
{
}
BOOL LLTaskInvFVBridge::isClipboardPasteable() const
{
return FALSE;
}
void LLTaskInvFVBridge::pasteFromClipboard()
{
}
void LLTaskInvFVBridge::pasteLinkFromClipboard()
{
}
BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
//llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
if(mPanel)
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
LLInventoryItem* inv = NULL;
if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID)))
{
const LLPermissions& perm = inv->getPermissions();
bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
GP_OBJECT_MANIPULATE);
// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a
// Kind of redundant due to the note below, but in case that ever gets fixed
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachment(object->getRootEdit())) )
{
return FALSE;
}
// [/RLVa:KB]
if (object->isAttachment() && !can_copy)
{
//RN: no copy contents of attachments cannot be dragged out
// due to a race condition and possible exploit where
// attached objects do not update their inventory items
// when their contents are manipulated
return FALSE;
}
if((can_copy && perm.allowTransferTo(gAgent.getID()))
|| object->permYouOwner())
// || gAgent.isGodlike())
{
*type = LLViewerAssetType::lookupDragAndDropType(inv->getType());
*id = inv->getUUID();
return TRUE;
}
}
}
}
return FALSE;
}
BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data)
{
//llinfos << "LLTaskInvFVBridge::dragOrDrop()" << llendl;
return FALSE;
}
//void LLTaskInvFVBridge::dropped()
//{
// llwarns << "LLTaskInvFVBridge::dropped() - not implemented" << llendl;
//}
// virtual
void LLTaskInvFVBridge::performAction(LLInventoryModel* model, std::string action)
{
if (action == "task_buy")
{
// Check the price of the item.
S32 price = getPrice();
if (-1 == price)
{
llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
}
else
{
if (price > 0 && price > gStatusBar->getBalance())
{
LLFloaterBuyCurrency::buyCurrency("This costs", price);
}
else
{
buyItem();
}
}
}
else if (action == "task_open")
{
openItem();
}
else if (action == "task_properties")
{
showProperties();
}
}
void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
LLInventoryItem* item = findItem();
std::vector<std::string> items;
std::vector<std::string> disabled_items;
if (!item)
{
hide_context_entries(menu, items, disabled_items);
return;
}
if(gAgent.allowOperation(PERM_OWNER, item->getPermissions(),
GP_OBJECT_MANIPULATE)
&& item->getSaleInfo().isForSale())
{
items.push_back(std::string("Task Buy"));
std::string label= LLTrans::getString("Buy");
// Check the price of the item.
S32 price = getPrice();
if (-1 == price)
{
llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
}
else
{
std::ostringstream info;
info << "Buy for " << gHippoGridManager->getConnectedGrid()->getCurrencySymbol() << price;
label.assign(info.str());
}
const LLView::child_list_t *list = menu.getChildList();
LLView::child_list_t::const_iterator itor;
for (itor = list->begin(); itor != list->end(); ++itor)
{
std::string name = (*itor)->getName();
LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor);
if (name == "Task Buy" && menu_itemp)
{
menu_itemp->setLabel(label);
}
}
}
else if (canOpenItem())
{
items.push_back(std::string("Task Open"));
if (!isItemCopyable())
{
disabled_items.push_back(std::string("Task Open"));
}
// [RLVa:KB] - Checked: 2010-03-01 (RLVa-1.2.0b) | Modified: RLVa-1.1.0a
else if (rlv_handler_t::isEnabled())
{
LLViewerObject* pAttachObj = gObjectList.findObject(mPanel->getTaskUUID());
bool fLocked = (pAttachObj) ? gRlvAttachmentLocks.isLockedAttachment(pAttachObj->getRootEdit()) : false;
if ( ((LLAssetType::AT_NOTECARD == item->getType()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE)) || (fLocked))) ||
((LLAssetType::AT_LSL_TEXT == item->getType()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT)) || (fLocked))) ||
((LLAssetType::AT_TEXTURE == item->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))) )
{
disabled_items.push_back(std::string("Task Open"));
}
}
// [/RLVa:KB]
}
items.push_back(std::string("Task Properties"));
// if(isItemRenameable())
// {
// items.push_back(std::string("Task Rename"));
// }
// if(isItemRemovable())
// {
// items.push_back(std::string("Task Remove"));
// }
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Added: RLVa-1.2.1f
items.push_back(std::string("Task Rename"));
items.push_back(std::string("Task Remove"));
if (!isItemRenameable())
{
disabled_items.push_back(std::string("Task Rename"));
}
if (!isItemRemovable())
{
disabled_items.push_back(std::string("Task Remove"));
}
// [/RLVa:KB]
hide_context_entries(menu, items, disabled_items);
}
///----------------------------------------------------------------------------
/// Class LLTaskFolderBridge
///----------------------------------------------------------------------------
class LLTaskCategoryBridge : public LLTaskInvFVBridge
{
public:
LLTaskCategoryBridge(
LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name);
virtual LLUIImagePtr getIcon() const;
virtual const std::string& getDisplayName() const;
virtual BOOL isItemRenameable() const;
// virtual BOOL isItemCopyable() const { return FALSE; }
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL isItemRemovable() const;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL hasChildren() const;
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data);
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
};
LLTaskCategoryBridge::LLTaskCategoryBridge(
LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name)
{
}
LLUIImagePtr LLTaskCategoryBridge::getIcon() const
{
return LLUI::getUIImage("inv_folder_plain_closed.tga");
}
// virtual
const std::string& LLTaskCategoryBridge::getDisplayName() const
{
return getName();
}
BOOL LLTaskCategoryBridge::isItemRenameable() const
{
return FALSE;
}
BOOL LLTaskCategoryBridge::renameItem(const std::string& new_name)
{
return FALSE;
}
BOOL LLTaskCategoryBridge::isItemRemovable() const
{
return FALSE;
}
void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
std::vector<std::string> items;
std::vector<std::string> disabled_items;
hide_context_entries(menu, items, disabled_items);
}
BOOL LLTaskCategoryBridge::hasChildren() const
{
// return TRUE if we have or do know know if we have children.
// *FIX: For now, return FALSE - we will know for sure soon enough.
return FALSE;
}
void LLTaskCategoryBridge::openItem()
{
}
BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
//llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
if(mPanel && mUUID.notNull())
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
const LLInventoryObject* cat = object->getInventoryObject(mUUID);
if ( (cat) && (move_inv_category_world_to_agent(mUUID, LLUUID::null, FALSE)) )
{
*type = LLViewerAssetType::lookupDragAndDropType(cat->getType());
*id = mUUID;
return TRUE;
}
}
}
return FALSE;
}
BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data)
{
//llinfos << "LLTaskCategoryBridge::dragOrDrop()" << llendl;
BOOL accept = FALSE;
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
switch(cargo_type)
{
case DAD_CATEGORY:
accept = LLToolDragAndDrop::getInstance()->dadUpdateInventoryCategory(object,drop);
break;
case DAD_TEXTURE:
case DAD_SOUND:
case DAD_LANDMARK:
case DAD_OBJECT:
case DAD_NOTECARD:
case DAD_CLOTHING:
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_CALLINGCARD:
case DAD_MESH:
accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
// <edit> testzone
//if(LLToolDragAndDrop::isInventoryDropAcceptable(
// object, (LLViewerInventoryItem*)cargo_data)
/*if(object->permModify()
// </edit>
&& (LLToolDragAndDrop::SOURCE_WORLD != LLToolDragAndDrop::getInstance()->getSource())
&& (LLToolDragAndDrop::SOURCE_NOTECARD != LLToolDragAndDrop::getInstance()->getSource()))
{
accept = TRUE;
}*/
if(accept && drop)
{
LLToolDragAndDrop::dropInventory(object,
(LLViewerInventoryItem*)cargo_data,
LLToolDragAndDrop::getInstance()->getSource(),
LLToolDragAndDrop::getInstance()->getSourceID());
}
break;
case DAD_SCRIPT:
// *HACK: In order to resolve SL-22177, we need to block
// drags from notecards and objects onto other
// objects. uncomment the simpler version when we have
// that right.
//accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
if(LLToolDragAndDrop::isInventoryDropAcceptable(
object, (LLViewerInventoryItem*)cargo_data)
&& (LLToolDragAndDrop::SOURCE_WORLD != LLToolDragAndDrop::getInstance()->getSource())
&& (LLToolDragAndDrop::SOURCE_NOTECARD != LLToolDragAndDrop::getInstance()->getSource()))
{
accept = TRUE;
}
if(accept && drop)
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)cargo_data;
// rez in the script active by default, rez in
// inactive if the control key is being held down.
BOOL active = ((mask & MASK_CONTROL) == 0);
LLToolDragAndDrop::dropScript(object, item, active,
LLToolDragAndDrop::getInstance()->getSource(),
LLToolDragAndDrop::getInstance()->getSourceID());
}
break;
default:
break;
}
}
return accept;
}
///----------------------------------------------------------------------------
/// Class LLTaskTextureBridge
///----------------------------------------------------------------------------
class LLTaskTextureBridge : public LLTaskInvFVBridge
{
public:
LLTaskTextureBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
};
void LLTaskTextureBridge::openItem()
{
// [RLVa:KB] - Checked: 2009-11-11 (RLVa-1.1.0a) | Modified: RLVa-1.1.0a
if (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWTEXTURE))
{
RlvUtil::notifyBlockedViewXXX(LLAssetType::AT_TEXTURE);
return;
}
// [/RLVa:KB]
llinfos << "LLTaskTextureBridge::openItem()" << llendl;
if(!LLPreview::show(mUUID))
{
// There isn't one, so make a new preview
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
rect.translate( left - rect.mLeft, top - rect.mTop );
LLPreviewTexture* preview = new LLPreviewTexture("preview task texture",
rect,
getName(),
mUUID,
mPanel->getTaskUUID());
preview->setFocus(TRUE);
}
}
///----------------------------------------------------------------------------
/// Class LLTaskSoundBridge
///----------------------------------------------------------------------------
class LLTaskSoundBridge : public LLTaskInvFVBridge
{
public:
LLTaskSoundBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
virtual void performAction(LLInventoryModel* model, std::string action);
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
static void openSoundPreview(void* data);
};
void LLTaskSoundBridge::openItem()
{
openSoundPreview((void*)this);
}
void LLTaskSoundBridge::openSoundPreview(void* data)
{
LLTaskSoundBridge* self = (LLTaskSoundBridge*)data;
if(!self)
return;
if(!LLPreview::show(self->mUUID))
{
// There isn't one, so make a new preview
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
LLPreviewSound* floaterp = new LLPreviewSound("preview task sound",
rect,
self->getName(),
self->mUUID,
self->mPanel->getTaskUUID());
floaterp->open(); /*Flawfinder: ignore*/
}
}
// virtual
void LLTaskSoundBridge::performAction(LLInventoryModel* model, std::string action)
{
if (action == "task_play")
{
LLInventoryItem* item = findItem();
if(item)
{
send_sound_trigger(item->getAssetUUID(), 1.0);
}
}
LLTaskInvFVBridge::performAction(model, action);
}
void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
LLInventoryItem* item = findItem();
if(!item) return;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
if(item->getPermissions().getOwner() != gAgent.getID()
&& item->getSaleInfo().isForSale())
{
items.push_back(std::string("Task Buy"));
std::string label= LLTrans::getString("Buy");
// Check the price of the item.
S32 price = getPrice();
if (-1 == price)
{
llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
}
else
{
std::ostringstream info;
info << "Buy for " << gHippoGridManager->getConnectedGrid()->getCurrencySymbol() << price;
label.assign(info.str());
}
const LLView::child_list_t *list = menu.getChildList();
LLView::child_list_t::const_iterator itor;
for (itor = list->begin(); itor != list->end(); ++itor)
{
std::string name = (*itor)->getName();
LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor);
if (name == "Task Buy" && menu_itemp)
{
menu_itemp->setLabel(label);
}
}
}
else if (canOpenItem())
{
//items.push_back(std::string("Task Open"));
if (!isItemCopyable())
{
disabled_items.push_back(std::string("Task Open"));
}
}
items.push_back(std::string("Task Properties"));
if(isItemRenameable())
{
items.push_back(std::string("Task Rename"));
}
if(isItemRemovable())
{
items.push_back(std::string("Task Remove"));
}
items.push_back(std::string("Task Play"));
/*menu.addSeparator();
menu.append(new LLMenuItemCallGL("Play",
&LLTaskSoundBridge::playSound,
NULL,
(void*)this));*/
hide_context_entries(menu, items, disabled_items);
}
///----------------------------------------------------------------------------
/// Class LLTaskLandmarkBridge
///----------------------------------------------------------------------------
class LLTaskLandmarkBridge : public LLTaskInvFVBridge
{
public:
LLTaskLandmarkBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
};
///----------------------------------------------------------------------------
/// Class LLTaskCallingCardBridge
///----------------------------------------------------------------------------
class LLTaskCallingCardBridge : public LLTaskInvFVBridge
{
public:
LLTaskCallingCardBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
virtual BOOL isItemRenameable() const;
virtual BOOL renameItem(const std::string& new_name);
};
BOOL LLTaskCallingCardBridge::isItemRenameable() const
{
return FALSE;
}
BOOL LLTaskCallingCardBridge::renameItem(const std::string& new_name)
{
return FALSE;
}
///----------------------------------------------------------------------------
/// Class LLTaskScriptBridge
///----------------------------------------------------------------------------
class LLTaskScriptBridge : public LLTaskInvFVBridge
{
public:
LLTaskScriptBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
//static BOOL enableIfCopyable( void* userdata );
};
class LLTaskLSLBridge : public LLTaskScriptBridge
{
public:
LLTaskLSLBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskScriptBridge(panel, uuid, name) {}
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
virtual BOOL removeItem();
//virtual void buildContextMenu(LLMenuGL& menu);
//static void copyToInventory(void* userdata);
};
void LLTaskLSLBridge::openItem()
{
llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl;
if(LLLiveLSLEditor::show(mUUID, mPanel->getTaskUUID()))
{
return;
}
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(!object || object->isInventoryPending())
{
return;
}
// [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.1.3b) | Modified: RLVa-1.1.0a
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachment(object->getRootEdit())) )
{
RlvUtil::notifyBlockedViewXXX(LLAssetType::AT_SCRIPT);
return;
}
// [/RLVa:KB]
if(object->permModify() || gAgent.isGodlike())
{
std::string title("Script: ");
LLInventoryItem* item = findItem();
if (item)
{
title.append(item->getName());
}
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
LLLiveLSLEditor* editor;
editor = new LLLiveLSLEditor("lsl ed",
rect,
title,
mPanel->getTaskUUID(),
mUUID);
LLMultiFloater* previous_host = LLFloater::getFloaterHost();
LLFloater::setFloaterHost(NULL);
editor->open(); /*Flawfinder: ignore*/
LLFloater::setFloaterHost(previous_host);
// keep onscreen
gFloaterView->adjustToFitScreen(editor, FALSE);
}
}
BOOL LLTaskLSLBridge::removeItem()
{
LLLiveLSLEditor::hide(mUUID, mPanel->getTaskUUID());
return LLTaskInvFVBridge::removeItem();
}
///----------------------------------------------------------------------------
/// Class LLTaskObjectBridge
///----------------------------------------------------------------------------
class LLTaskObjectBridge : public LLTaskInvFVBridge
{
public:
LLTaskObjectBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name,
U32 flags = 0) :
LLTaskInvFVBridge(panel, uuid, name, flags) {}
};
///----------------------------------------------------------------------------
/// Class LLTaskNotecardBridge
///----------------------------------------------------------------------------
class LLTaskNotecardBridge : public LLTaskInvFVBridge
{
public:
LLTaskNotecardBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
virtual BOOL removeItem();
};
void LLTaskNotecardBridge::openItem()
{
if(LLPreview::show(mUUID))
{
return;
}
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(!object || object->isInventoryPending())
{
return;
}
// [RLVa:KB] - Checked: 2009-11-11 (RLVa-1.1.3b) | Modified: RLVa-1.1.0a
if ( (rlv_handler_t::isEnabled()) &&
((gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE)) || (gRlvAttachmentLocks.isLockedAttachment(object->getRootEdit()))) )
{
RlvUtil::notifyBlockedViewXXX(LLAssetType::AT_NOTECARD);
return;
}
// [/RLVa:KB]
if(object->permModify() || gAgent.isGodlike())
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
LLPreviewNotecard* preview;
preview = new LLPreviewNotecard("live notecard editor",
rect,
getName(),
mUUID,
mPanel->getTaskUUID());
preview->setFocus(TRUE); // if you're opening a notecard from an object's inventory, it takes focus
// keep onscreen
gFloaterView->adjustToFitScreen(preview, FALSE);
}
}
BOOL LLTaskNotecardBridge::removeItem()
{
LLPreview::hide(mUUID);
return LLTaskInvFVBridge::removeItem();
}
///----------------------------------------------------------------------------
/// Class LLTaskGestureBridge
///----------------------------------------------------------------------------
class LLTaskGestureBridge : public LLTaskInvFVBridge
{
public:
LLTaskGestureBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
virtual BOOL removeItem();
};
void LLTaskGestureBridge::openItem()
{
if(LLPreview::show(mUUID))
{
return;
}
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(!object || object->isInventoryPending())
{
return;
}
// TODO: save rectangle
std::string title = getName();
LLUUID item_id = mUUID;
LLUUID object_id = mPanel->getTaskUUID();
LLPreviewGesture* preview = LLPreviewGesture::show(title, item_id, object_id);
// keep onscreen
gFloaterView->adjustToFitScreen(preview, FALSE);
}
BOOL LLTaskGestureBridge::removeItem()
{
// Don't need to deactivate gesture because gestures inside objects
// can never be active.
LLPreview::hide(mUUID);
return LLTaskInvFVBridge::removeItem();
}
///----------------------------------------------------------------------------
/// Class LLTaskAnimationBridge
///----------------------------------------------------------------------------
class LLTaskAnimationBridge : public LLTaskInvFVBridge
{
public:
LLTaskAnimationBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name) :
LLTaskInvFVBridge(panel, uuid, name) {}
virtual BOOL canOpenItem() const { return TRUE; }
virtual void openItem();
virtual BOOL removeItem();
};
void LLTaskAnimationBridge::openItem()
{
if(LLPreview::show(mUUID))
{
return;
}
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(!object || object->isInventoryPending())
{
return;
}
// TODO: what permissions allow looking at animation?
if(object->permModify() || gAgent.isGodlike())
{
// TODO: save rectangle
std::string title = getName();
LLUUID item_id = mUUID;
LLUUID object_id = mPanel->getTaskUUID();
if(!LLPreview::show(mUUID))
{
// There isn't one, so make a new preview
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
rect.translate(left - rect.mLeft, top - rect.mTop);
LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
rect,
getName(),
mUUID,
LLPreviewAnim::NONE,
mPanel->getTaskUUID());
preview->setFocus(TRUE); // take focus if you're looking at one of these
// Force to be entirely onscreen.
gFloaterView->adjustToFitScreen(preview, FALSE);
}
}
}
BOOL LLTaskAnimationBridge::removeItem()
{
LLPreview::hide(mUUID);
return LLTaskInvFVBridge::removeItem();
}
///----------------------------------------------------------------------------
/// Class LLTaskWearableBridge
///----------------------------------------------------------------------------
class LLTaskWearableBridge : public LLTaskInvFVBridge
{
public:
LLTaskWearableBridge(LLPanelObjectInventory* panel,
const LLUUID& uuid,
const std::string& name,
U32 flags) :
LLTaskInvFVBridge(panel, uuid, name, flags) {}
virtual LLUIImagePtr getIcon() const;
};
LLUIImagePtr LLTaskWearableBridge::getIcon() const
{
return LLInventoryIcon::getIcon(mAssetType, mInventoryType, mFlags, FALSE );
}
///----------------------------------------------------------------------------
/// LLTaskInvFVBridge impl
//----------------------------------------------------------------------------
LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory* panel,
LLInventoryObject* object)
{
LLTaskInvFVBridge* new_bridge = NULL;
const LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(object);
const U32 itemflags = ( NULL == item ? 0 : item->getFlags() );
LLAssetType::EType type = object ? object->getType() : LLAssetType::AT_CATEGORY;
LLUUID object_id = object ? object->getUUID() : LLUUID::null;
std::string object_name = object ? object->getName() : std::string();
switch(type)
{
case LLAssetType::AT_TEXTURE:
new_bridge = new LLTaskTextureBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_SOUND:
new_bridge = new LLTaskSoundBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_LANDMARK:
new_bridge = new LLTaskLandmarkBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_CALLINGCARD:
new_bridge = new LLTaskCallingCardBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_SCRIPT:
// OLD SCRIPTS DEPRECATED - JC
llwarns << "Old script" << llendl;
//new_bridge = new LLTaskOldScriptBridge(panel,
// object_id,
// object_name);
break;
case LLAssetType::AT_OBJECT:
new_bridge = new LLTaskObjectBridge(panel,
object_id,
object_name,
itemflags);
break;
case LLAssetType::AT_NOTECARD:
new_bridge = new LLTaskNotecardBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_ANIMATION:
new_bridge = new LLTaskAnimationBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_GESTURE:
new_bridge = new LLTaskGestureBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
new_bridge = new LLTaskWearableBridge(panel,
object_id,
object_name,
itemflags);
break;
case LLAssetType::AT_CATEGORY:
new_bridge = new LLTaskCategoryBridge(panel,
object_id,
object_name);
break;
case LLAssetType::AT_LSL_TEXT:
new_bridge = new LLTaskLSLBridge(panel,
object_id,
object_name);
break;
break;
default:
llinfos << "Unhandled inventory type (llassetstorage.h): "
<< (S32)type << llendl;
break;
}
return new_bridge;
}
///----------------------------------------------------------------------------
/// Class LLPanelObjectInventory
///----------------------------------------------------------------------------
// Default constructor
LLPanelObjectInventory::LLPanelObjectInventory(const std::string& name, const LLRect& rect) :
LLPanel(name, rect),
mScroller(NULL),
mFolders(NULL),
mHaveInventory(FALSE),
mIsInventoryEmpty(TRUE),
mInventoryNeedsUpdate(FALSE)
{
reset();
// Callbacks
init_object_inventory_panel_actions(this);
gIdleCallbacks.addFunction(idle, this);
}
// Destroys the object
LLPanelObjectInventory::~LLPanelObjectInventory()
{
if (!gIdleCallbacks.deleteFunction(idle, this))
{
llwarns << "LLPanelObjectInventory::~LLPanelObjectInventory() failed to delete callback" << llendl;
}
}
void LLPanelObjectInventory::clearContents()
{
mHaveInventory = FALSE;
mIsInventoryEmpty = TRUE;
if (LLToolDragAndDrop::getInstance() && LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_WORLD)
{
LLToolDragAndDrop::getInstance()->endDrag();
}
if( mScroller )
{
// removes mFolders
removeChild( mScroller );
mScroller->die();
mScroller = NULL;
mFolders = NULL;
}
}
void LLPanelObjectInventory::reset()
{
clearContents();
setBorderVisible(FALSE);
LLRect dummy_rect(0, 1, 1, 0);
mFolders = new LLFolderView(std::string("task inventory"), dummy_rect, getTaskUUID(), this, LLTaskInvFVBridge::createObjectBridge(this, NULL));
// this ensures that we never say "searching..." or "no items found"
mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
LLRect scroller_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
mScroller = new LLScrollableContainerView(std::string("task inventory scroller"), scroller_rect, mFolders );
mScroller->setFollowsAll();
addChild(mScroller);
mFolders->setScrollContainer( mScroller );
}
void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* data)
{
if(!object) return;
//llinfos << "invetnory arrived: \n"
// << " panel UUID: " << panel->mTaskUUID << "\n"
// << " task UUID: " << object->mID << llendl;
if(mTaskUUID == object->mID)
{
mInventoryNeedsUpdate = TRUE;
}
// refresh any properties floaters that are hanging around.
if(inventory)
{
// We need to copy the ones that need refreshing onto a
// temporary object because we cannot iterate through the
// object inventory twice... A pox on stateful iteration!
LLFloaterProperties* floater = NULL;
LLDynamicArray<LLFloaterProperties*> refresh;
LLInventoryObject::object_list_t::const_iterator it = inventory->begin();
LLInventoryObject::object_list_t::const_iterator end = inventory->end();
for( ; it != end; ++it)
{
floater = LLFloaterProperties::find((*it)->getUUID(),
object->getID());
if(floater)
{
refresh.put(floater);
}
}
S32 count = refresh.count();
for(S32 i = 0; i < count; ++i)
{
refresh.get(i)->refresh();
}
}
}
void LLPanelObjectInventory::updateInventory()
{
//llinfos << "inventory arrived: \n"
// << " panel UUID: " << panel->mTaskUUID << "\n"
// << " task UUID: " << object->mID << llendl;
// We're still interested in this task's inventory.
std::set<LLUUID> selected_items;
BOOL inventory_has_focus = FALSE;
if (mHaveInventory)
{
selected_items = mFolders->getSelectionList();
inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders);
}
reset();
LLViewerObject* objectp = gObjectList.findObject(mTaskUUID);
if (objectp)
{
LLInventoryObject* inventory_root = objectp->getInventoryRoot();
LLInventoryObject::object_list_t contents;
objectp->getInventoryContents(contents);
if (inventory_root)
{
createFolderViews(inventory_root, contents);
mHaveInventory = TRUE;
mIsInventoryEmpty = FALSE;
mFolders->setEnabled(TRUE);
}
else
{
// TODO: create an empty inventory
mIsInventoryEmpty = TRUE;
mHaveInventory = TRUE;
}
}
else
{
// TODO: create an empty inventory
mIsInventoryEmpty = TRUE;
mHaveInventory = TRUE;
}
// restore previous selection
std::set<LLUUID>::iterator selection_it;
BOOL first_item = TRUE;
for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it)
{
LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it);
if (selected_item)
{
//HACK: "set" first item then "change" each other one to get keyboard focus right
if (first_item)
{
mFolders->setSelection(selected_item, TRUE, inventory_has_focus);
first_item = FALSE;
}
else
{
mFolders->changeSelection(selected_item, TRUE);
}
}
}
mFolders->requestArrange();
mInventoryNeedsUpdate = FALSE;
}
// *FIX: This is currently a very expensive operation, because we have
// to iterate through the inventory one time for each category. This
// leads to an N^2 based on the category count. This could be greatly
// speeded with an efficient multimap implementation, but we don't
// have that in our current arsenal.
void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root, LLInventoryObject::object_list_t& contents)
{
if (!inventory_root)
{
return;
}
// Create a visible root category.
LLTaskInvFVBridge* bridge = NULL;
bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);
if(bridge)
{
LLFolderViewFolder* new_folder = NULL;
new_folder = new LLFolderViewFolder(inventory_root->getName(),
bridge->getIcon(),
bridge->getOpenIcon(),
NULL,
mFolders,
bridge);
new_folder->addToFolder(mFolders, mFolders);
new_folder->toggleOpen();
createViewsForCategory(&contents, inventory_root, new_folder);
}
}
typedef std::pair<LLInventoryObject*, LLFolderViewFolder*> obj_folder_pair;
void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_list_t* inventory,
LLInventoryObject* parent,
LLFolderViewFolder* folder)
{
// Find all in the first pass
LLDynamicArray<obj_folder_pair*> child_categories;
LLTaskInvFVBridge* bridge;
LLFolderViewItem* view;
LLInventoryObject::object_list_t::iterator it = inventory->begin();
LLInventoryObject::object_list_t::iterator end = inventory->end();
for( ; it != end; ++it)
{
LLInventoryObject* obj = *it;
if(parent->getUUID() == obj->getParentUUID())
{
bridge = LLTaskInvFVBridge::createObjectBridge(this, obj);
if(!bridge)
{
continue;
}
if(LLAssetType::AT_CATEGORY == obj->getType())
{
view = new LLFolderViewFolder(obj->getName(),
bridge->getIcon(),
bridge->getOpenIcon(),
NULL,
mFolders,
bridge);
child_categories.put(new obj_folder_pair(obj,
(LLFolderViewFolder*)view));
}
else
{
view = new LLFolderViewItem(obj->getName(),
bridge->getIcon(),
bridge->getOpenIcon(),
NULL,
bridge->getCreationDate(),
mFolders,
bridge);
}
view->addToFolder(folder, mFolders);
}
}
// now, for each category, do the second pass
for(S32 i = 0; i < child_categories.count(); i++)
{
createViewsForCategory(inventory, child_categories[i]->first,
child_categories[i]->second );
delete child_categories[i];
}
}
void LLPanelObjectInventory::refresh()
{
//llinfos << "LLPanelObjectInventory::refresh()" << llendl;
BOOL has_inventory = FALSE;
const BOOL non_root_ok = TRUE;
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(NULL, non_root_ok);
if(node)
{
LLViewerObject* object = node->getObject();
if(object && ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1)
|| (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)))
{
// determine if we need to make a request. Start with a
// default based on if we have inventory at all.
BOOL make_request = !mHaveInventory;
// If the task id is different than what we've stored,
// then make the request.
if(mTaskUUID != object->mID)
{
mTaskUUID = object->mID;
make_request = TRUE;
// This is a new object so pre-emptively clear the contents
// Otherwise we show the old stuff until the update comes in
clearContents();
// Register for updates from this object,
registerVOInventoryListener(object,NULL);
}
// Based on the node information, we may need to dirty the
// object inventory and get it again.
if(node->mValid)
{
if(node->mInventorySerial != object->getInventorySerial() || object->isInventoryDirty())
{
make_request = TRUE;
}
}
// do the request if necessary.
if(make_request)
{
requestVOInventory();
}
has_inventory = TRUE;
}
}
if(!has_inventory)
{
mTaskUUID = LLUUID::null;
removeVOInventoryListener();
clearContents();
}
//llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl;
}
void LLPanelObjectInventory::removeSelectedItem()
{
if(mFolders)
{
mFolders->removeSelectedItems();
}
}
void LLPanelObjectInventory::startRenamingSelectedItem()
{
if(mFolders)
{
mFolders->startRenamingSelectedItem();
}
}
void LLPanelObjectInventory::draw()
{
LLPanel::draw();
if(mIsInventoryEmpty)
{
if((LLUUID::null != mTaskUUID) && (!mHaveInventory))
{
LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("LoadingContents"), 0,
(S32)(getRect().getWidth() * 0.5f),
10,
LLColor4( 1, 1, 1, 1 ),
LLFontGL::HCENTER,
LLFontGL::BOTTOM);
}
else if(mHaveInventory)
{
LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("NoContents"), 0,
(S32)(getRect().getWidth() * 0.5f),
10,
LLColor4( 1, 1, 1, 1 ),
LLFontGL::HCENTER,
LLFontGL::BOTTOM);
}
}
}
void LLPanelObjectInventory::deleteAllChildren()
{
mScroller = NULL;
mFolders = NULL;
LLView::deleteAllChildren();
}
BOOL LLPanelObjectInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
{
if (mFolders && mHaveInventory)
{
LLFolderViewItem* folderp = mFolders->getNextFromChild(NULL);
if (!folderp)
{
return FALSE;
}
// Try to pass on unmodified mouse coordinates
S32 local_x = x - mFolders->getRect().mLeft;
S32 local_y = y - mFolders->getRect().mBottom;
if (mFolders->pointInView(local_x, local_y))
{
return mFolders->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
}
else
{
//force mouse coordinates to be inside folder rectangle
return mFolders->handleDragAndDrop(5, 1, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
}
}
else
{
return FALSE;
}
}
//static
void LLPanelObjectInventory::idle(void* user_data)
{
LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data;
if (self->mInventoryNeedsUpdate)
{
self->updateInventory();
}
}
void LLPanelObjectInventory::onFocusLost()
{
// inventory no longer handles cut/copy/paste/delete
if (LLEditMenuHandler::gEditMenuHandler == mFolders)
{
LLEditMenuHandler::gEditMenuHandler = NULL;
}
LLPanel::onFocusLost();
}
void LLPanelObjectInventory::onFocusReceived()
{
// inventory now handles cut/copy/paste/delete
LLEditMenuHandler::gEditMenuHandler = mFolders;
LLPanel::onFocusReceived();
}