PageRenderTime 718ms CodeModel.GetById 166ms app.highlight 405ms RepoModel.GetById 87ms app.codeStats 0ms

/indra/newview/llsidepaneliteminfo.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1035 lines | 799 code | 109 blank | 127 comment | 124 complexity | 87fdca359d1e77257a1c4ac31654f1c8 MD5 | raw file
   1/** 
   2 * @file llsidepaneliteminfo.cpp
   3 * @brief A floater which shows an inventory item's properties.
   4 *
   5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28#include "llsidepaneliteminfo.h"
  29
  30#include "roles_constants.h"
  31
  32#include "llagent.h"
  33#include "llavataractions.h"
  34#include "llbutton.h"
  35#include "llfloaterreg.h"
  36#include "llgroupactions.h"
  37#include "llinventorydefines.h"
  38#include "llinventorymodel.h"
  39#include "llinventoryobserver.h"
  40#include "lllineeditor.h"
  41#include "llradiogroup.h"
  42#include "llslurl.h"
  43#include "llviewercontrol.h"
  44#include "llviewerinventory.h"
  45#include "llviewerobjectlist.h"
  46
  47
  48//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  49// Class LLItemPropertiesObserver
  50//
  51// Helper class to watch for changes to the item.
  52//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  53class LLItemPropertiesObserver : public LLInventoryObserver
  54{
  55public:
  56	LLItemPropertiesObserver(LLSidepanelItemInfo* floater)
  57		: mFloater(floater)
  58	{
  59		gInventory.addObserver(this);
  60	}
  61	virtual ~LLItemPropertiesObserver()
  62	{
  63		gInventory.removeObserver(this);
  64	}
  65	virtual void changed(U32 mask);
  66private:
  67	LLSidepanelItemInfo* mFloater;
  68};
  69
  70void LLItemPropertiesObserver::changed(U32 mask)
  71{
  72	const std::set<LLUUID>& mChangedItemIDs = gInventory.getChangedIDs();
  73	std::set<LLUUID>::const_iterator it;
  74
  75	const LLUUID& item_id = mFloater->getItemID();
  76
  77	for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++)
  78	{
  79		// set dirty for 'item profile panel' only if changed item is the item for which 'item profile panel' is shown (STORM-288)
  80		if (*it == item_id)
  81		{
  82			// if there's a change we're interested in.
  83			if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
  84			{
  85				mFloater->dirty();
  86			}
  87		}
  88	}
  89}
  90
  91//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  92// Class LLObjectInventoryObserver
  93//
  94// Helper class to watch for changes in an object inventory.
  95// Used to update item properties in LLSidepanelItemInfo.
  96//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  97class LLObjectInventoryObserver : public LLVOInventoryListener
  98{
  99public:
 100	LLObjectInventoryObserver(LLSidepanelItemInfo* floater, LLViewerObject* object)
 101		: mFloater(floater)
 102	{
 103		registerVOInventoryListener(object, NULL);
 104	}
 105	virtual ~LLObjectInventoryObserver()
 106	{
 107		removeVOInventoryListener();
 108	}
 109	/*virtual*/ void inventoryChanged(LLViewerObject* object,
 110									  LLInventoryObject::object_list_t* inventory,
 111									  S32 serial_num,
 112									  void* user_data);
 113private:
 114	LLSidepanelItemInfo* mFloater;
 115};
 116
 117/*virtual*/
 118void LLObjectInventoryObserver::inventoryChanged(LLViewerObject* object,
 119												 LLInventoryObject::object_list_t* inventory,
 120												 S32 serial_num,
 121												 void* user_data)
 122{
 123	mFloater->dirty();
 124}
 125
 126///----------------------------------------------------------------------------
 127/// Class LLSidepanelItemInfo
 128///----------------------------------------------------------------------------
 129
 130static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
 131
 132// Default constructor
 133LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
 134	: LLSidepanelInventorySubpanel(p)
 135	, mItemID(LLUUID::null)
 136	, mObjectInventoryObserver(NULL)
 137{
 138	mPropertiesObserver = new LLItemPropertiesObserver(this);
 139}
 140
 141// Destroys the object
 142LLSidepanelItemInfo::~LLSidepanelItemInfo()
 143{
 144	delete mPropertiesObserver;
 145	mPropertiesObserver = NULL;
 146
 147	stopObjectInventoryObserver();
 148}
 149
 150// virtual
 151BOOL LLSidepanelItemInfo::postBuild()
 152{
 153	LLSidepanelInventorySubpanel::postBuild();
 154
 155	getChild<LLLineEditor>("LabelItemName")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
 156	getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this));
 157	getChild<LLLineEditor>("LabelItemDesc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
 158	getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this));
 159	// Creator information
 160	getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickCreator,this));
 161	// owner information
 162	getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickOwner,this));
 163	// acquired date
 164	// owner permissions
 165	// Permissions debug text
 166	// group permissions
 167	getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
 168	// everyone permissions
 169	getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
 170	// next owner permissions
 171	getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
 172	getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
 173	getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
 174	// Mark for sale or not, and sale info
 175	getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
 176	// "Price" label for edit
 177	getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
 178	refresh();
 179	return TRUE;
 180}
 181
 182void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
 183{
 184	mObjectID = object_id;
 185
 186	// Start monitoring changes in the object inventory to update
 187	// selected inventory item properties in Item Profile panel. See STORM-148.
 188	startObjectInventoryObserver();
 189}
 190
 191void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
 192{
 193	mItemID = item_id;
 194}
 195
 196const LLUUID& LLSidepanelItemInfo::getObjectID() const
 197{
 198	return mObjectID;
 199}
 200
 201const LLUUID& LLSidepanelItemInfo::getItemID() const
 202{
 203	return mItemID;
 204}
 205
 206void LLSidepanelItemInfo::reset()
 207{
 208	LLSidepanelInventorySubpanel::reset();
 209
 210	mObjectID = LLUUID::null;
 211	mItemID = LLUUID::null;
 212
 213	stopObjectInventoryObserver();
 214}
 215
 216void LLSidepanelItemInfo::refresh()
 217{
 218	LLViewerInventoryItem* item = findItem();
 219	if(item)
 220	{
 221		refreshFromItem(item);
 222		updateVerbs();
 223		return;
 224	}
 225	else
 226	{
 227		if (getIsEditing())
 228		{
 229			setIsEditing(FALSE);
 230		}
 231	}
 232
 233	if (!getIsEditing())
 234	{
 235		const std::string no_item_names[]={
 236			"LabelItemName",
 237			"LabelItemDesc",
 238			"LabelCreatorName",
 239			"LabelOwnerName",
 240			"CheckOwnerModify",
 241			"CheckOwnerCopy",
 242			"CheckOwnerTransfer",
 243			"CheckShareWithGroup",
 244			"CheckEveryoneCopy",
 245			"CheckNextOwnerModify",
 246			"CheckNextOwnerCopy",
 247			"CheckNextOwnerTransfer",
 248			"CheckPurchase",
 249			"Edit Cost"
 250		};
 251
 252		for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
 253		{
 254			getChildView(no_item_names[t])->setEnabled(false);
 255		}
 256		
 257		const std::string hide_names[]={
 258			"BaseMaskDebug",
 259			"OwnerMaskDebug",
 260			"GroupMaskDebug",
 261			"EveryoneMaskDebug",
 262			"NextMaskDebug"
 263		};
 264		for(size_t t=0; t<LL_ARRAY_SIZE(hide_names); ++t)
 265		{
 266			getChildView(hide_names[t])->setVisible(false);
 267		}
 268	}
 269
 270	if (!item)
 271	{
 272		const std::string no_edit_mode_names[]={
 273			"BtnCreator",
 274			"BtnOwner",
 275		};
 276		for(size_t t=0; t<LL_ARRAY_SIZE(no_edit_mode_names); ++t)
 277		{
 278			getChildView(no_edit_mode_names[t])->setEnabled(false);
 279		}
 280	}
 281
 282	updateVerbs();
 283}
 284
 285void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 286{
 287	////////////////////////
 288	// PERMISSIONS LOOKUP //
 289	////////////////////////
 290
 291	llassert(item);
 292	if (!item) return;
 293
 294	// do not enable the UI for incomplete items.
 295	BOOL is_complete = item->isFinished();
 296	const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType());
 297	const BOOL is_calling_card = (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
 298	const LLPermissions& perm = item->getPermissions();
 299	const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm, 
 300								GP_OBJECT_MANIPULATE);
 301	const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm, 
 302							  GP_OBJECT_SET_SALE) &&
 303		!cannot_restrict_permissions;
 304	const BOOL is_link = item->getIsLinkType();
 305	
 306	const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
 307	bool not_in_trash = (item->getUUID() != trash_id) && !gInventory.isObjectDescendentOf(item->getUUID(), trash_id);
 308
 309	// You need permission to modify the object to modify an inventory
 310	// item in it.
 311	LLViewerObject* object = NULL;
 312	if(!mObjectID.isNull()) object = gObjectList.findObject(mObjectID);
 313	BOOL is_obj_modify = TRUE;
 314	if(object)
 315	{
 316		is_obj_modify = object->permOwnerModify();
 317	}
 318
 319	//////////////////////
 320	// ITEM NAME & DESC //
 321	//////////////////////
 322	BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
 323											   GP_OBJECT_MANIPULATE)
 324		&& is_obj_modify && is_complete && not_in_trash;
 325
 326	getChildView("LabelItemNameTitle")->setEnabled(TRUE);
 327	getChildView("LabelItemName")->setEnabled(is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
 328	getChild<LLUICtrl>("LabelItemName")->setValue(item->getName());
 329	getChildView("LabelItemDescTitle")->setEnabled(TRUE);
 330	getChildView("LabelItemDesc")->setEnabled(is_modifiable);
 331	getChildView("IconLocked")->setVisible(!is_modifiable);
 332	getChild<LLUICtrl>("LabelItemDesc")->setValue(item->getDescription());
 333
 334	//////////////////
 335	// CREATOR NAME //
 336	//////////////////
 337	if(!gCacheName) return;
 338	if(!gAgent.getRegion()) return;
 339
 340	if (item->getCreatorUUID().notNull())
 341	{
 342		LLUUID creator_id = item->getCreatorUUID();
 343		std::string name =
 344			LLSLURL("agent", creator_id, "completename").getSLURLString();
 345		getChildView("BtnCreator")->setEnabled(TRUE);
 346		getChildView("LabelCreatorTitle")->setEnabled(TRUE);
 347		getChildView("LabelCreatorName")->setEnabled(FALSE);
 348		getChild<LLUICtrl>("LabelCreatorName")->setValue(name);
 349	}
 350	else
 351	{
 352		getChildView("BtnCreator")->setEnabled(FALSE);
 353		getChildView("LabelCreatorTitle")->setEnabled(FALSE);
 354		getChildView("LabelCreatorName")->setEnabled(FALSE);
 355		getChild<LLUICtrl>("LabelCreatorName")->setValue(getString("unknown"));
 356	}
 357
 358	////////////////
 359	// OWNER NAME //
 360	////////////////
 361	if(perm.isOwned())
 362	{
 363		std::string name;
 364		if (perm.isGroupOwned())
 365		{
 366			gCacheName->getGroupName(perm.getGroup(), name);
 367		}
 368		else
 369		{
 370			LLUUID owner_id = perm.getOwner();
 371			name = LLSLURL("agent", owner_id, "completename").getSLURLString();
 372		}
 373		getChildView("BtnOwner")->setEnabled(TRUE);
 374		getChildView("LabelOwnerTitle")->setEnabled(TRUE);
 375		getChildView("LabelOwnerName")->setEnabled(FALSE);
 376		getChild<LLUICtrl>("LabelOwnerName")->setValue(name);
 377	}
 378	else
 379	{
 380		getChildView("BtnOwner")->setEnabled(FALSE);
 381		getChildView("LabelOwnerTitle")->setEnabled(FALSE);
 382		getChildView("LabelOwnerName")->setEnabled(FALSE);
 383		getChild<LLUICtrl>("LabelOwnerName")->setValue(getString("public"));
 384	}
 385	
 386	////////////
 387	// ORIGIN //
 388	////////////
 389
 390	if (object)
 391	{
 392		getChild<LLUICtrl>("origin")->setValue(getString("origin_inworld"));
 393	}
 394	else
 395	{
 396		getChild<LLUICtrl>("origin")->setValue(getString("origin_inventory"));
 397	}
 398
 399	//////////////////
 400	// ACQUIRE DATE //
 401	//////////////////
 402	
 403	time_t time_utc = item->getCreationDate();
 404	if (0 == time_utc)
 405	{
 406		getChild<LLUICtrl>("LabelAcquiredDate")->setValue(getString("unknown"));
 407	}
 408	else
 409	{
 410		std::string timeStr = getString("acquiredDate");
 411		LLSD substitution;
 412		substitution["datetime"] = (S32) time_utc;
 413		LLStringUtil::format (timeStr, substitution);
 414		getChild<LLUICtrl>("LabelAcquiredDate")->setValue(timeStr);
 415	}
 416	
 417	//////////////////////////////////////
 418	// PERMISSIONS AND SALE ITEM HIDING //
 419	//////////////////////////////////////
 420	
 421	const std::string perm_and_sale_items[]={
 422		"perms_inv",
 423		"OwnerLabel",
 424		"perm_modify",
 425		"CheckOwnerModify",
 426		"CheckOwnerCopy",
 427		"CheckOwnerTransfer",
 428		"GroupLabel",
 429		"CheckShareWithGroup",
 430		"AnyoneLabel",
 431		"CheckEveryoneCopy",
 432		"NextOwnerLabel",
 433		"CheckNextOwnerModify",
 434		"CheckNextOwnerCopy",
 435		"CheckNextOwnerTransfer",
 436		"CheckPurchase",
 437		"SaleLabel",
 438		"combobox sale copy",
 439		"Edit Cost",
 440		"TextPrice"
 441	};
 442	
 443	const std::string debug_items[]={
 444		"BaseMaskDebug",
 445		"OwnerMaskDebug",
 446		"GroupMaskDebug",
 447		"EveryoneMaskDebug",
 448		"NextMaskDebug"
 449	};
 450	
 451	// Hide permissions checkboxes and labels and for sale info if in the trash
 452	// or ui elements don't apply to these objects and return from function
 453	if (!not_in_trash || cannot_restrict_permissions)
 454	{
 455		for(size_t t=0; t<LL_ARRAY_SIZE(perm_and_sale_items); ++t)
 456		{
 457			getChildView(perm_and_sale_items[t])->setVisible(false);
 458		}
 459		
 460		for(size_t t=0; t<LL_ARRAY_SIZE(debug_items); ++t)
 461		{
 462			getChildView(debug_items[t])->setVisible(false);
 463		}
 464		return;
 465	}
 466	else // Make sure perms and sale ui elements are visible
 467	{
 468		for(size_t t=0; t<LL_ARRAY_SIZE(perm_and_sale_items); ++t)
 469		{
 470			getChildView(perm_and_sale_items[t])->setVisible(true);
 471		}
 472	}
 473
 474	///////////////////////
 475	// OWNER PERMISSIONS //
 476	///////////////////////
 477	if(can_agent_manipulate)
 478	{
 479		getChild<LLUICtrl>("OwnerLabel")->setValue(getString("you_can"));
 480	}
 481	else
 482	{
 483		getChild<LLUICtrl>("OwnerLabel")->setValue(getString("owner_can"));
 484	}
 485
 486	U32 base_mask		= perm.getMaskBase();
 487	U32 owner_mask		= perm.getMaskOwner();
 488	U32 group_mask		= perm.getMaskGroup();
 489	U32 everyone_mask	= perm.getMaskEveryone();
 490	U32 next_owner_mask	= perm.getMaskNextOwner();
 491
 492	getChildView("OwnerLabel")->setEnabled(TRUE);
 493	getChildView("CheckOwnerModify")->setEnabled(FALSE);
 494	getChild<LLUICtrl>("CheckOwnerModify")->setValue(LLSD((BOOL)(owner_mask & PERM_MODIFY)));
 495	getChildView("CheckOwnerCopy")->setEnabled(FALSE);
 496	getChild<LLUICtrl>("CheckOwnerCopy")->setValue(LLSD((BOOL)(owner_mask & PERM_COPY)));
 497	getChildView("CheckOwnerTransfer")->setEnabled(FALSE);
 498	getChild<LLUICtrl>("CheckOwnerTransfer")->setValue(LLSD((BOOL)(owner_mask & PERM_TRANSFER)));
 499
 500	///////////////////////
 501	// DEBUG PERMISSIONS //
 502	///////////////////////
 503
 504	if( gSavedSettings.getBOOL("DebugPermissions") )
 505	{
 506		BOOL slam_perm 			= FALSE;
 507		BOOL overwrite_group	= FALSE;
 508		BOOL overwrite_everyone	= FALSE;
 509
 510		if (item->getType() == LLAssetType::AT_OBJECT)
 511		{
 512			U32 flags = item->getFlags();
 513			slam_perm 			= flags & LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM;
 514			overwrite_everyone	= flags & LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
 515			overwrite_group		= flags & LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
 516		}
 517		
 518		std::string perm_string;
 519
 520		perm_string = "B: ";
 521		perm_string += mask_to_string(base_mask);
 522		getChild<LLUICtrl>("BaseMaskDebug")->setValue(perm_string);
 523		getChildView("BaseMaskDebug")->setVisible(TRUE);
 524		
 525		perm_string = "O: ";
 526		perm_string += mask_to_string(owner_mask);
 527		getChild<LLUICtrl>("OwnerMaskDebug")->setValue(perm_string);
 528		getChildView("OwnerMaskDebug")->setVisible(TRUE);
 529		
 530		perm_string = "G";
 531		perm_string += overwrite_group ? "*: " : ": ";
 532		perm_string += mask_to_string(group_mask);
 533		getChild<LLUICtrl>("GroupMaskDebug")->setValue(perm_string);
 534		getChildView("GroupMaskDebug")->setVisible(TRUE);
 535		
 536		perm_string = "E";
 537		perm_string += overwrite_everyone ? "*: " : ": ";
 538		perm_string += mask_to_string(everyone_mask);
 539		getChild<LLUICtrl>("EveryoneMaskDebug")->setValue(perm_string);
 540		getChildView("EveryoneMaskDebug")->setVisible(TRUE);
 541		
 542		perm_string = "N";
 543		perm_string += slam_perm ? "*: " : ": ";
 544		perm_string += mask_to_string(next_owner_mask);
 545		getChild<LLUICtrl>("NextMaskDebug")->setValue(perm_string);
 546		getChildView("NextMaskDebug")->setVisible(TRUE);
 547	}
 548	else
 549	{
 550		getChildView("BaseMaskDebug")->setVisible(FALSE);
 551		getChildView("OwnerMaskDebug")->setVisible(FALSE);
 552		getChildView("GroupMaskDebug")->setVisible(FALSE);
 553		getChildView("EveryoneMaskDebug")->setVisible(FALSE);
 554		getChildView("NextMaskDebug")->setVisible(FALSE);
 555	}
 556
 557	/////////////
 558	// SHARING //
 559	/////////////
 560
 561	// Check for ability to change values.
 562	if (is_link || cannot_restrict_permissions)
 563	{
 564		getChildView("CheckShareWithGroup")->setEnabled(FALSE);
 565		getChildView("CheckEveryoneCopy")->setEnabled(FALSE);
 566	}
 567	else if (is_obj_modify && can_agent_manipulate)
 568	{
 569		getChildView("CheckShareWithGroup")->setEnabled(TRUE);
 570		getChildView("CheckEveryoneCopy")->setEnabled((owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
 571	}
 572	else
 573	{
 574		getChildView("CheckShareWithGroup")->setEnabled(FALSE);
 575		getChildView("CheckEveryoneCopy")->setEnabled(FALSE);
 576	}
 577
 578	// Set values.
 579	BOOL is_group_copy = (group_mask & PERM_COPY) ? TRUE : FALSE;
 580	BOOL is_group_modify = (group_mask & PERM_MODIFY) ? TRUE : FALSE;
 581	BOOL is_group_move = (group_mask & PERM_MOVE) ? TRUE : FALSE;
 582
 583	if (is_group_copy && is_group_modify && is_group_move)
 584	{
 585		getChild<LLUICtrl>("CheckShareWithGroup")->setValue(LLSD((BOOL)TRUE));
 586
 587		LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
 588		if(ctl)
 589		{
 590			ctl->setTentative(FALSE);
 591		}
 592	}
 593	else if (!is_group_copy && !is_group_modify && !is_group_move)
 594	{
 595		getChild<LLUICtrl>("CheckShareWithGroup")->setValue(LLSD((BOOL)FALSE));
 596		LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
 597		if(ctl)
 598		{
 599			ctl->setTentative(FALSE);
 600		}
 601	}
 602	else
 603	{
 604		LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
 605		if(ctl)
 606		{
 607			ctl->setTentative(TRUE);
 608			ctl->set(TRUE);
 609		}
 610	}
 611	
 612	getChild<LLUICtrl>("CheckEveryoneCopy")->setValue(LLSD((BOOL)(everyone_mask & PERM_COPY)));
 613
 614	///////////////
 615	// SALE INFO //
 616	///////////////
 617
 618	const LLSaleInfo& sale_info = item->getSaleInfo();
 619	BOOL is_for_sale = sale_info.isForSale();
 620	// Check for ability to change values.
 621	if (is_obj_modify && can_agent_sell 
 622		&& gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
 623	{
 624		getChildView("SaleLabel")->setEnabled(is_complete);
 625		getChildView("CheckPurchase")->setEnabled(is_complete);
 626
 627		getChildView("NextOwnerLabel")->setEnabled(TRUE);
 628		getChildView("CheckNextOwnerModify")->setEnabled((base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
 629		getChildView("CheckNextOwnerCopy")->setEnabled((base_mask & PERM_COPY) && !cannot_restrict_permissions);
 630		getChildView("CheckNextOwnerTransfer")->setEnabled((next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
 631
 632		getChildView("TextPrice")->setEnabled(is_complete && is_for_sale);
 633		getChildView("Edit Cost")->setEnabled(is_complete && is_for_sale);
 634	}
 635	else
 636	{
 637		getChildView("SaleLabel")->setEnabled(FALSE);
 638		getChildView("CheckPurchase")->setEnabled(FALSE);
 639
 640		getChildView("NextOwnerLabel")->setEnabled(FALSE);
 641		getChildView("CheckNextOwnerModify")->setEnabled(FALSE);
 642		getChildView("CheckNextOwnerCopy")->setEnabled(FALSE);
 643		getChildView("CheckNextOwnerTransfer")->setEnabled(FALSE);
 644
 645		getChildView("TextPrice")->setEnabled(FALSE);
 646		getChildView("Edit Cost")->setEnabled(FALSE);
 647	}
 648
 649	// Set values.
 650	getChild<LLUICtrl>("CheckPurchase")->setValue(is_for_sale);
 651	getChildView("combobox sale copy")->setEnabled(is_for_sale);
 652	getChildView("Edit Cost")->setEnabled(is_for_sale);
 653	getChild<LLUICtrl>("CheckNextOwnerModify")->setValue(LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
 654	getChild<LLUICtrl>("CheckNextOwnerCopy")->setValue(LLSD(BOOL(next_owner_mask & PERM_COPY)));
 655	getChild<LLUICtrl>("CheckNextOwnerTransfer")->setValue(LLSD(BOOL(next_owner_mask & PERM_TRANSFER)));
 656
 657	if (is_for_sale)
 658	{
 659		S32 numerical_price;
 660		numerical_price = sale_info.getSalePrice();
 661		getChild<LLUICtrl>("Edit Cost")->setValue(llformat("%d",numerical_price));
 662	}
 663	else
 664	{
 665		getChild<LLUICtrl>("Edit Cost")->setValue(llformat("%d",0));
 666	}
 667}
 668
 669void LLSidepanelItemInfo::startObjectInventoryObserver()
 670{
 671	if (!mObjectInventoryObserver)
 672	{
 673		stopObjectInventoryObserver();
 674
 675		// Previous object observer should be removed before starting to observe a new object.
 676		llassert(mObjectInventoryObserver == NULL);
 677	}
 678
 679	if (mObjectID.isNull())
 680	{
 681		llwarns << "Empty object id passed to inventory observer" << llendl;
 682		return;
 683	}
 684
 685	LLViewerObject* object = gObjectList.findObject(mObjectID);
 686
 687	mObjectInventoryObserver = new LLObjectInventoryObserver(this, object);
 688}
 689
 690void LLSidepanelItemInfo::stopObjectInventoryObserver()
 691{
 692	delete mObjectInventoryObserver;
 693	mObjectInventoryObserver = NULL;
 694}
 695
 696void LLSidepanelItemInfo::onClickCreator()
 697{
 698	LLViewerInventoryItem* item = findItem();
 699	if(!item) return;
 700	if(!item->getCreatorUUID().isNull())
 701	{
 702		LLAvatarActions::showProfile(item->getCreatorUUID());
 703	}
 704}
 705
 706// static
 707void LLSidepanelItemInfo::onClickOwner()
 708{
 709	LLViewerInventoryItem* item = findItem();
 710	if(!item) return;
 711	if(item->getPermissions().isGroupOwned())
 712	{
 713		LLGroupActions::show(item->getPermissions().getGroup());
 714	}
 715	else
 716	{
 717		LLAvatarActions::showProfile(item->getPermissions().getOwner());
 718	}
 719}
 720
 721// static
 722void LLSidepanelItemInfo::onCommitName()
 723{
 724	//llinfos << "LLSidepanelItemInfo::onCommitName()" << llendl;
 725	LLViewerInventoryItem* item = findItem();
 726	if(!item)
 727	{
 728		return;
 729	}
 730	LLLineEditor* labelItemName = getChild<LLLineEditor>("LabelItemName");
 731
 732	if(labelItemName&&
 733	   (item->getName() != labelItemName->getText()) && 
 734	   (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) )
 735	{
 736		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
 737		new_item->rename(labelItemName->getText());
 738		if(mObjectID.isNull())
 739		{
 740			new_item->updateServer(FALSE);
 741			gInventory.updateItem(new_item);
 742			gInventory.notifyObservers();
 743		}
 744		else
 745		{
 746			LLViewerObject* object = gObjectList.findObject(mObjectID);
 747			if(object)
 748			{
 749				object->updateInventory(
 750					new_item,
 751					TASK_INVENTORY_ITEM_KEY,
 752					false);
 753			}
 754		}
 755	}
 756}
 757
 758void LLSidepanelItemInfo::onCommitDescription()
 759{
 760	//llinfos << "LLSidepanelItemInfo::onCommitDescription()" << llendl;
 761	LLViewerInventoryItem* item = findItem();
 762	if(!item) return;
 763
 764	LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc");
 765	if(!labelItemDesc)
 766	{
 767		return;
 768	}
 769	if((item->getDescription() != labelItemDesc->getText()) && 
 770	   (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)))
 771	{
 772		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
 773
 774		new_item->setDescription(labelItemDesc->getText());
 775		if(mObjectID.isNull())
 776		{
 777			new_item->updateServer(FALSE);
 778			gInventory.updateItem(new_item);
 779			gInventory.notifyObservers();
 780		}
 781		else
 782		{
 783			LLViewerObject* object = gObjectList.findObject(mObjectID);
 784			if(object)
 785			{
 786				object->updateInventory(
 787					new_item,
 788					TASK_INVENTORY_ITEM_KEY,
 789					false);
 790			}
 791		}
 792	}
 793}
 794
 795// static
 796void LLSidepanelItemInfo::onCommitPermissions()
 797{
 798	//llinfos << "LLSidepanelItemInfo::onCommitPermissions()" << llendl;
 799	LLViewerInventoryItem* item = findItem();
 800	if(!item) return;
 801	LLPermissions perm(item->getPermissions());
 802
 803
 804	LLCheckBoxCtrl* CheckShareWithGroup = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
 805
 806	if(CheckShareWithGroup)
 807	{
 808		perm.setGroupBits(gAgent.getID(), gAgent.getGroupID(),
 809						CheckShareWithGroup->get(),
 810						PERM_MODIFY | PERM_MOVE | PERM_COPY);
 811	}
 812	LLCheckBoxCtrl* CheckEveryoneCopy = getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
 813	if(CheckEveryoneCopy)
 814	{
 815		perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(),
 816						 CheckEveryoneCopy->get(), PERM_COPY);
 817	}
 818
 819	LLCheckBoxCtrl* CheckNextOwnerModify = getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
 820	if(CheckNextOwnerModify)
 821	{
 822		perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
 823							CheckNextOwnerModify->get(), PERM_MODIFY);
 824	}
 825	LLCheckBoxCtrl* CheckNextOwnerCopy = getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
 826	if(CheckNextOwnerCopy)
 827	{
 828		perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
 829							CheckNextOwnerCopy->get(), PERM_COPY);
 830	}
 831	LLCheckBoxCtrl* CheckNextOwnerTransfer = getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
 832	if(CheckNextOwnerTransfer)
 833	{
 834		perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
 835							CheckNextOwnerTransfer->get(), PERM_TRANSFER);
 836	}
 837	if(perm != item->getPermissions()
 838		&& item->isFinished())
 839	{
 840		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
 841		new_item->setPermissions(perm);
 842		U32 flags = new_item->getFlags();
 843		// If next owner permissions have changed (and this is an object)
 844		// then set the slam permissions flag so that they are applied on rez.
 845		if((perm.getMaskNextOwner()!=item->getPermissions().getMaskNextOwner())
 846		   && (item->getType() == LLAssetType::AT_OBJECT))
 847		{
 848			flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM;
 849		}
 850		// If everyone permissions have changed (and this is an object)
 851		// then set the overwrite everyone permissions flag so they
 852		// are applied on rez.
 853		if ((perm.getMaskEveryone()!=item->getPermissions().getMaskEveryone())
 854			&& (item->getType() == LLAssetType::AT_OBJECT))
 855		{
 856			flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
 857		}
 858		// If group permissions have changed (and this is an object)
 859		// then set the overwrite group permissions flag so they
 860		// are applied on rez.
 861		if ((perm.getMaskGroup()!=item->getPermissions().getMaskGroup())
 862			&& (item->getType() == LLAssetType::AT_OBJECT))
 863		{
 864			flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
 865		}
 866		new_item->setFlags(flags);
 867		if(mObjectID.isNull())
 868		{
 869			new_item->updateServer(FALSE);
 870			gInventory.updateItem(new_item);
 871			gInventory.notifyObservers();
 872		}
 873		else
 874		{
 875			LLViewerObject* object = gObjectList.findObject(mObjectID);
 876			if(object)
 877			{
 878				object->updateInventory(
 879					new_item,
 880					TASK_INVENTORY_ITEM_KEY,
 881					false);
 882			}
 883		}
 884	}
 885	else
 886	{
 887		// need to make sure we don't just follow the click
 888		refresh();
 889	}
 890}
 891
 892// static
 893void LLSidepanelItemInfo::onCommitSaleInfo()
 894{
 895	//llinfos << "LLSidepanelItemInfo::onCommitSaleInfo()" << llendl;
 896	updateSaleInfo();
 897}
 898
 899// static
 900void LLSidepanelItemInfo::onCommitSaleType()
 901{
 902	//llinfos << "LLSidepanelItemInfo::onCommitSaleType()" << llendl;
 903	updateSaleInfo();
 904}
 905
 906void LLSidepanelItemInfo::updateSaleInfo()
 907{
 908	LLViewerInventoryItem* item = findItem();
 909	if(!item) return;
 910	LLSaleInfo sale_info(item->getSaleInfo());
 911	if(!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(), GP_OBJECT_SET_SALE))
 912	{
 913		getChild<LLUICtrl>("CheckPurchase")->setValue(LLSD((BOOL)FALSE));
 914	}
 915
 916	if((BOOL)getChild<LLUICtrl>("CheckPurchase")->getValue())
 917	{
 918		// turn on sale info
 919		LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_COPY;
 920	
 921		LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("RadioSaleType");
 922		if(RadioSaleType)
 923		{
 924			switch (RadioSaleType->getSelectedIndex())
 925			{
 926			case 0:
 927				sale_type = LLSaleInfo::FS_ORIGINAL;
 928				break;
 929			case 1:
 930				sale_type = LLSaleInfo::FS_COPY;
 931				break;
 932			case 2:
 933				sale_type = LLSaleInfo::FS_CONTENTS;
 934				break;
 935			default:
 936				sale_type = LLSaleInfo::FS_COPY;
 937				break;
 938			}
 939		}
 940
 941		if (sale_type == LLSaleInfo::FS_COPY 
 942			&& !gAgent.allowOperation(PERM_COPY, item->getPermissions(), 
 943									  GP_OBJECT_SET_SALE))
 944		{
 945			sale_type = LLSaleInfo::FS_ORIGINAL;
 946		}
 947
 948	     
 949		
 950		S32 price = -1;
 951		price =  getChild<LLUICtrl>("Edit Cost")->getValue().asInteger();;
 952
 953		// Invalid data - turn off the sale
 954		if (price < 0)
 955		{
 956			sale_type = LLSaleInfo::FS_NOT;
 957			price = 0;
 958		}
 959
 960		sale_info.setSaleType(sale_type);
 961		sale_info.setSalePrice(price);
 962	}
 963	else
 964	{
 965		sale_info.setSaleType(LLSaleInfo::FS_NOT);
 966	}
 967	if(sale_info != item->getSaleInfo()
 968		&& item->isFinished())
 969	{
 970		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
 971
 972		// Force an update on the sale price at rez
 973		if (item->getType() == LLAssetType::AT_OBJECT)
 974		{
 975			U32 flags = new_item->getFlags();
 976			flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_SALE;
 977			new_item->setFlags(flags);
 978		}
 979
 980		new_item->setSaleInfo(sale_info);
 981		if(mObjectID.isNull())
 982		{
 983			// This is in the agent's inventory.
 984			new_item->updateServer(FALSE);
 985			gInventory.updateItem(new_item);
 986			gInventory.notifyObservers();
 987		}
 988		else
 989		{
 990			// This is in an object's contents.
 991			LLViewerObject* object = gObjectList.findObject(mObjectID);
 992			if(object)
 993			{
 994				object->updateInventory(
 995					new_item,
 996					TASK_INVENTORY_ITEM_KEY,
 997					false);
 998			}
 999		}
1000	}
1001	else
1002	{
1003		// need to make sure we don't just follow the click
1004		refresh();
1005	}
1006}
1007
1008LLViewerInventoryItem* LLSidepanelItemInfo::findItem() const
1009{
1010	LLViewerInventoryItem* item = NULL;
1011	if(mObjectID.isNull())
1012	{
1013		// it is in agent inventory
1014		item = gInventory.getItem(mItemID);
1015	}
1016	else
1017	{
1018		LLViewerObject* object = gObjectList.findObject(mObjectID);
1019		if(object)
1020		{
1021			item = static_cast<LLViewerInventoryItem*>(object->getInventoryObject(mItemID));
1022		}
1023	}
1024	return item;
1025}
1026
1027// virtual
1028void LLSidepanelItemInfo::save()
1029{
1030	onCommitName();
1031	onCommitDescription();
1032	onCommitPermissions();
1033	onCommitSaleInfo();
1034	onCommitSaleType();
1035}