PageRenderTime 1358ms CodeModel.GetById 144ms app.highlight 1119ms RepoModel.GetById 78ms app.codeStats 1ms

/indra/newview/llpanelmaininventory.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1262 lines | 1008 code | 164 blank | 90 comment | 182 complexity | 816455192ab657fc94eebb138044f847 MD5 | raw file
   1/** 
   2 * @file llpanelmaininventory.cpp
   3 * @brief Implementation of llpanelmaininventory.
   4 *
   5 * $LicenseInfo:firstyear=2001&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 "llpanelmaininventory.h"
  29
  30#include "llagent.h"
  31#include "llagentcamera.h"
  32#include "llavataractions.h"
  33#include "lldndbutton.h"
  34#include "lleconomy.h"
  35#include "llfilepicker.h"
  36#include "llfloaterinventory.h"
  37#include "llinventorybridge.h"
  38#include "llinventoryfunctions.h"
  39#include "llinventorymodelbackgroundfetch.h"
  40#include "llinventorypanel.h"
  41#include "llfiltereditor.h"
  42#include "llfloatersidepanelcontainer.h"
  43#include "llfloaterreg.h"
  44#include "llmenubutton.h"
  45#include "lloutfitobserver.h"
  46#include "llpreviewtexture.h"
  47#include "llresmgr.h"
  48#include "llscrollcontainer.h"
  49#include "llsdserialize.h"
  50#include "llspinctrl.h"
  51#include "lltoggleablemenu.h"
  52#include "lltooldraganddrop.h"
  53#include "llviewermenu.h"
  54#include "llviewertexturelist.h"
  55#include "llsidepanelinventory.h"
  56
  57const std::string FILTERS_FILENAME("filters.xml");
  58
  59static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory");
  60
  61void on_file_loaded_for_save(BOOL success, 
  62							 LLViewerFetchedTexture *src_vi,
  63							 LLImageRaw* src, 
  64							 LLImageRaw* aux_src, 
  65							 S32 discard_level,
  66							 BOOL final,
  67							 void* userdata);
  68
  69///----------------------------------------------------------------------------
  70/// LLFloaterInventoryFinder
  71///----------------------------------------------------------------------------
  72
  73class LLFloaterInventoryFinder : public LLFloater
  74{
  75public:
  76	LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view);
  77	virtual void draw();
  78	/*virtual*/	BOOL	postBuild();
  79	void changeFilter(LLInventoryFilter* filter);
  80	void updateElementsFromFilter();
  81	BOOL getCheckShowEmpty();
  82	BOOL getCheckSinceLogoff();
  83
  84	static void onTimeAgo(LLUICtrl*, void *);
  85	static void onCloseBtn(void* user_data);
  86	static void selectAllTypes(void* user_data);
  87	static void selectNoTypes(void* user_data);
  88private:
  89	LLPanelMainInventory*	mPanelMainInventory;
  90	LLSpinCtrl*			mSpinSinceDays;
  91	LLSpinCtrl*			mSpinSinceHours;
  92	LLInventoryFilter*	mFilter;
  93};
  94
  95///----------------------------------------------------------------------------
  96/// LLPanelMainInventory
  97///----------------------------------------------------------------------------
  98
  99LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
 100	: LLPanel(p),
 101	  mActivePanel(NULL),
 102	  mSavedFolderState(NULL),
 103	  mFilterText(""),
 104	  mMenuGearDefault(NULL),
 105	  mMenuAdd(NULL),
 106	  mNeedUploadCost(true)
 107{
 108	LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT);
 109	// Menu Callbacks (non contex menus)
 110	mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2));
 111	mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this));
 112	mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
 113	mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
 114	mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2));
 115 	//mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow, this));
 116	mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this));
 117	mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this));
 118	mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2));
 119	mCommitCallbackRegistrar.add("Inventory.Share",  boost::bind(&LLAvatarActions::shareWithAvatars));
 120
 121	mSavedFolderState = new LLSaveFolderState();
 122	mSavedFolderState->setApply(FALSE);
 123}
 124
 125BOOL LLPanelMainInventory::postBuild()
 126{
 127	gInventory.addObserver(this);
 128	
 129	mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
 130	mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
 131	
 132	//panel->getFilter()->markDefault();
 133
 134	// Set up the default inv. panel/filter settings.
 135	mActivePanel = getChild<LLInventoryPanel>("All Items");
 136	if (mActivePanel)
 137	{
 138		// "All Items" is the previous only view, so it gets the InventorySortOrder
 139		mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER));
 140		mActivePanel->getFilter()->markDefault();
 141		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 142		mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));
 143		mResortActivePanel = true;
 144	}
 145	LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
 146	if (recent_items_panel)
 147	{
 148		recent_items_panel->setSinceLogoff(TRUE);
 149		recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);
 150		recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
 151		recent_items_panel->getFilter()->markDefault();
 152		recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));
 153	}
 154
 155	// Now load the stored settings from disk, if available.
 156	std::ostringstream filterSaveName;
 157	filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME);
 158	llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName.str() << llendl;
 159	llifstream file(filterSaveName.str());
 160	LLSD savedFilterState;
 161	if (file.is_open())
 162	{
 163		LLSDSerialize::fromXML(savedFilterState, file);
 164		file.close();
 165
 166		// Load the persistent "Recent Items" settings.
 167		// Note that the "All Items" settings do not persist.
 168		if(recent_items_panel)
 169		{
 170			if(savedFilterState.has(recent_items_panel->getFilter()->getName()))
 171			{
 172				LLSD recent_items = savedFilterState.get(
 173					recent_items_panel->getFilter()->getName());
 174				recent_items_panel->getFilter()->fromLLSD(recent_items);
 175			}
 176		}
 177
 178	}
 179
 180	mFilterEditor = getChild<LLFilterEditor>("inventory search editor");
 181	if (mFilterEditor)
 182	{
 183		mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2));
 184	}
 185
 186	mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
 187
 188	initListCommandsHandlers();
 189
 190	// *TODO:Get the cost info from the server
 191	const std::string upload_cost("10");
 192	mMenuAdd->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost);
 193	mMenuAdd->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost);
 194	mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
 195	mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
 196
 197	// Trigger callback for focus received so we can deselect items in inbox/outbox
 198	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
 199
 200	return TRUE;
 201}
 202
 203// Destroys the object
 204LLPanelMainInventory::~LLPanelMainInventory( void )
 205{
 206	// Save the filters state.
 207	LLSD filterRoot;
 208	LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
 209	if (all_items_panel)
 210	{
 211		LLInventoryFilter* filter = all_items_panel->getFilter();
 212		if (filter)
 213		{
 214			LLSD filterState;
 215			filter->toLLSD(filterState);
 216			filterRoot[filter->getName()] = filterState;
 217		}
 218	}
 219
 220	LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
 221	if (recent_items_panel)
 222	{
 223		LLInventoryFilter* filter = recent_items_panel->getFilter();
 224		if (filter)
 225		{
 226			LLSD filterState;
 227			filter->toLLSD(filterState);
 228			filterRoot[filter->getName()] = filterState;
 229		}
 230	}
 231
 232	std::ostringstream filterSaveName;
 233	filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME);
 234	llofstream filtersFile(filterSaveName.str());
 235	if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile))
 236	{
 237		llwarns << "Could not write to filters save file " << filterSaveName << llendl;
 238	}
 239	else
 240		filtersFile.close();
 241
 242	gInventory.removeObserver(this);
 243	delete mSavedFolderState;
 244}
 245
 246void LLPanelMainInventory::startSearch()
 247{
 248	// this forces focus to line editor portion of search editor
 249	if (mFilterEditor)
 250	{
 251		mFilterEditor->focusFirstItem(TRUE);
 252	}
 253}
 254
 255BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask)
 256{
 257	LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL;
 258	if (root_folder)
 259	{
 260		// first check for user accepting current search results
 261		if (mFilterEditor 
 262			&& mFilterEditor->hasFocus()
 263		    && (key == KEY_RETURN 
 264		    	|| key == KEY_DOWN)
 265		    && mask == MASK_NONE)
 266		{
 267			// move focus to inventory proper
 268			mActivePanel->setFocus(TRUE);
 269			root_folder->scrollToShowSelection();
 270			return TRUE;
 271		}
 272
 273		if (mActivePanel->hasFocus() && key == KEY_UP)
 274		{
 275			startSearch();
 276		}
 277	}
 278
 279	return LLPanel::handleKeyHere(key, mask);
 280
 281}
 282
 283//----------------------------------------------------------------------------
 284// menu callbacks
 285
 286void LLPanelMainInventory::doToSelected(const LLSD& userdata)
 287{
 288	getPanel()->getRootFolder()->doToSelected(&gInventory, userdata);
 289}
 290
 291void LLPanelMainInventory::closeAllFolders()
 292{
 293	getPanel()->getRootFolder()->closeAllFolders();
 294}
 295
 296void LLPanelMainInventory::newWindow()
 297{
 298	static S32 instance_num = 0;
 299	instance_num = (instance_num + 1) % S32_MAX;
 300
 301	if (!gAgentCamera.cameraMouselook())
 302	{
 303		LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num));
 304	}
 305}
 306
 307void LLPanelMainInventory::doCreate(const LLSD& userdata)
 308{
 309	menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata);
 310}
 311
 312void LLPanelMainInventory::resetFilters()
 313{
 314	LLFloaterInventoryFinder *finder = getFinder();
 315	getActivePanel()->getFilter()->resetDefault();
 316	if (finder)
 317	{
 318		finder->updateElementsFromFilter();
 319	}
 320
 321	setFilterTextFromFilter();
 322}
 323
 324void LLPanelMainInventory::setSortBy(const LLSD& userdata)
 325{
 326	U32 sort_order_mask = getActivePanel()->getSortOrder();
 327	std::string sort_type = userdata.asString();
 328	if (sort_type == "name")
 329	{
 330		sort_order_mask &= ~LLInventoryFilter::SO_DATE;
 331	}
 332	else if (sort_type == "date")
 333	{
 334		sort_order_mask |= LLInventoryFilter::SO_DATE;
 335	}
 336	else if (sort_type == "foldersalwaysbyname")
 337	{
 338		if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME )
 339		{
 340			sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME;
 341		}
 342		else
 343		{
 344			sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME;
 345		}
 346	}
 347	else if (sort_type == "systemfolderstotop")
 348	{
 349		if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP )
 350		{
 351			sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
 352		}
 353		else
 354		{
 355			sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
 356		}
 357	}
 358
 359	getActivePanel()->setSortOrder(sort_order_mask);
 360	gSavedSettings.setU32("InventorySortOrder", sort_order_mask);
 361}
 362
 363// static
 364BOOL LLPanelMainInventory::filtersVisible(void* user_data)
 365{
 366	LLPanelMainInventory* self = (LLPanelMainInventory*)user_data;
 367	if(!self) return FALSE;
 368
 369	return self->getFinder() != NULL;
 370}
 371
 372void LLPanelMainInventory::onClearSearch()
 373{
 374	LLFloater *finder = getFinder();
 375	if (mActivePanel)
 376	{
 377		mActivePanel->setFilterSubString(LLStringUtil::null);
 378		mActivePanel->setFilterTypes(0xffffffff);
 379		mActivePanel->setFilterLinks(LLInventoryFilter::FILTERLINK_INCLUDE_LINKS);
 380	}
 381
 382	if (finder)
 383	{
 384		LLFloaterInventoryFinder::selectAllTypes(finder);
 385	}
 386
 387	// re-open folders that were initially open
 388	if (mActivePanel)
 389	{
 390		mSavedFolderState->setApply(TRUE);
 391		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 392		LLOpenFoldersWithSelection opener;
 393		mActivePanel->getRootFolder()->applyFunctorRecursively(opener);
 394		mActivePanel->getRootFolder()->scrollToShowSelection();
 395	}
 396	mFilterSubString = "";
 397}
 398
 399void LLPanelMainInventory::onFilterEdit(const std::string& search_string )
 400{
 401	if (search_string == "")
 402	{
 403		onClearSearch();
 404	}
 405	if (!mActivePanel)
 406	{
 407		return;
 408	}
 409
 410	LLInventoryModelBackgroundFetch::instance().start();
 411
 412	mFilterSubString = search_string;
 413	if (mActivePanel->getFilterSubString().empty() && mFilterSubString.empty())
 414	{
 415			// current filter and new filter empty, do nothing
 416			return;
 417	}
 418
 419	// save current folder open state if no filter currently applied
 420	if (!mActivePanel->getRootFolder()->isFilterModified())
 421	{
 422		mSavedFolderState->setApply(FALSE);
 423		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 424	}
 425
 426	// set new filter string
 427	setFilterSubString(mFilterSubString);
 428}
 429
 430
 431 //static
 432 BOOL LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward)
 433 {
 434 	LLPanelMainInventory* active_view = NULL;
 435	
 436	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
 437	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
 438	{
 439		LLPanelMainInventory* iv = dynamic_cast<LLPanelMainInventory*>(*iter);
 440		if (iv)
 441		{
 442			if (gFocusMgr.childHasKeyboardFocus(iv))
 443			{
 444				active_view = iv;
 445				break;
 446			}
 447 		}
 448 	}
 449
 450 	if (!active_view)
 451 	{
 452 		return FALSE;
 453 	}
 454
 455 	std::string search_string(find_text);
 456
 457 	if (search_string.empty())
 458 	{
 459 		return FALSE;
 460 	}
 461
 462 	if (active_view->getPanel() &&
 463 		active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward))
 464 	{
 465 		return TRUE;
 466 	}
 467
 468 	return FALSE;
 469 }
 470
 471void LLPanelMainInventory::onFilterSelected()
 472{
 473	// Find my index
 474	mActivePanel = (LLInventoryPanel*)getChild<LLTabContainer>("inventory filter tabs")->getCurrentPanel();
 475
 476	if (!mActivePanel)
 477	{
 478		return;
 479	}
 480
 481	setFilterSubString(mFilterSubString);
 482	LLInventoryFilter* filter = mActivePanel->getFilter();
 483	LLFloaterInventoryFinder *finder = getFinder();
 484	if (finder)
 485	{
 486		finder->changeFilter(filter);
 487	}
 488	if (filter->isActive())
 489	{
 490		// If our filter is active we may be the first thing requiring a fetch so we better start it here.
 491		LLInventoryModelBackgroundFetch::instance().start();
 492	}
 493	setFilterTextFromFilter();
 494}
 495
 496const std::string LLPanelMainInventory::getFilterSubString() 
 497{ 
 498	return mActivePanel->getFilterSubString(); 
 499}
 500
 501void LLPanelMainInventory::setFilterSubString(const std::string& string) 
 502{ 
 503	mActivePanel->setFilterSubString(string); 
 504}
 505
 506BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 507										 EDragAndDropType cargo_type,
 508										 void* cargo_data,
 509										 EAcceptance* accept,
 510										 std::string& tooltip_msg)
 511{
 512	// Check to see if we are auto scrolling from the last frame
 513	LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel();
 514	BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y);
 515	if(mFilterTabs)
 516	{
 517		if(needsToScroll)
 518		{
 519			mFilterTabs->startDragAndDropDelayTimer();
 520		}
 521	}
 522	
 523	BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
 524
 525	return handled;
 526}
 527
 528// virtual
 529void LLPanelMainInventory::changed(U32)
 530{
 531	updateItemcountText();
 532}
 533
 534
 535// virtual
 536void LLPanelMainInventory::draw()
 537{
 538	if (mActivePanel && mFilterEditor)
 539	{
 540		mFilterEditor->setText(mFilterSubString);
 541	}	
 542	if (mActivePanel && mResortActivePanel)
 543	{
 544		// EXP-756: Force resorting of the list the first time we draw the list: 
 545		// In the case of date sorting, we don't have enough information at initialization time
 546		// to correctly sort the folders. Later manual resort doesn't do anything as the order value is 
 547		// set correctly. The workaround is to reset the order to alphabetical (or anything) then to the correct order.
 548		U32 order = mActivePanel->getSortOrder();
 549		mActivePanel->setSortOrder(LLInventoryFilter::SO_NAME);
 550		mActivePanel->setSortOrder(order);
 551		mResortActivePanel = false;
 552	}
 553	LLPanel::draw();
 554	updateItemcountText();
 555}
 556
 557void LLPanelMainInventory::updateItemcountText()
 558{
 559	// *TODO: Calling setlocale() on each frame may be inefficient.
 560	LLLocale locale(LLStringUtil::getLocale());
 561	std::string item_count_string;
 562	LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
 563
 564	LLStringUtil::format_map_t string_args;
 565	string_args["[ITEM_COUNT]"] = item_count_string;
 566	string_args["[FILTER]"] = getFilterText();
 567
 568	std::string text = "";
 569
 570	if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive())
 571	{
 572		text = getString("ItemcountFetching", string_args);
 573	}
 574	else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched())
 575	{
 576		text = getString("ItemcountCompleted", string_args);
 577	}
 578	else
 579	{
 580		text = getString("ItemcountUnknown");
 581	}
 582	
 583	// *TODO: Cache the LLUICtrl* for the ItemcountText control
 584	getChild<LLUICtrl>("ItemcountText")->setValue(text);
 585}
 586
 587void LLPanelMainInventory::onFocusReceived()
 588{
 589	LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
 590	if (!sidepanel_inventory)
 591	{
 592		llwarns << "Could not find Inventory Panel in My Inventory floater" << llendl;
 593		return;
 594	}
 595
 596	sidepanel_inventory->clearSelections(false, true);
 597}
 598
 599void LLPanelMainInventory::setFilterTextFromFilter() 
 600{ 
 601	mFilterText = mActivePanel->getFilter()->getFilterText(); 
 602}
 603
 604void LLPanelMainInventory::toggleFindOptions()
 605{
 606	LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE);
 607	LLFloater *floater = getFinder();
 608	if (!floater)
 609	{
 610		LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this);
 611		mFinderHandle = finder->getHandle();
 612		finder->openFloater();
 613
 614		LLFloater* parent_floater = gFloaterView->getParentFloater(this);
 615		if (parent_floater)
 616			parent_floater->addDependentFloater(mFinderHandle);
 617		// start background fetch of folders
 618		LLInventoryModelBackgroundFetch::instance().start();
 619	}
 620	else
 621	{
 622		floater->closeFloater();
 623	}
 624}
 625
 626void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
 627{
 628	getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
 629	getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb);
 630}
 631
 632void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action)
 633{
 634	updateListCommands();
 635	panel->onSelectionChange(items, user_action);
 636}
 637
 638///----------------------------------------------------------------------------
 639/// LLFloaterInventoryFinder
 640///----------------------------------------------------------------------------
 641
 642LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() 
 643{ 
 644	return (LLFloaterInventoryFinder*)mFinderHandle.get();
 645}
 646
 647
 648LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :	
 649	LLFloater(LLSD()),
 650	mPanelMainInventory(inventory_view),
 651	mFilter(inventory_view->getPanel()->getFilter())
 652{
 653	buildFromFile("floater_inventory_view_finder.xml");
 654	updateElementsFromFilter();
 655}
 656
 657BOOL LLFloaterInventoryFinder::postBuild()
 658{
 659	const LLRect& viewrect = mPanelMainInventory->getRect();
 660	setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight()));
 661
 662	childSetAction("All", selectAllTypes, this);
 663	childSetAction("None", selectNoTypes, this);
 664
 665	mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
 666	childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
 667
 668	mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
 669	childSetCommitCallback("spin_days_ago", onTimeAgo, this);
 670
 671	childSetAction("Close", onCloseBtn, this);
 672
 673	updateElementsFromFilter();
 674	return TRUE;
 675}
 676void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
 677{
 678	LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
 679	if (!self) return;
 680	
 681	if ( self->mSpinSinceDays->get() ||  self->mSpinSinceHours->get() )
 682	{
 683		self->getChild<LLUICtrl>("check_since_logoff")->setValue(false);
 684	}
 685}
 686
 687void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter)
 688{
 689	mFilter = filter;
 690	updateElementsFromFilter();
 691}
 692
 693void LLFloaterInventoryFinder::updateElementsFromFilter()
 694{
 695	if (!mFilter)
 696		return;
 697
 698	// Get data needed for filter display
 699	U32 filter_types = mFilter->getFilterObjectTypes();
 700	std::string filter_string = mFilter->getFilterSubString();
 701	LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
 702	U32 hours = mFilter->getHoursAgo();
 703
 704	// update the ui elements
 705	setTitle(mFilter->getName());
 706
 707	getChild<LLUICtrl>("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
 708
 709	getChild<LLUICtrl>("check_calling_card")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
 710	getChild<LLUICtrl>("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
 711	getChild<LLUICtrl>("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
 712	getChild<LLUICtrl>("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
 713	getChild<LLUICtrl>("check_mesh")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MESH));
 714	getChild<LLUICtrl>("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
 715	getChild<LLUICtrl>("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
 716	getChild<LLUICtrl>("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
 717	getChild<LLUICtrl>("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
 718	getChild<LLUICtrl>("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
 719	getChild<LLUICtrl>("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
 720	getChild<LLUICtrl>("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
 721	getChild<LLUICtrl>("check_since_logoff")->setValue(mFilter->isSinceLogoff());
 722	mSpinSinceHours->set((F32)(hours % 24));
 723	mSpinSinceDays->set((F32)(hours / 24));
 724}
 725
 726void LLFloaterInventoryFinder::draw()
 727{
 728	LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW);
 729	U32 filter = 0xffffffff;
 730	BOOL filtered_by_all_types = TRUE;
 731
 732	if (!getChild<LLUICtrl>("check_animation")->getValue())
 733	{
 734		filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
 735		filtered_by_all_types = FALSE;
 736	}
 737
 738
 739	if (!getChild<LLUICtrl>("check_calling_card")->getValue())
 740	{
 741		filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
 742		filtered_by_all_types = FALSE;
 743	}
 744
 745	if (!getChild<LLUICtrl>("check_clothing")->getValue())
 746	{
 747		filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
 748		filtered_by_all_types = FALSE;
 749	}
 750
 751	if (!getChild<LLUICtrl>("check_gesture")->getValue())
 752	{
 753		filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
 754		filtered_by_all_types = FALSE;
 755	}
 756
 757	if (!getChild<LLUICtrl>("check_landmark")->getValue())
 758
 759
 760	{
 761		filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
 762		filtered_by_all_types = FALSE;
 763	}
 764
 765	if (!getChild<LLUICtrl>("check_mesh")->getValue())
 766	{
 767		filter &= ~(0x1 << LLInventoryType::IT_MESH);
 768		filtered_by_all_types = FALSE;
 769	}
 770
 771	if (!getChild<LLUICtrl>("check_notecard")->getValue())
 772	{
 773		filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
 774		filtered_by_all_types = FALSE;
 775	}
 776
 777	if (!getChild<LLUICtrl>("check_object")->getValue())
 778	{
 779		filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
 780		filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
 781		filtered_by_all_types = FALSE;
 782	}
 783
 784	if (!getChild<LLUICtrl>("check_script")->getValue())
 785	{
 786		filter &= ~(0x1 << LLInventoryType::IT_LSL);
 787		filtered_by_all_types = FALSE;
 788	}
 789
 790	if (!getChild<LLUICtrl>("check_sound")->getValue())
 791	{
 792		filter &= ~(0x1 << LLInventoryType::IT_SOUND);
 793		filtered_by_all_types = FALSE;
 794	}
 795
 796	if (!getChild<LLUICtrl>("check_texture")->getValue())
 797	{
 798		filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
 799		filtered_by_all_types = FALSE;
 800	}
 801
 802	if (!getChild<LLUICtrl>("check_snapshot")->getValue())
 803	{
 804		filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
 805		filtered_by_all_types = FALSE;
 806	}
 807
 808	if (!filtered_by_all_types)
 809	{
 810		// don't include folders in filter, unless I've selected everything
 811		filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
 812	}
 813
 814	// update the panel, panel will update the filter
 815	mPanelMainInventory->getPanel()->setShowFolderState(getCheckShowEmpty() ?
 816		LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
 817	mPanelMainInventory->getPanel()->setFilterTypes(filter);
 818	if (getCheckSinceLogoff())
 819	{
 820		mSpinSinceDays->set(0);
 821		mSpinSinceHours->set(0);
 822	}
 823	U32 days = (U32)mSpinSinceDays->get();
 824	U32 hours = (U32)mSpinSinceHours->get();
 825	if (hours > 24)
 826	{
 827		days += hours / 24;
 828		hours = (U32)hours % 24;
 829		mSpinSinceDays->set((F32)days);
 830		mSpinSinceHours->set((F32)hours);
 831	}
 832	hours += days * 24;
 833	mPanelMainInventory->getPanel()->setHoursAgo(hours);
 834	mPanelMainInventory->getPanel()->setSinceLogoff(getCheckSinceLogoff());
 835	mPanelMainInventory->setFilterTextFromFilter();
 836
 837	LLPanel::draw();
 838}
 839
 840BOOL LLFloaterInventoryFinder::getCheckShowEmpty()
 841{
 842	return getChild<LLUICtrl>("check_show_empty")->getValue();
 843}
 844
 845BOOL LLFloaterInventoryFinder::getCheckSinceLogoff()
 846{
 847	return getChild<LLUICtrl>("check_since_logoff")->getValue();
 848}
 849
 850void LLFloaterInventoryFinder::onCloseBtn(void* user_data)
 851{
 852	LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data;
 853	finderp->closeFloater();
 854}
 855
 856// static
 857void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
 858{
 859	LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
 860	if(!self) return;
 861
 862	self->getChild<LLUICtrl>("check_animation")->setValue(TRUE);
 863	self->getChild<LLUICtrl>("check_calling_card")->setValue(TRUE);
 864	self->getChild<LLUICtrl>("check_clothing")->setValue(TRUE);
 865	self->getChild<LLUICtrl>("check_gesture")->setValue(TRUE);
 866	self->getChild<LLUICtrl>("check_landmark")->setValue(TRUE);
 867	self->getChild<LLUICtrl>("check_mesh")->setValue(TRUE);
 868	self->getChild<LLUICtrl>("check_notecard")->setValue(TRUE);
 869	self->getChild<LLUICtrl>("check_object")->setValue(TRUE);
 870	self->getChild<LLUICtrl>("check_script")->setValue(TRUE);
 871	self->getChild<LLUICtrl>("check_sound")->setValue(TRUE);
 872	self->getChild<LLUICtrl>("check_texture")->setValue(TRUE);
 873	self->getChild<LLUICtrl>("check_snapshot")->setValue(TRUE);
 874}
 875
 876//static
 877void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
 878{
 879	LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
 880	if(!self) return;
 881
 882	self->getChild<LLUICtrl>("check_animation")->setValue(FALSE);
 883	self->getChild<LLUICtrl>("check_calling_card")->setValue(FALSE);
 884	self->getChild<LLUICtrl>("check_clothing")->setValue(FALSE);
 885	self->getChild<LLUICtrl>("check_gesture")->setValue(FALSE);
 886	self->getChild<LLUICtrl>("check_landmark")->setValue(FALSE);
 887	self->getChild<LLUICtrl>("check_mesh")->setValue(FALSE);
 888	self->getChild<LLUICtrl>("check_notecard")->setValue(FALSE);
 889	self->getChild<LLUICtrl>("check_object")->setValue(FALSE);
 890	self->getChild<LLUICtrl>("check_script")->setValue(FALSE);
 891	self->getChild<LLUICtrl>("check_sound")->setValue(FALSE);
 892	self->getChild<LLUICtrl>("check_texture")->setValue(FALSE);
 893	self->getChild<LLUICtrl>("check_snapshot")->setValue(FALSE);
 894}
 895
 896//////////////////////////////////////////////////////////////////////////////////
 897// List Commands                                                                //
 898
 899void LLPanelMainInventory::initListCommandsHandlers()
 900{
 901	childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
 902	childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
 903
 904	mTrashButton = getChild<LLDragAndDropButton>("trash_btn");
 905	mTrashButton->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
 906			,	_4 // BOOL drop
 907			,	_5 // EDragAndDropType cargo_type
 908			,	_7 // EAcceptance* accept
 909			));
 910
 911	mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
 912	mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
 913	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
 914	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 915	mGearMenuButton->setMenu(mMenuGearDefault);
 916	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 917
 918	// Update the trash button when selected item(s) get worn or taken off.
 919	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
 920}
 921
 922void LLPanelMainInventory::updateListCommands()
 923{
 924	bool trash_enabled = isActionEnabled("delete");
 925
 926	mTrashButton->setEnabled(trash_enabled);
 927}
 928
 929void LLPanelMainInventory::onAddButtonClick()
 930{
 931// Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed
 932// unless "Always show folders" is checked in the filter options.
 933	bool recent_active = ("Recent Items" == mActivePanel->getName());
 934	mMenuAdd->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
 935
 936	setUploadCostIfNeeded();
 937
 938	showActionMenu(mMenuAdd,"add_btn");
 939}
 940
 941void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
 942{
 943	if (menu)
 944	{
 945		menu->buildDrawLabels();
 946		menu->updateParent(LLMenuGL::sMenuContainer);
 947		LLView* spawning_view = getChild<LLView> (spawning_view_name);
 948		S32 menu_x, menu_y;
 949		//show menu in co-ordinates of panel
 950		spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
 951		menu_y += menu->getRect().getHeight();
 952		LLMenuGL::showPopup(this, menu, menu_x, menu_y);
 953	}
 954}
 955
 956void LLPanelMainInventory::onTrashButtonClick()
 957{
 958	onClipboardAction("delete");
 959}
 960
 961void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)
 962{
 963	std::string command_name = userdata.asString();
 964	getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
 965}
 966
 967void LLPanelMainInventory::saveTexture(const LLSD& userdata)
 968{
 969	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
 970	if (!current_item)
 971	{
 972		return;
 973	}
 974	
 975	const LLUUID& item_id = current_item->getListener()->getUUID();
 976	LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);
 977	if (preview_texture)
 978	{
 979		preview_texture->openToSave();
 980	}
 981}
 982
 983void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 984{
 985	if (!isActionEnabled(userdata))
 986		return;
 987
 988	const std::string command_name = userdata.asString();
 989	if (command_name == "new_window")
 990	{
 991		newWindow();
 992	}
 993	if (command_name == "sort_by_name")
 994	{
 995		const LLSD arg = "name";
 996		setSortBy(arg);
 997	}
 998	if (command_name == "sort_by_recent")
 999	{
1000		const LLSD arg = "date";
1001		setSortBy(arg);
1002	}
1003	if (command_name == "sort_folders_by_name")
1004	{
1005		const LLSD arg = "foldersalwaysbyname";
1006		setSortBy(arg);
1007	}
1008	if (command_name == "sort_system_folders_to_top")
1009	{
1010		const LLSD arg = "systemfolderstotop";
1011		setSortBy(arg);
1012	}
1013	if (command_name == "show_filters")
1014	{
1015		toggleFindOptions();
1016	}
1017	if (command_name == "reset_filters")
1018	{
1019		resetFilters();
1020	}
1021	if (command_name == "close_folders")
1022	{
1023		closeAllFolders();
1024	}
1025	if (command_name == "empty_trash")
1026	{
1027		const std::string notification = "ConfirmEmptyTrash";
1028		gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH);
1029	}
1030	if (command_name == "empty_lostnfound")
1031	{
1032		const std::string notification = "ConfirmEmptyLostAndFound";
1033		gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND);
1034	}
1035	if (command_name == "save_texture")
1036	{
1037		saveTexture(userdata);
1038	}
1039	// This doesn't currently work, since the viewer can't change an assetID an item.
1040	if (command_name == "regenerate_link")
1041	{
1042		LLInventoryPanel *active_panel = getActivePanel();
1043		LLFolderViewItem* current_item = active_panel->getRootFolder()->getCurSelectedItem();
1044		if (!current_item)
1045		{
1046			return;
1047		}
1048		const LLUUID item_id = current_item->getListener()->getUUID();
1049		LLViewerInventoryItem *item = gInventory.getItem(item_id);
1050		if (item)
1051		{
1052			item->regenerateLink();
1053		}
1054		active_panel->setSelection(item_id, TAKE_FOCUS_NO);
1055	}
1056	if (command_name == "find_original")
1057	{
1058		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
1059		if (!current_item)
1060		{
1061			return;
1062		}
1063		current_item->getListener()->performAction(getActivePanel()->getModel(), "goto");
1064	}
1065
1066	if (command_name == "find_links")
1067	{
1068		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
1069		if (!current_item)
1070		{
1071			return;
1072		}
1073		const LLUUID& item_id = current_item->getListener()->getUUID();
1074		const std::string &item_name = current_item->getListener()->getName();
1075		mFilterSubString = item_name;
1076		LLInventoryFilter *filter = mActivePanel->getFilter();
1077		filter->setFilterSubString(item_name);
1078		mFilterEditor->setText(item_name);
1079
1080		mFilterEditor->setFocus(TRUE);
1081		filter->setFilterUUID(item_id);
1082		filter->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
1083		filter->setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS);
1084	}
1085}
1086
1087bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)
1088{
1089	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
1090	if (current_item) 
1091	{
1092		LLViewerInventoryItem *inv_item = current_item->getInventoryItem();
1093		if(inv_item)
1094		{
1095			bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
1096			LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType();
1097			return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT);
1098		}
1099	}
1100	return false;
1101}
1102
1103BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
1104{
1105	const std::string command_name = userdata.asString();
1106	if (command_name == "delete")
1107	{
1108		BOOL can_delete = FALSE;
1109		LLFolderView* root = getActivePanel()->getRootFolder();
1110		if (root)
1111		{
1112			can_delete = TRUE;
1113			std::set<LLUUID> selection_set = root->getSelectionList();
1114			if (selection_set.empty()) return FALSE;
1115			for (std::set<LLUUID>::iterator iter = selection_set.begin();
1116				 iter != selection_set.end();
1117				 ++iter)
1118			{
1119				const LLUUID &item_id = (*iter);
1120				LLFolderViewItem *item = root->getItemByID(item_id);
1121				const LLFolderViewEventListener *listener = item->getListener();
1122				llassert(listener);
1123				if (!listener) return FALSE;
1124				can_delete &= listener->isItemRemovable();
1125				can_delete &= !listener->isItemInTrash();
1126			}
1127			return can_delete;
1128		}
1129		return FALSE;
1130	}
1131	if (command_name == "save_texture")
1132	{
1133		return isSaveTextureEnabled(userdata);
1134	}
1135	if (command_name == "find_original")
1136	{
1137		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
1138		if (!current_item) return FALSE;
1139		const LLUUID& item_id = current_item->getListener()->getUUID();
1140		const LLViewerInventoryItem *item = gInventory.getItem(item_id);
1141		if (item && item->getIsLinkType() && !item->getIsBrokenLink())
1142		{
1143			return TRUE;
1144		}
1145		return FALSE;
1146	}
1147
1148	if (command_name == "find_links")
1149	{
1150		LLFolderView* root = getActivePanel()->getRootFolder();
1151		std::set<LLUUID> selection_set = root->getSelectionList();
1152		if (selection_set.size() != 1) return FALSE;
1153		LLFolderViewItem* current_item = root->getCurSelectedItem();
1154		if (!current_item) return FALSE;
1155		const LLUUID& item_id = current_item->getListener()->getUUID();
1156		const LLInventoryObject *obj = gInventory.getObject(item_id);
1157		if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType()))
1158		{
1159			return TRUE;
1160		}
1161		return FALSE;
1162	}
1163	// This doesn't currently work, since the viewer can't change an assetID an item.
1164	if (command_name == "regenerate_link")
1165	{
1166		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
1167		if (!current_item) return FALSE;
1168		const LLUUID& item_id = current_item->getListener()->getUUID();
1169		const LLViewerInventoryItem *item = gInventory.getItem(item_id);
1170		if (item && item->getIsBrokenLink())
1171		{
1172			return TRUE;
1173		}
1174		return FALSE;
1175	}
1176
1177	if (command_name == "share")
1178	{
1179		LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
1180		return parent ? parent->canShare() : FALSE;
1181	}
1182
1183	return TRUE;
1184}
1185
1186BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
1187{
1188	U32 sort_order_mask = getActivePanel()->getSortOrder();
1189	const std::string command_name = userdata.asString();
1190	if (command_name == "sort_by_name")
1191	{
1192		return ~sort_order_mask & LLInventoryFilter::SO_DATE;
1193	}
1194
1195	if (command_name == "sort_by_recent")
1196	{
1197		return sort_order_mask & LLInventoryFilter::SO_DATE;
1198	}
1199
1200	if (command_name == "sort_folders_by_name")
1201	{
1202		return sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME;
1203	}
1204
1205	if (command_name == "sort_system_folders_to_top")
1206	{
1207		return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
1208	}
1209
1210	return FALSE;
1211}
1212
1213bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
1214{
1215	*accept = ACCEPT_NO;
1216
1217	const bool is_enabled = isActionEnabled("delete");
1218	if (is_enabled) *accept = ACCEPT_YES_MULTI;
1219
1220	if (is_enabled && drop)
1221	{
1222		onClipboardAction("delete");
1223	}
1224	return true;
1225}
1226
1227void LLPanelMainInventory::setUploadCostIfNeeded()
1228{
1229	// *NOTE dzaporozhan
1230	// Upload cost is set in process_economy_data() (llviewermessage.cpp). But since we
1231	// have two instances of Inventory panel at the moment(and two instances of context menu),
1232	// call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances.
1233
1234	if(mNeedUploadCost && mMenuAdd)
1235	{
1236		LLMenuItemBranchGL* upload_menu = mMenuAdd->findChild<LLMenuItemBranchGL>("upload");
1237		if(upload_menu)
1238		{
1239			S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
1240			std::string cost_str;
1241
1242			// getPriceUpload() returns -1 if no data available yet.
1243			if(upload_cost >= 0)
1244			{
1245				mNeedUploadCost = false;
1246				cost_str = llformat("%d", upload_cost);
1247			}
1248			else
1249			{
1250				cost_str = llformat("%d", gSavedSettings.getU32("DefaultUploadCost"));
1251			}
1252
1253			upload_menu->getChild<LLView>("Upload Image")->setLabelArg("[COST]", cost_str);
1254			upload_menu->getChild<LLView>("Upload Sound")->setLabelArg("[COST]", cost_str);
1255			upload_menu->getChild<LLView>("Upload Animation")->setLabelArg("[COST]", cost_str);
1256			upload_menu->getChild<LLView>("Bulk Upload")->setLabelArg("[COST]", cost_str);
1257		}
1258	}
1259}
1260
1261// List Commands                                                              //
1262////////////////////////////////////////////////////////////////////////////////