PageRenderTime 3683ms CodeModel.GetById 1006ms app.highlight 1878ms RepoModel.GetById 601ms app.codeStats 1ms

/indra/newview/llfloaterscriptlimits.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1361 lines | 1030 code | 222 blank | 109 comment | 130 complexity | 7e720e4ff4c36289332954d15c8af9c0 MD5 | raw file
   1/** 
   2 * @file llfloaterscriptlimits.cpp
   3 * @author Gabriel Lee
   4 * @brief Implementation of the region info and controls floater and panels.
   5 *
   6 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
   7 * Second Life Viewer Source Code
   8 * Copyright (C) 2010, Linden Research, Inc.
   9 * 
  10 * This library is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU Lesser General Public
  12 * License as published by the Free Software Foundation;
  13 * version 2.1 of the License only.
  14 * 
  15 * This library is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * Lesser General Public License for more details.
  19 * 
  20 * You should have received a copy of the GNU Lesser General Public
  21 * License along with this library; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  23 * 
  24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  25 * $/LicenseInfo$
  26 */
  27
  28#include "llviewerprecompiledheaders.h"
  29#include "llfloaterscriptlimits.h"
  30
  31// library includes
  32#include "llavatarnamecache.h"
  33#include "llsdutil.h"
  34#include "llsdutil_math.h"
  35#include "message.h"
  36
  37#include "llagent.h"
  38#include "llfloateravatarpicker.h"
  39#include "llfloaterland.h"
  40#include "llfloaterreg.h"
  41#include "llregionhandle.h"
  42#include "llscrolllistctrl.h"
  43#include "llscrolllistitem.h"
  44#include "llparcel.h"
  45#include "lltabcontainer.h"
  46#include "lltracker.h"
  47#include "lltrans.h"
  48#include "llviewercontrol.h"
  49#include "lluictrlfactory.h"
  50#include "llviewerparcelmgr.h"
  51#include "llviewerregion.h"
  52#include "llviewerwindow.h"
  53
  54///----------------------------------------------------------------------------
  55/// LLFloaterScriptLimits
  56///----------------------------------------------------------------------------
  57
  58// debug switches, won't work in release
  59#ifndef LL_RELEASE_FOR_DOWNLOAD
  60
  61// dump responder replies to llinfos for debugging
  62//#define DUMP_REPLIES_TO_LLINFOS
  63
  64#ifdef DUMP_REPLIES_TO_LLINFOS
  65#include "llsdserialize.h"
  66#include "llwindow.h"
  67#endif
  68
  69// use fake LLSD responses to check the viewer side is working correctly
  70// I'm syncing this with the server side efforts so hopfully we can keep
  71// the to-ing and fro-ing between the two teams to a minimum
  72//#define USE_FAKE_RESPONSES
  73
  74#ifdef USE_FAKE_RESPONSES
  75const S32 FAKE_NUMBER_OF_URLS = 329;
  76const S32 FAKE_AVAILABLE_URLS = 731;
  77const S32 FAKE_AMOUNT_OF_MEMORY = 66741;
  78const S32 FAKE_AVAILABLE_MEMORY = 895577;
  79#endif
  80
  81#endif
  82
  83const S32 SIZE_OF_ONE_KB = 1024;
  84
  85LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed)
  86	: LLFloater(seed)
  87{
  88}
  89
  90BOOL LLFloaterScriptLimits::postBuild()
  91{
  92	// a little cheap and cheerful - if there's an about land panel open default to showing parcel info,
  93	// otherwise default to showing attachments (avatar appearance)
  94	bool selectParcelPanel = false;
  95	
  96	LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
  97	if(instance)
  98	{
  99		if(instance->isShown())
 100		{
 101			selectParcelPanel = true;
 102		}
 103	}
 104
 105	mTab = getChild<LLTabContainer>("scriptlimits_panels");
 106	
 107	if(!mTab)
 108	{
 109		llwarns << "Error! couldn't get scriptlimits_panels, aborting Script Information setup" << llendl;
 110		return FALSE;
 111	}
 112
 113	// contruct the panels
 114	std::string land_url = gAgent.getRegion()->getCapability("LandResources");
 115	if (!land_url.empty())
 116	{
 117		LLPanelScriptLimitsRegionMemory* panel_memory;
 118		panel_memory = new LLPanelScriptLimitsRegionMemory;
 119		mInfoPanels.push_back(panel_memory);
 120		panel_memory->buildFromFile( "panel_script_limits_region_memory.xml");
 121		mTab->addTabPanel(panel_memory);
 122	}
 123	
 124	std::string attachment_url = gAgent.getRegion()->getCapability("AttachmentResources");
 125	if (!attachment_url.empty())
 126	{
 127		LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
 128		mInfoPanels.push_back(panel_attachments);
 129		panel_attachments->buildFromFile("panel_script_limits_my_avatar.xml");
 130		mTab->addTabPanel(panel_attachments);
 131	}
 132	
 133	if(mInfoPanels.size() > 0)
 134	{
 135		mTab->selectTab(0);
 136	}
 137
 138	if(!selectParcelPanel && (mInfoPanels.size() > 1))
 139	{
 140		mTab->selectTab(1);
 141	}
 142
 143	return TRUE;
 144}
 145
 146LLFloaterScriptLimits::~LLFloaterScriptLimits()
 147{
 148}
 149
 150// public
 151void LLFloaterScriptLimits::refresh()
 152{
 153	for(info_panels_t::iterator iter = mInfoPanels.begin();
 154		iter != mInfoPanels.end(); ++iter)
 155	{
 156		(*iter)->refresh();
 157	}
 158}
 159
 160///----------------------------------------------------------------------------
 161// Base class for panels
 162///----------------------------------------------------------------------------
 163
 164LLPanelScriptLimitsInfo::LLPanelScriptLimitsInfo()
 165	: LLPanel()
 166{
 167}
 168
 169
 170// virtual
 171BOOL LLPanelScriptLimitsInfo::postBuild()
 172{
 173	refresh();
 174	return TRUE;
 175}
 176
 177// virtual 
 178void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
 179{
 180}
 181
 182///----------------------------------------------------------------------------
 183// Responders
 184///----------------------------------------------------------------------------
 185
 186void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
 187{
 188	//we don't need to test with a fake respose here (shouldn't anyway)
 189
 190#ifdef DUMP_REPLIES_TO_LLINFOS
 191
 192	LLSDNotationStreamer notation_streamer(content);
 193	std::ostringstream nice_llsd;
 194	nice_llsd << notation_streamer;
 195
 196	OSMessageBox(nice_llsd.str(), "main cap response:", 0);
 197
 198	llinfos << "main cap response:" << content << llendl;
 199
 200#endif
 201
 202	// at this point we have an llsd which should contain ether one or two urls to the services we want.
 203	// first we look for the details service:
 204	if(content.has("ScriptResourceDetails"))
 205	{
 206		LLHTTPClient::get(content["ScriptResourceDetails"], new fetchScriptLimitsRegionDetailsResponder(mInfo));
 207	}
 208	else
 209	{
 210		LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 211		if(!instance)
 212		{
 213			llwarns << "Failed to get llfloaterscriptlimits instance" << llendl;
 214		}
 215	}
 216
 217	// then the summary service:
 218	if(content.has("ScriptResourceSummary"))
 219	{
 220		LLHTTPClient::get(content["ScriptResourceSummary"], new fetchScriptLimitsRegionSummaryResponder(mInfo));
 221	}
 222}
 223
 224void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& reason)
 225{
 226	llwarns << "Error from responder " << reason << llendl;
 227}
 228
 229void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
 230{
 231#ifdef USE_FAKE_RESPONSES
 232
 233	LLSD fake_content;
 234	LLSD summary = LLSD::emptyMap();
 235	LLSD available = LLSD::emptyArray();
 236	LLSD available_urls = LLSD::emptyMap();
 237	LLSD available_memory = LLSD::emptyMap();
 238	LLSD used = LLSD::emptyArray();
 239	LLSD used_urls = LLSD::emptyMap();
 240	LLSD used_memory = LLSD::emptyMap();
 241
 242	used_urls["type"] = "urls";
 243	used_urls["amount"] = FAKE_NUMBER_OF_URLS;
 244	available_urls["type"] = "urls";
 245	available_urls["amount"] = FAKE_AVAILABLE_URLS;
 246	used_memory["type"] = "memory";
 247	used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY;
 248	available_memory["type"] = "memory";
 249	available_memory["amount"] = FAKE_AVAILABLE_MEMORY;
 250
 251//summary response:{'summary':{'available':[{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'},{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'}],'used':[{'amount':i329,'type':'urls'},{'amount':i66741,'type':'memory'}]}}
 252
 253	used.append(used_urls);
 254	used.append(used_memory);
 255	available.append(available_urls);
 256	available.append(available_memory);
 257
 258	summary["available"] = available;
 259	summary["used"] = used;
 260	
 261	fake_content["summary"] = summary;
 262
 263	const LLSD& content = fake_content;
 264
 265#else
 266
 267	const LLSD& content = content_ref;
 268
 269#endif
 270
 271
 272#ifdef DUMP_REPLIES_TO_LLINFOS
 273
 274	LLSDNotationStreamer notation_streamer(content);
 275	std::ostringstream nice_llsd;
 276	nice_llsd << notation_streamer;
 277
 278	OSMessageBox(nice_llsd.str(), "summary response:", 0);
 279
 280	llwarns << "summary response:" << *content << llendl;
 281
 282#endif
 283
 284	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 285	if(!instance)
 286	{
 287		llwarns << "Failed to get llfloaterscriptlimits instance" << llendl;
 288	}
 289	else
 290	{
 291		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 292		if(tab)
 293		{
 294		LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
 295			if(panel_memory)
 296			{
 297				panel_memory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
 298
 299				LLButton* btn = panel_memory->getChild<LLButton>("refresh_list_btn");
 300				if(btn)
 301				{
 302					btn->setEnabled(true);
 303				}
 304				
 305		panel_memory->setRegionSummary(content);
 306	}
 307}
 308	}
 309}
 310
 311void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::string& reason)
 312{
 313	llwarns << "Error from responder " << reason << llendl;
 314}
 315
 316void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref)
 317{
 318#ifdef USE_FAKE_RESPONSES
 319/*
 320Updated detail service, ** denotes field added:
 321
 322result (map)
 323+-parcels (array of maps)
 324  +-id (uuid)
 325  +-local_id (S32)**
 326  +-name (string)
 327  +-owner_id (uuid) (in ERS as owner, but owner_id in code)
 328  +-objects (array of maps)
 329    +-id (uuid)
 330    +-name (string)
 331	+-owner_id (uuid) (in ERS as owner, in code as owner_id)
 332	+-owner_name (sting)**
 333	+-location (map)**
 334	  +-x (float)
 335	  +-y (float)
 336	  +-z (float)
 337    +-resources (map) (this is wrong in the ERS but right in code)
 338      +-type (string)
 339      +-amount (int)
 340*/
 341	LLSD fake_content;
 342	LLSD resource = LLSD::emptyMap();
 343	LLSD location = LLSD::emptyMap();
 344	LLSD object = LLSD::emptyMap();
 345	LLSD objects = LLSD::emptyArray();
 346	LLSD parcel = LLSD::emptyMap();
 347	LLSD parcels = LLSD::emptyArray();
 348
 349	resource["urls"] = FAKE_NUMBER_OF_URLS;
 350	resource["memory"] = FAKE_AMOUNT_OF_MEMORY;
 351	
 352	location["x"] = 128.0f;
 353	location["y"] = 128.0f;
 354	location["z"] = 0.0f;
 355	
 356	object["id"] = LLUUID("d574a375-0c6c-fe3d-5733-da669465afc7");
 357	object["name"] = "Gabs fake Object!";
 358	object["owner_id"] = LLUUID("8dbf2d41-69a0-4e5e-9787-0c9d297bc570");
 359	object["owner_name"] = "Gabs Linden";
 360	object["location"] = location;
 361	object["resources"] = resource;
 362
 363	objects.append(object);
 364
 365	parcel["id"] = LLUUID("da05fb28-0d20-e593-2728-bddb42dd0160");
 366	parcel["local_id"] = 42;
 367	parcel["name"] = "Gabriel Linden\'s Sub Plot";
 368	parcel["objects"] = objects;
 369	parcels.append(parcel);
 370
 371	fake_content["parcels"] = parcels;
 372	const LLSD& content = fake_content;
 373
 374#else
 375
 376	const LLSD& content = content_ref;
 377
 378#endif
 379
 380#ifdef DUMP_REPLIES_TO_LLINFOS
 381
 382	LLSDNotationStreamer notation_streamer(content);
 383	std::ostringstream nice_llsd;
 384	nice_llsd << notation_streamer;
 385
 386	OSMessageBox(nice_llsd.str(), "details response:", 0);
 387
 388	llinfos << "details response:" << content << llendl;
 389
 390#endif
 391
 392	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 393
 394	if(!instance)
 395	{
 396		llwarns << "Failed to get llfloaterscriptlimits instance" << llendl;
 397	}
 398	else
 399	{
 400		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 401		if(tab)
 402		{
 403			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
 404			if(panel_memory)
 405			{
 406				panel_memory->setRegionDetails(content);
 407			}
 408			else
 409			{
 410				llwarns << "Failed to get scriptlimits memory panel" << llendl;
 411			}
 412		}
 413		else
 414		{
 415			llwarns << "Failed to get scriptlimits_panels" << llendl;
 416		}
 417	}
 418}
 419
 420void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::string& reason)
 421{
 422	llwarns << "Error from responder " << reason << llendl;
 423}
 424
 425void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
 426{
 427
 428#ifdef USE_FAKE_RESPONSES
 429
 430	// just add the summary, as that's all I'm testing currently!
 431	LLSD fake_content = LLSD::emptyMap();
 432	LLSD summary = LLSD::emptyMap();
 433	LLSD available = LLSD::emptyArray();
 434	LLSD available_urls = LLSD::emptyMap();
 435	LLSD available_memory = LLSD::emptyMap();
 436	LLSD used = LLSD::emptyArray();
 437	LLSD used_urls = LLSD::emptyMap();
 438	LLSD used_memory = LLSD::emptyMap();
 439
 440	used_urls["type"] = "urls";
 441	used_urls["amount"] = FAKE_NUMBER_OF_URLS;
 442	available_urls["type"] = "urls";
 443	available_urls["amount"] = FAKE_AVAILABLE_URLS;
 444	used_memory["type"] = "memory";
 445	used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY;
 446	available_memory["type"] = "memory";
 447	available_memory["amount"] = FAKE_AVAILABLE_MEMORY;
 448
 449	used.append(used_urls);
 450	used.append(used_memory);
 451	available.append(available_urls);
 452	available.append(available_memory);
 453
 454	summary["available"] = available;
 455	summary["used"] = used;
 456	
 457	fake_content["summary"] = summary;
 458	fake_content["attachments"] = content_ref["attachments"];
 459
 460	const LLSD& content = fake_content;
 461
 462#else
 463
 464	const LLSD& content = content_ref;
 465
 466#endif
 467
 468#ifdef DUMP_REPLIES_TO_LLINFOS
 469
 470	LLSDNotationStreamer notation_streamer(content);
 471	std::ostringstream nice_llsd;
 472	nice_llsd << notation_streamer;
 473
 474	OSMessageBox(nice_llsd.str(), "attachment response:", 0);
 475	
 476	llinfos << "attachment response:" << content << llendl;
 477
 478#endif
 479
 480	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 481
 482	if(!instance)
 483	{
 484		llwarns << "Failed to get llfloaterscriptlimits instance" << llendl;
 485	}
 486	else
 487	{
 488		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 489		if(tab)
 490		{
 491			LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
 492			if(panel)
 493			{
 494				panel->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
 495
 496				LLButton* btn = panel->getChild<LLButton>("refresh_list_btn");
 497				if(btn)
 498				{
 499					btn->setEnabled(true);
 500				}
 501			
 502				panel->setAttachmentDetails(content);
 503			}
 504			else
 505			{
 506				llwarns << "Failed to get script_limits_my_avatar_panel" << llendl;
 507			}
 508		}
 509		else
 510		{
 511			llwarns << "Failed to get scriptlimits_panels" << llendl;
 512		}
 513	}
 514}
 515
 516void fetchScriptLimitsAttachmentInfoResponder::error(U32 status, const std::string& reason)
 517{
 518	llwarns << "Error from responder " << reason << llendl;
 519}
 520
 521///----------------------------------------------------------------------------
 522// Memory Panel
 523///----------------------------------------------------------------------------
 524
 525LLPanelScriptLimitsRegionMemory::~LLPanelScriptLimitsRegionMemory()
 526{
 527	if(!mParcelId.isNull())
 528	{
 529		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
 530		mParcelId.setNull();
 531	}
 532};
 533
 534BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources()
 535{
 536	LLSD body;
 537	std::string url = gAgent.getRegion()->getCapability("LandResources");
 538	if (!url.empty())
 539	{
 540		body["parcel_id"] = mParcelId;
 541
 542		LLSD info;
 543		info["parcel_id"] = mParcelId;
 544		LLHTTPClient::post(url, body, new fetchScriptLimitsRegionInfoResponder(info));
 545				
 546		return TRUE;
 547	}
 548	else
 549	{
 550		return FALSE;
 551	}
 552}
 553
 554void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parcel_data)
 555{
 556	if(!getLandScriptResources())
 557	{
 558		std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
 559		getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_error));
 560	}
 561	else
 562	{
 563		std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
 564		getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
 565	}
 566}
 567
 568void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
 569{
 570	if (!parcel_id.isNull())
 571	{
 572		if(!mParcelId.isNull())
 573		{
 574			LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
 575			mParcelId.setNull();
 576		}
 577		mParcelId = parcel_id;
 578		LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
 579		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
 580	}
 581	else
 582	{
 583		std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
 584		getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_error));
 585	}
 586}
 587
 588// virtual
 589void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason)
 590{
 591	llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
 592}
 593
 594// callback from the name cache with an owner name to add to the list
 595void LLPanelScriptLimitsRegionMemory::onNameCache(
 596						 const LLUUID& id,
 597						 const std::string& full_name)
 598{
 599	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");	
 600	if(!list)
 601	{
 602		return;
 603	}
 604	
 605	std::string name;
 606	if (LLAvatarNameCache::useDisplayNames())
 607	{
 608		name = LLCacheName::buildUsername(full_name);
 609	}
 610	else
 611	{
 612		name = full_name;
 613	}
 614
 615	std::vector<LLSD>::iterator id_itor;
 616	for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
 617	{
 618		LLSD element = *id_itor;
 619		if(element["owner_id"].asUUID() == id)
 620		{
 621			LLScrollListItem* item = list->getItem(element["id"].asUUID());
 622
 623			if(item)
 624			{
 625				item->getColumn(3)->setValue(LLSD(name));
 626				element["columns"][3]["value"] = name;
 627			}
 628		}
 629	}
 630}
 631
 632void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
 633{
 634	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
 635	
 636	if(!list)
 637	{
 638		llwarns << "Error getting the scripts_list control" << llendl;
 639		return;
 640	}
 641
 642	S32 number_parcels = content["parcels"].size();
 643
 644	LLStringUtil::format_map_t args_parcels;
 645	args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
 646	std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
 647	getChild<LLUICtrl>("parcels_listed")->setValue(LLSD(msg_parcels));
 648
 649	uuid_vec_t names_requested;
 650
 651	// This makes the assumption that all objects will have the same set
 652	// of attributes, ie they will all have, or none will have locations
 653	// This is a pretty safe assumption as it's reliant on server version.
 654	bool has_locations = false;
 655	bool has_local_ids = false;
 656
 657	for(S32 i = 0; i < number_parcels; i++)
 658	{
 659		std::string parcel_name = content["parcels"][i]["name"].asString();
 660		LLUUID parcel_id = content["parcels"][i]["id"].asUUID();
 661		S32 number_objects = content["parcels"][i]["objects"].size();
 662
 663		S32 local_id = 0;
 664		if(content["parcels"][i].has("local_id"))
 665		{
 666			// if any locations are found flag that we can use them and turn on the highlight button
 667			has_local_ids = true;
 668			local_id = content["parcels"][i]["local_id"].asInteger();
 669		}
 670
 671		for(S32 j = 0; j < number_objects; j++)
 672		{
 673			S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
 674			
 675			S32 urls = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger();
 676			
 677			std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
 678			LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
 679			LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
 680			// This field may not be sent by all server versions, but it's OK if
 681			// it uses the LLSD default of false
 682			bool is_group_owned = content["parcels"][i]["objects"][j]["is_group_owned"].asBoolean();
 683
 684			F32 location_x = 0.0f;
 685			F32 location_y = 0.0f;
 686			F32 location_z = 0.0f;
 687
 688			if(content["parcels"][i]["objects"][j].has("location"))
 689			{
 690				// if any locations are found flag that we can use them and turn on the highlight button
 691				LLVector3 vec = ll_vector3_from_sd(content["parcels"][i]["objects"][j]["location"]);
 692				has_locations = true;
 693				location_x = vec.mV[0];
 694				location_y = vec.mV[1];
 695				location_z = vec.mV[2];
 696			}
 697
 698			std::string owner_buf;
 699
 700			// in the future the server will give us owner names, so see if we're there yet:
 701			if(content["parcels"][i]["objects"][j].has("owner_name"))
 702			{
 703				owner_buf = content["parcels"][i]["objects"][j]["owner_name"].asString();
 704			}
 705			// ...and if not use the slightly more painful method of disovery:
 706			else
 707			{
 708				BOOL name_is_cached;
 709				if (is_group_owned)
 710				{
 711					name_is_cached = gCacheName->getGroupName(owner_id, owner_buf);
 712				}
 713				else
 714				{
 715					name_is_cached = gCacheName->getFullName(owner_id, owner_buf);  // username
 716					if (LLAvatarNameCache::useDisplayNames())
 717					{
 718						owner_buf = LLCacheName::buildUsername(owner_buf);
 719					}
 720				}
 721				if(!name_is_cached)
 722				{
 723					if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
 724					{
 725						names_requested.push_back(owner_id);
 726						gCacheName->get(owner_id, is_group_owned,  // username
 727							boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
 728							    this, _1, _2));
 729					}
 730				}
 731			}
 732
 733			LLScrollListItem::Params item_params;
 734			item_params.value = task_id;
 735
 736			LLScrollListCell::Params cell_params;
 737			cell_params.font = LLFontGL::getFontSansSerif();
 738
 739			cell_params.column = "size";
 740			cell_params.value = size;
 741			item_params.columns.add(cell_params);
 742
 743			cell_params.column = "urls";
 744			cell_params.value = urls;
 745			item_params.columns.add(cell_params);
 746
 747			cell_params.column = "name";
 748			cell_params.value = name_buf;
 749			item_params.columns.add(cell_params);
 750
 751			cell_params.column = "owner";
 752			cell_params.value = owner_buf;
 753			item_params.columns.add(cell_params);
 754
 755			cell_params.column = "parcel";
 756			cell_params.value = parcel_name;
 757			item_params.columns.add(cell_params);
 758
 759			cell_params.column = "location";
 760			cell_params.value = has_locations
 761				? llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z)
 762				: "";
 763			item_params.columns.add(cell_params);
 764
 765			list->addRow(item_params);
 766			
 767			LLSD element;
 768			element["owner_id"] = owner_id;
 769
 770			element["id"] = task_id;
 771			element["local_id"] = local_id;
 772			mObjectListItems.push_back(element);
 773		}
 774	}
 775
 776	if (has_locations)
 777	{
 778		LLButton* btn = getChild<LLButton>("highlight_btn");
 779		if(btn)
 780		{
 781			btn->setVisible(true);
 782		}
 783	}
 784
 785	if (has_local_ids)
 786	{
 787		LLButton* btn = getChild<LLButton>("return_btn");
 788		if(btn)
 789		{
 790			btn->setVisible(true);
 791		}
 792	}
 793	
 794	// save the structure to make object return easier
 795	mContent = content;
 796}
 797
 798void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content)
 799{
 800	if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
 801	{
 802		mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
 803		mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
 804		mGotParcelMemoryUsed = true;
 805	}
 806	else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
 807	{
 808		mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
 809		mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
 810		mGotParcelMemoryUsed = true;
 811	}
 812	else
 813	{
 814		llwarns << "summary doesn't contain memory info" << llendl;
 815		return;
 816	}
 817	
 818	if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
 819	{
 820		mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
 821		mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger();
 822		mGotParcelURLsUsed = true;
 823	}
 824	else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
 825	{
 826		mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
 827		mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger();
 828		mGotParcelURLsUsed = true;
 829	}
 830	else
 831	{
 832		llwarns << "summary doesn't contain urls info" << llendl;
 833		return;
 834	}
 835
 836	if((mParcelMemoryUsed >= 0) && (mParcelMemoryMax >= 0))
 837	{
 838		S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed;
 839
 840		LLStringUtil::format_map_t args_parcel_memory;
 841		args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
 842		args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax);
 843		args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available);
 844		std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory);
 845		getChild<LLUICtrl>("memory_used")->setValue(LLSD(msg_parcel_memory));
 846	}
 847
 848	if((mParcelURLsUsed >= 0) && (mParcelURLsMax >= 0))
 849	{
 850		S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed;
 851
 852		LLStringUtil::format_map_t args_parcel_urls;
 853		args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
 854		args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax);
 855		args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available);
 856		std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls);
 857		getChild<LLUICtrl>("urls_used")->setValue(LLSD(msg_parcel_urls));
 858	}
 859}
 860
 861BOOL LLPanelScriptLimitsRegionMemory::postBuild()
 862{
 863	childSetAction("refresh_list_btn", onClickRefresh, this);
 864	childSetAction("highlight_btn", onClickHighlight, this);
 865	childSetAction("return_btn", onClickReturn, this);
 866		
 867	std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
 868	getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
 869
 870	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
 871	if(!list)
 872	{
 873		return FALSE;
 874	}
 875
 876	//set all columns to resizable mode even if some columns will be empty
 877	for(S32 column = 0; column < list->getNumColumns(); column++)
 878	{
 879		LLScrollListColumn* columnp = list->getColumn(column);
 880		columnp->mHeader->setHasResizableElement(TRUE);
 881	}
 882
 883	return StartRequestChain();
 884}
 885
 886BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
 887{
 888	LLUUID region_id;
 889	
 890	LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
 891	if(!instance)
 892	{
 893		getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
 894		//might have to do parent post build here
 895		//if not logic below could use early outs
 896		return FALSE;
 897	}
 898	LLParcel* parcel = instance->getCurrentSelectedParcel();
 899	LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
 900	
 901	LLUUID current_region_id = gAgent.getRegion()->getRegionID();
 902
 903	if ((region) && (parcel))
 904	{
 905		LLVector3 parcel_center = parcel->getCenterpoint();
 906		
 907		region_id = region->getRegionID();
 908		
 909		if(region_id != current_region_id)
 910		{
 911			std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion");
 912			getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_wrong_region));
 913			return FALSE;
 914		}
 915		
 916		LLVector3d pos_global = region->getCenterGlobal();
 917		
 918		LLSD body;
 919		std::string url = region->getCapability("RemoteParcelRequest");
 920		if (!url.empty())
 921		{
 922			body["location"] = ll_sd_from_vector3(parcel_center);
 923			if (!region_id.isNull())
 924			{
 925				body["region_id"] = region_id;
 926			}
 927			if (!pos_global.isExactlyZero())
 928			{
 929				U64 region_handle = to_region_handle(pos_global);
 930				body["region_handle"] = ll_sd_from_U64(region_handle);
 931			}
 932			LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
 933		}
 934		else
 935		{
 936			llwarns << "Can't get parcel info for script information request" << region_id
 937					<< ". Region: "	<< region->getName()
 938					<< " does not support RemoteParcelRequest" << llendl;
 939					
 940			std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
 941			getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
 942		}
 943	}
 944	else
 945	{
 946		std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestNoParcelSelected");
 947		getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
 948	}
 949
 950	return LLPanelScriptLimitsInfo::postBuild();
 951}
 952
 953void LLPanelScriptLimitsRegionMemory::clearList()
 954{
 955	LLCtrlListInterface *list = childGetListInterface("scripts_list");
 956	
 957	if (list)
 958	{
 959		list->operateOnAll(LLCtrlListInterface::OP_DELETE);
 960	}
 961
 962	mGotParcelMemoryUsed = false;
 963	mGotParcelMemoryMax = false;
 964	mGotParcelURLsUsed = false;
 965	mGotParcelURLsMax = false;
 966	
 967	LLStringUtil::format_map_t args_parcel_memory;
 968	std::string msg_empty_string("");
 969	getChild<LLUICtrl>("memory_used")->setValue(LLSD(msg_empty_string));
 970	getChild<LLUICtrl>("urls_used")->setValue(LLSD(msg_empty_string));
 971	getChild<LLUICtrl>("parcels_listed")->setValue(LLSD(msg_empty_string));
 972
 973	mObjectListItems.clear();
 974}
 975
 976// static
 977void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata)
 978{
 979	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
 980	if(instance)
 981	{
 982		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
 983		if(tab)
 984		{
 985			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
 986			if(panel_memory)
 987			{
 988				//To stop people from hammering the refesh button and accidentally dosing themselves - enough requests can crash the viewer!
 989				//turn the button off, then turn it on when we get a response
 990				LLButton* btn = panel_memory->getChild<LLButton>("refresh_list_btn");
 991				if(btn)
 992				{
 993					btn->setEnabled(false);
 994				}
 995				panel_memory->clearList();
 996		
 997				panel_memory->StartRequestChain();
 998			}
 999		}
1000		return;
1001	}
1002	else
1003	{
1004		llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
1005		return;
1006	}
1007}
1008
1009void LLPanelScriptLimitsRegionMemory::showBeacon()
1010{	
1011	LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
1012	if (!list) return;
1013
1014	LLScrollListItem* first_selected = list->getFirstSelected();
1015	if (!first_selected) return;
1016
1017	std::string name = first_selected->getColumn(2)->getValue().asString();
1018	std::string pos_string =  first_selected->getColumn(5)->getValue().asString();
1019	
1020	F32 x, y, z;
1021	S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
1022	if (matched != 3) return;
1023
1024	LLVector3 pos_agent(x, y, z);
1025	LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
1026
1027	std::string tooltip("");
1028	LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);
1029}
1030
1031// static
1032void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata)
1033{
1034	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
1035	if(instance)
1036	{
1037		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
1038		if(tab)
1039		{
1040			LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
1041			if(panel)
1042			{
1043				panel->showBeacon();
1044			}
1045		}
1046		return;
1047	}
1048	else
1049	{
1050		llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
1051		return;
1052	}
1053}
1054
1055void LLPanelScriptLimitsRegionMemory::returnObjectsFromParcel(S32 local_id)
1056{
1057	LLMessageSystem *msg = gMessageSystem;
1058
1059	LLViewerRegion* region = gAgent.getRegion();
1060	if (!region) return;
1061
1062	LLCtrlListInterface *list = childGetListInterface("scripts_list");
1063	if (!list || list->getItemCount() == 0) return;
1064
1065	std::vector<LLSD>::iterator id_itor;
1066
1067	bool start_message = true;
1068
1069	for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
1070	{
1071		LLSD element = *id_itor;
1072		if (!list->isSelected(element["id"].asUUID()))
1073		{
1074			// Selected only
1075			continue;
1076		}
1077		
1078		if(element["local_id"].asInteger() != local_id)
1079		{
1080			// Not the parcel we are looking for
1081			continue;
1082		}
1083
1084		if (start_message)
1085		{
1086			msg->newMessageFast(_PREHASH_ParcelReturnObjects);
1087			msg->nextBlockFast(_PREHASH_AgentData);
1088			msg->addUUIDFast(_PREHASH_AgentID,	gAgent.getID());
1089			msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
1090			msg->nextBlockFast(_PREHASH_ParcelData);
1091			msg->addS32Fast(_PREHASH_LocalID, element["local_id"].asInteger());
1092			msg->addU32Fast(_PREHASH_ReturnType, RT_LIST);
1093			start_message = false;
1094		}
1095
1096		msg->nextBlockFast(_PREHASH_TaskIDs);
1097		msg->addUUIDFast(_PREHASH_TaskID, element["id"].asUUID());
1098
1099		if (msg->isSendFullFast(_PREHASH_TaskIDs))
1100		{
1101			msg->sendReliable(region->getHost());
1102			start_message = true;
1103		}
1104	}
1105
1106	if (!start_message)
1107	{
1108		msg->sendReliable(region->getHost());
1109	}
1110}
1111
1112void LLPanelScriptLimitsRegionMemory::returnObjects()
1113{
1114	if(!mContent.has("parcels"))
1115	{
1116		return;
1117	}
1118	
1119	S32 number_parcels = mContent["parcels"].size();
1120
1121	// a message per parcel containing all objects to be returned from that parcel
1122	for(S32 i = 0; i < number_parcels; i++)
1123	{
1124		S32 local_id = 0;
1125		if(mContent["parcels"][i].has("local_id"))
1126		{
1127			local_id = mContent["parcels"][i]["local_id"].asInteger();
1128			returnObjectsFromParcel(local_id);
1129		}
1130	}
1131
1132	onClickRefresh(NULL);
1133}
1134
1135
1136// static
1137void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
1138{
1139	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
1140	if(instance)
1141	{
1142		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
1143		if(tab)
1144		{
1145			LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
1146			if(panel)
1147			{
1148				panel->returnObjects();
1149			}
1150		}
1151		return;
1152	}
1153	else
1154	{
1155		llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
1156		return;
1157	}
1158}
1159
1160///----------------------------------------------------------------------------
1161// Attachment Panel
1162///----------------------------------------------------------------------------
1163
1164BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
1165{
1166	LLSD body;
1167	std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
1168	if (!url.empty())
1169	{
1170		LLHTTPClient::get(url, body, new fetchScriptLimitsAttachmentInfoResponder());
1171		return TRUE;
1172	}
1173	else
1174	{
1175		return FALSE;
1176	}
1177}
1178
1179void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
1180{
1181	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
1182	
1183	if(!list)
1184	{
1185		return;
1186	}
1187	
1188	S32 number_attachments = content["attachments"].size();
1189
1190	for(int i = 0; i < number_attachments; i++)
1191	{
1192		std::string humanReadableLocation = "";
1193		if(content["attachments"][i].has("location"))
1194		{
1195			std::string actualLocation = content["attachments"][i]["location"];
1196			humanReadableLocation = LLTrans::getString(actualLocation.c_str());
1197		}
1198		
1199		S32 number_objects = content["attachments"][i]["objects"].size();
1200		for(int j = 0; j < number_objects; j++)
1201		{
1202			LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
1203			S32 size = 0;
1204			if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
1205			{
1206				size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
1207			}
1208			S32 urls = 0;
1209			if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
1210			{
1211				urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger();
1212			}
1213			std::string name = content["attachments"][i]["objects"][j]["name"].asString();
1214			
1215			LLSD element;
1216
1217			element["id"] = task_id;
1218			element["columns"][0]["column"] = "size";
1219			element["columns"][0]["value"] = llformat("%d", size);
1220			element["columns"][0]["font"] = "SANSSERIF";
1221
1222			element["columns"][1]["column"] = "urls";
1223			element["columns"][1]["value"] = llformat("%d", urls);
1224			element["columns"][1]["font"] = "SANSSERIF";
1225			
1226			element["columns"][2]["column"] = "name";
1227			element["columns"][2]["value"] = name;
1228			element["columns"][2]["font"] = "SANSSERIF";
1229			
1230			element["columns"][3]["column"] = "location";
1231			element["columns"][3]["value"] = humanReadableLocation;
1232			element["columns"][3]["font"] = "SANSSERIF";
1233
1234			list->addElement(element);
1235		}
1236	}
1237	
1238	setAttachmentSummary(content);
1239
1240	getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
1241
1242	LLButton* btn = getChild<LLButton>("refresh_list_btn");
1243	if(btn)
1244	{
1245		btn->setEnabled(true);
1246	}
1247}
1248
1249BOOL LLPanelScriptLimitsAttachment::postBuild()
1250{
1251	childSetAction("refresh_list_btn", onClickRefresh, this);
1252		
1253	std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
1254	getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
1255	return requestAttachmentDetails();
1256}
1257
1258void LLPanelScriptLimitsAttachment::clearList()
1259{
1260	LLCtrlListInterface *list = childGetListInterface("scripts_list");
1261
1262	if (list)
1263	{
1264		list->operateOnAll(LLCtrlListInterface::OP_DELETE);
1265	}
1266
1267	std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
1268	getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
1269}
1270
1271void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content)
1272{
1273	if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
1274	{
1275		mAttachmentMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
1276		mAttachmentMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
1277		mGotAttachmentMemoryUsed = true;
1278	}
1279	else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
1280	{
1281		mAttachmentMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
1282		mAttachmentMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
1283		mGotAttachmentMemoryUsed = true;
1284	}
1285	else
1286	{
1287		llwarns << "attachment details don't contain memory summary info" << llendl;
1288		return;
1289	}
1290	
1291	if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
1292	{
1293		mAttachmentURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
1294		mAttachmentURLsMax = content["summary"]["available"][0]["amount"].asInteger();
1295		mGotAttachmentURLsUsed = true;
1296	}
1297	else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
1298	{
1299		mAttachmentURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
1300		mAttachmentURLsMax = content["summary"]["available"][1]["amount"].asInteger();
1301		mGotAttachmentURLsUsed = true;
1302	}
1303	else
1304	{
1305		llwarns << "attachment details don't contain urls summary info" << llendl;
1306		return;
1307	}
1308
1309	if((mAttachmentMemoryUsed >= 0) && (mAttachmentMemoryMax >= 0))
1310	{
1311		S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed;
1312
1313		LLStringUtil::format_map_t args_attachment_memory;
1314		args_attachment_memory["[COUNT]"] = llformat ("%d", mAttachmentMemoryUsed);
1315		args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax);
1316		args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available);
1317		std::string msg_attachment_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_attachment_memory);
1318		getChild<LLUICtrl>("memory_used")->setValue(LLSD(msg_attachment_memory));
1319	}
1320
1321	if((mAttachmentURLsUsed >= 0) && (mAttachmentURLsMax >= 0))
1322	{
1323		S32 attachment_urls_available = mAttachmentURLsMax - mAttachmentURLsUsed;
1324
1325		LLStringUtil::format_map_t args_attachment_urls;
1326		args_attachment_urls["[COUNT]"] = llformat ("%d", mAttachmentURLsUsed);
1327		args_attachment_urls["[MAX]"] = llformat ("%d", mAttachmentURLsMax);
1328		args_attachment_urls["[AVAILABLE]"] = llformat ("%d", attachment_urls_available);
1329		std::string msg_attachment_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_attachment_urls);
1330		getChild<LLUICtrl>("urls_used")->setValue(LLSD(msg_attachment_urls));
1331	}
1332}
1333
1334// static
1335void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
1336{
1337	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
1338	if(instance)
1339	{
1340		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
1341		LLPanelScriptLimitsAttachment* panel_attachments = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
1342		LLButton* btn = panel_attachments->getChild<LLButton>("refresh_list_btn");
1343		
1344		//To stop people from hammering the refesh button and accidentally dosing themselves - enough requests can crash the viewer!
1345		//turn the button off, then turn it on when we get a response
1346		if(btn)
1347		{
1348			btn->setEnabled(false);
1349		}
1350		panel_attachments->clearList();
1351		panel_attachments->requestAttachmentDetails();
1352		
1353		return;
1354	}
1355	else
1356	{
1357		llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
1358		return;
1359	}
1360}
1361