Files
SingularityViewer/indra/newview/llpanelmaininventory.cpp
Lirusaito 2653567d82 Sync with alchemy
Moves some constants out of llavatarconstants.h
8ebf8f4608bd: Change various const constants to constexpr
e07d5d43ba30: CID-143595
30b6935fc66d: CID-143595
acc96f9051cb: Fix a memory leak in viewer side baking initial wearable setup
Sync llmodel.*

Changesets assimilated:
f8f7706c2902: CID-143554 - fix out of bounds access
223eb65adce4: CID-143554 - Chase
2ceb49aaa133: CID-42838, CID-42930, CID-42933, CID-42938, CID-42940, CID-42945, CID-42948, CID-56111, CID-83907
d220005d9f23: Missing null check before deref
31dbb0f3b6ee: CID-42571 CID-42576 CID-42578
49caf082e65c: change unordered_map to flat_map
Doesn't cause as many problems as a hashmap when it comes to assumptions in the
LLUI system.
f93f5e881484: "update" linux cef
downgrade to fix javascript problems
cba818dd9269: Various null checks and etc.
1b4c6bc483bb: CID-42847, CID-42854, CID-42886, CID-42921, CID-42922, CID-42923, CID-42924, CID-42925,
CID-42927, CID-42928, CID-83871, CID-83876, CID-83878, CID-83880, CID-83900, CID-143573
0fe90cd9ec24: Various file size related things
a79f6f653dca: CID-42918 - Initialize member pointers in LLFloaterGodTools
0b70d600d978: Tweak LLFloaterBuyLand initializations
e8b173ffe813: CID-42854 - Additional fix to LLDrawInfo
b5d745cf3fde: Fix signage
4f2e2f384781: Initialize and cleanup various class member variables.
CID-42899, CID-42900, CID-42902, CID-42903, CID-42904, CID-42905, CID-42909, CID-42910,
CID-42911, CID-42912, CID-42913, CID-42967, CID-83853, CID-83898, CID-83890, CID-143584
9851a3e39b4c: Fix platform specific include directories
5c074e84f1be: Initialize and clenaup various more class member variables.
CID-42885, CID-42853, CID-42894, CID-42895, CID-42896, CID-83908, CID-143574, CID-143575,
CID-143576, CID-143576, CID-143578
ac262854ac92: Brace sub-object in initialization to make our intentions clear to clang
358da477d4c1: More double brace init
c3850119314a: Initialize various member pointers in panels
CID-83902, CID-83903, CID-83905, CID-83909, CID-83911, CID-83912, CID-143572
2016-03-30 21:06:47 -04:00

1204 lines
34 KiB
C++

/**
* @file llpanelmaininventory.cpp
* @brief Implementation of llpanelmaininventory.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llpanelmaininventory.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "lleconomy.h"
#include "llfirstuse.h"
#include "llfiltereditor.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
#include "llpreviewtexture.h"
#include "llresmgr.h"
#include "llscrollcontainer.h"
#include "llsdserialize.h"
#include "llspinctrl.h"
#include "lltooldraganddrop.h"
#include "llviewermenu.h"
#include "llviewertexturelist.h"
#include "llpanelobjectinventory.h"
#include "llappviewer.h"
#include "rlvhandler.h"
const std::string FILTERS_FILENAME("filters.xml");
std::vector<LLInventoryView*> LLInventoryView::sActiveViews;
const S32 INV_MIN_WIDTH = 240;
const S32 INV_MIN_HEIGHT = 150;
const S32 INV_FINDER_WIDTH = 160;
const S32 INV_FINDER_HEIGHT = 408;
//BOOL LLInventoryView::sOpenNextNewItem = FALSE;
class LLFloaterInventoryFinder : public LLFloater
{
public:
LLFloaterInventoryFinder(const std::string& name,
const LLRect& rect,
LLInventoryView* inventory_view);
virtual void draw();
/*virtual*/ BOOL postBuild();
virtual void onClose(bool app_quitting);
void changeFilter(LLInventoryFilter* filter);
void updateElementsFromFilter();
BOOL getCheckShowEmpty();
BOOL getCheckSinceLogoff();
static void onTimeAgo(LLUICtrl*, void *);
static void onCloseBtn(void* user_data);
static void selectAllTypes(void* user_data);
static void selectNoTypes(void* user_data);
protected:
LLInventoryView* mInventoryView;
LLSpinCtrl* mSpinSinceDays;
LLSpinCtrl* mSpinSinceHours;
LLInventoryFilter* mFilter;
};
///----------------------------------------------------------------------------
/// LLInventoryView
///----------------------------------------------------------------------------
// Default constructor
LLInventoryView::LLInventoryView(const std::string& name,
const std::string& rect,
LLInventoryModel* inventory) :
LLFloater(name, rect, std::string("Inventory"), RESIZE_YES,
INV_MIN_WIDTH, INV_MIN_HEIGHT, DRAG_ON_TOP,
MINIMIZE_NO, CLOSE_YES),
mFilterEditor(nullptr),
mFilterTabs(nullptr),
mActivePanel(nullptr),
mResortActivePanel(true),
mSavedFolderState(nullptr),
mFilterText("")
//LLHandle<LLFloater> mFinderHandle takes care of its own initialization
{
init(inventory);
}
LLInventoryView::LLInventoryView(const std::string& name,
const LLRect& rect,
LLInventoryModel* inventory) :
LLFloater(name, rect, std::string("Inventory"), RESIZE_YES,
INV_MIN_WIDTH, INV_MIN_HEIGHT, DRAG_ON_TOP,
MINIMIZE_NO, CLOSE_YES),
mFilterEditor(nullptr),
mFilterTabs(nullptr),
mActivePanel(nullptr),
mResortActivePanel(true),
mSavedFolderState(nullptr),
mFilterText("")
//LLHandle<LLFloater> mFinderHandle takes care of its own initialization
{
init(inventory);
setRect(rect); // override XML
}
void LLInventoryView::init(LLInventoryModel* inventory)
{
// Callbacks
init_inventory_actions(this);
// Controls
addBoolControl("Inventory.ShowFilters", FALSE);
addBoolControl("Inventory.SortByName", FALSE);
addBoolControl("Inventory.SortByDate", TRUE);
addBoolControl("Inventory.FoldersAlwaysByName", TRUE);
addBoolControl("Inventory.SystemFoldersToTop", TRUE);
updateSortControls();
addBoolControl("Inventory.SearchName", TRUE);
addBoolControl("Inventory.SearchDesc", FALSE);
addBoolControl("Inventory.SearchCreator", FALSE);
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory.xml", NULL);
}
BOOL LLInventoryView::postBuild()
{
gInventory.addObserver(this);
mFilterTabs = (LLTabContainer*)getChild<LLTabContainer>("inventory filter tabs");
// Set up the default inv. panel/filter settings.
mActivePanel = getChild<LLInventoryPanel>("All Items");
if (mActivePanel)
{
// "All Items" is the previous only view, so it gets the InventorySortOrder
mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER));
mActivePanel->getFilter()->markDefault();
mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
mActivePanel->setSelectCallback(boost::bind(&LLInventoryView::onSelectionChange, this, mActivePanel, _1, _2));
mResortActivePanel = true;
}
LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
if (recent_items_panel)
{
recent_items_panel->setSinceLogoff(TRUE);
recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER));
recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
recent_items_panel->getFilter()->markDefault();
recent_items_panel->setSelectCallback(boost::bind(&LLInventoryView::onSelectionChange, this, recent_items_panel, _1, _2));
}
LLInventoryPanel* worn_items_panel = getChild<LLInventoryPanel>("Worn Items");
if (worn_items_panel)
{
worn_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::WORNITEMS_SORT_ORDER));
worn_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
worn_items_panel->getFilter()->markDefault();
worn_items_panel->setFilterWorn(true);
worn_items_panel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS);
worn_items_panel->setSelectCallback(boost::bind(&LLInventoryView::onSelectionChange, this, worn_items_panel, _1, _2));
}
// Now load the stored settings from disk, if available.
std::ostringstream filterSaveName;
filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME);
LL_INFOS() << "LLInventoryView::init: reading from " << filterSaveName.str() << LL_ENDL;
llifstream file(filterSaveName.str());
LLSD savedFilterState;
if (file.is_open())
{
LLSDSerialize::fromXML(savedFilterState, file);
file.close();
// Load the persistent "Recent Items" settings.
// Note that the "All Items" and "Worn Items" settings do not persist per-account.
if(recent_items_panel)
{
if(savedFilterState.has(recent_items_panel->getFilter()->getName()))
{
LLSD recent_items = savedFilterState.get(
recent_items_panel->getFilter()->getName());
recent_items_panel->getFilter()->fromLLSD(recent_items);
}
}
}
mFilterEditor = getChild<LLFilterEditor>("inventory search editor");
if (mFilterEditor)
{
mFilterEditor->setCommitCallback(boost::bind(&LLInventoryView::onFilterEdit, this, _2));
}
mQuickFilterCombo = getChild<LLComboBox>("Quick Filter");
if (mQuickFilterCombo)
{
mQuickFilterCombo->setCommitCallback(boost::bind(LLInventoryView::onQuickFilterCommit, _1, this));
}
sActiveViews.push_back(this);
getChild<LLTabContainer>("inventory filter tabs")->setCommitCallback(boost::bind(&LLInventoryView::onFilterSelected,this));
childSetAction("Inventory.ResetAll",onResetAll,this);
childSetAction("Inventory.ExpandAll",onExpandAll,this);
childSetAction("collapse_btn", onCollapseAll, this);
return TRUE;
}
// Destroys the object
LLInventoryView::~LLInventoryView( void )
{
// Save the filters state.
LLSD filterRoot;
LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
if (all_items_panel)
{
LLInventoryFilter* filter = all_items_panel->getFilter();
if (filter)
{
LLSD filterState;
filter->toLLSD(filterState);
filterRoot[filter->getName()] = filterState;
}
}
LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
if (recent_items_panel)
{
LLInventoryFilter* filter = recent_items_panel->getFilter();
if (filter)
{
LLSD filterState;
filter->toLLSD(filterState);
filterRoot[filter->getName()] = filterState;
}
}
LLInventoryPanel* worn_items_panel = getChild<LLInventoryPanel>("Worn Items");
if (worn_items_panel)
{
LLInventoryFilter* filter = worn_items_panel->getFilter();
if (filter)
{
LLSD filterState;
filter->toLLSD(filterState);
filterRoot[filter->getName()] = filterState;
}
}
std::ostringstream filterSaveName;
filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
llofstream filtersFile(filterSaveName.str());
if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile))
{
LL_WARNS() << "Could not write to filters save file " << filterSaveName.str().c_str() << LL_ENDL;
}
else
filtersFile.close();
vector_replace_with_last(sActiveViews, this);
gInventory.removeObserver(this);
delete mSavedFolderState;
}
void LLInventoryView::startSearch()
{
// this forces focus to line editor portion of search editor
if (mFilterEditor)
{
mFilterEditor->focusFirstItem(TRUE);
}
}
// virtual, from LLView
void LLInventoryView::setVisible( BOOL visible )
{
gSavedSettings.setBOOL("ShowInventory", visible);
LLFloater::setVisible(visible);
}
// Destroy all but the last floater, which is made invisible.
void LLInventoryView::onClose(bool app_quitting)
{
// S32 count = sActiveViews.count();
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
// See LLInventoryView::closeAll() on why we're doing it this way
S32 count = 0;
for (S32 idx = 0, cnt = sActiveViews.size(); idx < cnt; idx++)
{
if (!sActiveViews.at(idx)->isDead())
count++;
}
// [/RLVa:KB]
if (count > 1)
{
destroy();
}
else
{
if (!app_quitting)
{
gSavedSettings.setBOOL("ShowInventory", FALSE);
}
// clear filters, but save user's folder state first
if (!mActivePanel->getRootFolder()->isFilterModified())
{
mSavedFolderState->setApply(FALSE);
mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
}
// onClearSearch(this);
// pass up
LLFloater::setVisible(FALSE);
}
}
BOOL LLInventoryView::handleKeyHere(KEY key, MASK mask)
{
LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL;
if (root_folder)
{
// first check for user accepting current search results
if (mFilterEditor
&& mFilterEditor->hasFocus()
&& (key == KEY_RETURN
|| key == KEY_DOWN)
&& mask == MASK_NONE)
{
// move focus to inventory proper
mActivePanel->setFocus(TRUE);
root_folder->scrollToShowSelection();
return TRUE;
}
if (mActivePanel->hasFocus() && key == KEY_UP)
{
startSearch();
}
}
return LLFloater::handleKeyHere(key, mask);
}
// static
// *TODO: remove take_keyboard_focus param
LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus)
{
if (gDisconnected || gNoRender)
{
return NULL;
}
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV))
{
return NULL;
}
// [/RLVa:KB]
LLInventoryView* iv = LLInventoryView::getActiveInventory();
#if 0 && !LL_RELEASE_FOR_DOWNLOAD
if (sActiveViews.count() == 1)
{
delete iv;
iv = NULL;
}
#endif
if(!iv && !gAgentCamera.cameraMouselook())
{
// create one.
iv = new LLInventoryView(std::string("Inventory"),
std::string("FloaterInventoryRect"),
&gInventory);
iv->open();
// keep onscreen
gFloaterView->adjustToFitScreen(iv, FALSE);
gSavedSettings.setBOOL("ShowInventory", TRUE);
}
if(iv)
{
// Make sure it's in front and it makes a noise
iv->setTitle(std::string("Inventory"));
iv->open(); /*Flawfinder: ignore*/
}
//if (take_keyboard_focus)
//{
// iv->startSearch();
// gFocusMgr.triggerFocusFlash();
//}
return iv;
}
// static
LLInventoryView* LLInventoryView::getActiveInventory()
{
LLInventoryView* iv = NULL;
S32 count = sActiveViews.size();
if(count > 0)
{
iv = sActiveViews.at(0);
S32 z_order = gFloaterView->getZOrder(iv);
S32 z_next = 0;
LLInventoryView* next_iv = NULL;
for(S32 i = 1; i < count; ++i)
{
next_iv = sActiveViews.at(i);
z_next = gFloaterView->getZOrder(next_iv);
if(z_next < z_order)
{
iv = next_iv;
z_order = z_next;
}
}
}
return iv;
}
// static
void LLInventoryView::toggleVisibility()
{
S32 count = sActiveViews.size();
if (0 == count)
{
// We're using the inventory, possibly for the first time.
LLFirstUse::useInventory();
showAgentInventory(TRUE);
}
else if (1 == count)
{
if (sActiveViews.at(0)->getVisible())
{
sActiveViews.at(0)->close();
gSavedSettings.setBOOL("ShowInventory", FALSE);
}
else
{
showAgentInventory(TRUE);
}
}
else
{
// With more than one open, we know at least one
// is visible.
// Close all the last one spawned.
S32 last_index = sActiveViews.size() - 1;
sActiveViews.at(last_index)->close();
}
}
// static
void LLInventoryView::cleanup()
{
S32 count = sActiveViews.size();
for (S32 i = 0; i < count; i++)
{
sActiveViews.at(i)->destroy();
}
}
void LLInventoryView::updateSortControls()
{
U32 order = mActivePanel ? mActivePanel->getSortOrder() : gSavedSettings.getU32("InventorySortOrder");
bool sort_by_date = order & LLInventoryFilter::SO_DATE;
bool folders_by_name = order & LLInventoryFilter::SO_FOLDERS_BY_NAME;
bool sys_folders_on_top = order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
getControl("Inventory.SortByDate")->setValue(sort_by_date);
getControl("Inventory.SortByName")->setValue(!sort_by_date);
getControl("Inventory.FoldersAlwaysByName")->setValue(folders_by_name);
getControl("Inventory.SystemFoldersToTop")->setValue(sys_folders_on_top);
}
void LLInventoryView::resetFilters()
{
LLFloaterInventoryFinder *finder = getFinder();
getActivePanel()->getFilter()->resetDefault();
if (finder)
{
finder->updateElementsFromFilter();
}
setFilterTextFromFilter();
}
// static
BOOL LLInventoryView::filtersVisible(void* user_data)
{
LLInventoryView* self = (LLInventoryView*)user_data;
if(!self) return FALSE;
return self->getFinder() != NULL;
}
void LLInventoryView::onClearSearch()
{
LLFloater *finder = getFinder();
if (mActivePanel)
{
mActivePanel->setFilterSubString(LLStringUtil::null);
mActivePanel->setFilterTypes(0xffffffffffffffffULL);
}
if (finder)
{
LLFloaterInventoryFinder::selectAllTypes(finder);
}
// re-open folders that were initially open
if (mActivePanel)
{
mSavedFolderState->setApply(TRUE);
mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
LLOpenFoldersWithSelection opener;
mActivePanel->getRootFolder()->applyFunctorRecursively(opener);
mActivePanel->getRootFolder()->scrollToShowSelection();
}
//self->mFilterSubString = "";
}
void LLInventoryView::onFilterEdit(const std::string& search_string )
{
if (search_string == "")
{
onClearSearch();
}
if (!mActivePanel)
{
return;
}
LLInventoryModelBackgroundFetch::instance().start();
//self->mFilterSubString = search_string;
std::string filter_text = search_string;
std::string uppercase_search_string = filter_text;
LLStringUtil::toUpper(uppercase_search_string);
if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty() /*self->mFilterSubString.empty()*/)
{
// current filter and new filter empty, do nothing
return;
}
// save current folder open state if no filter currently applied
if (!mActivePanel->getRootFolder()->isFilterModified())
{
mSavedFolderState->setApply(FALSE);
mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
}
// set new filter string
mActivePanel->setFilterSubString(uppercase_search_string/*self->mFilterSubString*/);
}
struct FilterEntry : public LLDictionaryEntry
{
FilterEntry(const std::string &filter_name) :
LLDictionaryEntry(filter_name){}
};
class LLFilterDictionary : public LLSingleton<LLFilterDictionary>,
public LLDictionary<U32, FilterEntry>
{
public:
LLFilterDictionary()
{}
void init(LLInventoryView *view)
{
addEntry(0x1 << LLInventoryType::IT_ANIMATION, new FilterEntry(view->getString("filter_type_animation")));
addEntry(0x1 << LLInventoryType::IT_CALLINGCARD, new FilterEntry(view->getString("filter_type_callingcard")));
addEntry(0x1 << LLInventoryType::IT_WEARABLE, new FilterEntry(view->getString("filter_type_wearable")));
addEntry(0x1 << LLInventoryType::IT_GESTURE, new FilterEntry(view->getString("filter_type_gesture")));
addEntry(0x1 << LLInventoryType::IT_LANDMARK, new FilterEntry(view->getString("filter_type_landmark")));
addEntry(0x1 << LLInventoryType::IT_NOTECARD, new FilterEntry(view->getString("filter_type_notecard")));
addEntry(0x1 << LLInventoryType::IT_OBJECT, new FilterEntry(view->getString("filter_type_object")));
addEntry(0x1 << LLInventoryType::IT_LSL, new FilterEntry(view->getString("filter_type_script")));
addEntry(0x1 << LLInventoryType::IT_SOUND, new FilterEntry(view->getString("filter_type_sound")));
addEntry(0x1 << LLInventoryType::IT_TEXTURE, new FilterEntry(view->getString("filter_type_texture")));
addEntry(0x1 << LLInventoryType::IT_SNAPSHOT, new FilterEntry(view->getString("filter_type_snapshot")));
addEntry(0xffffffff, new FilterEntry(view->getString("filter_type_all")));
}
virtual U32 notFound() const
{
return 0;
}
};
//static
void LLInventoryView::onQuickFilterCommit(LLUICtrl* ctrl, void* user_data)
{
LLComboBox* quickfilter = (LLComboBox*)ctrl;
LLInventoryView* view = (LLInventoryView*)(quickfilter->getParent());
if (!view->mActivePanel)
{
return;
}
std::string item_type = quickfilter->getSimple();
if (view->getString("filter_type_custom") == item_type)
{
// When they select custom, show the floater then return
if( !(view->filtersVisible(view)) )
{
view->toggleFindOptions();
}
return;
}
else
{
if(!LLFilterDictionary::instanceExists())
LLFilterDictionary::instance().init(view);
U32 filter_type = LLFilterDictionary::instance().lookup(item_type);
if(!filter_type)
{
LL_WARNS() << "Ignoring unknown filter: " << item_type << LL_ENDL;
return;
}
else
{
view->mActivePanel->setFilterTypes( filter_type );
// Force the filters window to update itself, if it's open.
LLFloaterInventoryFinder* finder = view->getFinder();
if( finder )
finder->updateElementsFromFilter();
}
}
}
//static
void LLInventoryView::refreshQuickFilter(LLUICtrl* ctrl)
{
LLInventoryView* view = (LLInventoryView*)(ctrl->getParent());
if (!view->mActivePanel)
{
return;
}
LLComboBox* quickfilter = view->getChild<LLComboBox>("Quick Filter");
if (!quickfilter)
{
return;
}
U32 filter_type = view->mActivePanel->getFilterObjectTypes();
if(!LLFilterDictionary::instanceExists())
LLFilterDictionary::instance().init(view);
// Mask to extract only the bit fields we care about.
// *TODO: There's probably a cleaner way to construct this mask.
U32 filter_mask = 0;
for (LLFilterDictionary::const_iterator_t dictionary_iter = LLFilterDictionary::instance().map_t::begin();
dictionary_iter != LLFilterDictionary::instance().map_t::end(); dictionary_iter++)
{
if(dictionary_iter->first != 0xffffffff)
filter_mask |= dictionary_iter->first;
}
filter_type &= filter_mask;
//LL_INFOS() << "filter_type: " << filter_type << LL_ENDL;
std::string selection;
if (filter_type == filter_mask)
{
selection = view->getString("filter_type_all");
}
else
{
const FilterEntry *entry = LLFilterDictionary::instance().lookup(filter_type);
if(entry)
selection = entry->mName;
else
selection = view->getString("filter_type_custom");
}
// Select the chosen item by label text
BOOL result = quickfilter->setSimple( (selection) );
if( !result )
{
LL_INFOS() << "The item didn't exist: " << selection << LL_ENDL;
}
}
void LLInventoryView::onResetAll(void* userdata)
{
LLInventoryView* self = (LLInventoryView*) userdata;
self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs");
if (!self->mActivePanel)
{
return;
}
if (self->mActivePanel && self->mFilterEditor)
{
self->mFilterEditor->setText(LLStringUtil::null);
}
self->onFilterEdit("");
self->mActivePanel->closeAllFolders();
}
//static
void LLInventoryView::onExpandAll(void* userdata)
{
LLInventoryView* self = (LLInventoryView*) userdata;
self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs");
if (!self->mActivePanel)
{
return;
}
self->mActivePanel->openAllFolders();
}
//static
void LLInventoryView::onCollapseAll(void* userdata)
{
LLInventoryView* self = (LLInventoryView*) userdata;
self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs");
if (!self->mActivePanel)
{
return;
}
self->mActivePanel->closeAllFolders();
}
void LLInventoryView::onFilterSelected()
{
// Find my index
mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs");
if (!mActivePanel)
{
return;
}
//>setFilterSubString(self->mFilterSubString);
LLInventoryFilter* filter = mActivePanel->getFilter();
LLFloaterInventoryFinder *finder = getFinder();
if (finder)
{
finder->changeFilter(filter);
}
if (filter->isActive())
{
// If our filter is active we may be the first thing requiring a fetch so we better start it here.
LLInventoryModelBackgroundFetch::instance().start();
}
setFilterTextFromFilter();
updateSortControls();
}
const std::string LLInventoryView::getFilterSubString()
{
return mActivePanel->getFilterSubString();
}
void LLInventoryView::setFilterSubString(const std::string& string)
{
mActivePanel->setFilterSubString(string);
}
BOOL LLInventoryView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
// Check to see if we are auto scrolling from the last frame
LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel();
BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y);
if(mFilterTabs)
{
if(needsToScroll)
{
mFilterTabs->startDragAndDropDelayTimer();
}
}
BOOL handled = LLFloater::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
return handled;
}
void LLInventoryView::changed(U32 mask)
{
// Singu note: only if there's a change we're interested in.
if ((mask & (LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) != 0)
{
updateItemcountText();
}
}
void LLInventoryView::draw()
{
if (mActivePanel && mFilterEditor)
{
mFilterEditor->setText(mActivePanel->getFilterSubString());
}
if (mActivePanel && mQuickFilterCombo)
{
refreshQuickFilter( mQuickFilterCombo );
}
if (mActivePanel && mResortActivePanel)
{
// EXP-756: Force resorting of the list the first time we draw the list:
// In the case of date sorting, we don't have enough information at initialization time
// to correctly sort the folders. Later manual resort doesn't do anything as the order value is
// set correctly. The workaround is to reset the order to alphabetical (or anything) then to the correct order.
U32 order = mActivePanel->getSortOrder();
mActivePanel->setSortOrder(LLInventoryFilter::SO_NAME);
mActivePanel->setSortOrder(order);
mResortActivePanel = false;
}
updateItemcountText();
LLFloater::draw();
}
void LLInventoryView::updateItemcountText()
{
std::ostringstream title;
title << "Inventory";
if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || LLInventoryModelBackgroundFetch::instance().isEverythingFetched())
{
LLLocale locale(LLLocale::USER_LOCALE);
std::string item_count_string;
LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
if(LLInventoryModelBackgroundFetch::instance().folderFetchActive())
title << " (Fetched " << item_count_string << " items...)";
else
title << " ("<< item_count_string << " items)";
}
title << mFilterText;
setTitle(title.str());
}
void LLInventoryView::setFilterTextFromFilter()
{
mFilterText = mActivePanel->getFilter()->getFilterText();
}
void LLInventoryView::toggleFindOptions()
{
LLFloater *floater = getFinder();
if (!floater)
{
LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(std::string("Inventory Finder"),
LLRect(getRect().mLeft - INV_FINDER_WIDTH, getRect().mTop, getRect().mLeft, getRect().mTop - INV_FINDER_HEIGHT),
this);
mFinderHandle = finder->getHandle();
finder->open(); /*Flawfinder: ignore*/
addDependentFloater(mFinderHandle);
// start background fetch of folders
LLInventoryModelBackgroundFetch::instance().start();
mFloaterControls[std::string("Inventory.ShowFilters")]->setValue(TRUE);
}
else
{
floater->close();
mFloaterControls[std::string("Inventory.ShowFilters")]->setValue(FALSE);
}
}
LLFolderView* LLInventoryView::getRootFolder() const
{
return mActivePanel ? (mActivePanel->getRootFolder()) : NULL;
}
void LLInventoryView::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
{
getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb);
getChild<LLInventoryPanel>("Worn Items")->setSelectCallback(cb);
}
void LLInventoryView::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action)
{
panel->onSelectionChange(items, user_action);
}
///----------------------------------------------------------------------------
/// LLFloaterInventoryFinder
///----------------------------------------------------------------------------
LLFloaterInventoryFinder* LLInventoryView::getFinder()
{
return (LLFloaterInventoryFinder*)mFinderHandle.get();
}
LLFloaterInventoryFinder::LLFloaterInventoryFinder(const std::string& name,
const LLRect& rect,
LLInventoryView* inventory_view) :
LLFloater(name, rect, std::string("Filters"), RESIZE_NO,
INV_FINDER_WIDTH, INV_FINDER_HEIGHT, DRAG_ON_TOP,
MINIMIZE_NO, CLOSE_YES),
mInventoryView(inventory_view),
mFilter(inventory_view->getPanel()->getFilter())
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml");
updateElementsFromFilter();
}
BOOL LLFloaterInventoryFinder::postBuild()
{
const LLRect& viewrect = mInventoryView->getRect();
setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight()));
childSetAction("All", selectAllTypes, this);
childSetAction("None", selectNoTypes, this);
mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
childSetCommitCallback("spin_days_ago", onTimeAgo, this);
childSetAction("Close", onCloseBtn, this);
updateElementsFromFilter();
return TRUE;
}
void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
{
LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
if (!self) return;
bool since_logoff=true;
if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() )
{
since_logoff = false;
}
self->childSetValue("check_since_logoff", since_logoff);
}
void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter)
{
mFilter = filter;
updateElementsFromFilter();
}
void LLFloaterInventoryFinder::updateElementsFromFilter()
{
if (!mFilter)
return;
// Get data needed for filter display
U32 filter_types = mFilter->getFilterObjectTypes();
std::string filter_string = mFilter->getFilterSubString();
LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
U32 hours = mFilter->getHoursAgo();
// update the ui elements
LLFloater::setTitle(mFilter->getName());
getChild<LLUICtrl>("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
getChild<LLUICtrl>("check_calling_card")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
getChild<LLUICtrl>("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
getChild<LLUICtrl>("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
getChild<LLUICtrl>("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
getChild<LLUICtrl>("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
getChild<LLUICtrl>("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
getChild<LLUICtrl>("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
getChild<LLUICtrl>("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
getChild<LLUICtrl>("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
getChild<LLUICtrl>("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
getChild<LLUICtrl>("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
getChild<LLUICtrl>("check_since_logoff")->setValue(mFilter->isSinceLogoff());
mSpinSinceHours->set((F32)(hours % 24));
mSpinSinceDays->set((F32)(hours / 24));
}
void LLFloaterInventoryFinder::draw()
{
U64 filter = 0xffffffffffffffffULL;
BOOL filtered_by_all_types = TRUE;
if (!getChild<LLUICtrl>("check_animation")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_calling_card")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_clothing")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_gesture")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_landmark")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_notecard")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_object")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_script")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_LSL);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_sound")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_SOUND);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_texture")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
filtered_by_all_types = FALSE;
}
if (!getChild<LLUICtrl>("check_snapshot")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
filtered_by_all_types = FALSE;
}
if (!filtered_by_all_types)
{
// don't include folders in filter, unless I've selected everything
filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
}
// update the panel, panel will update the filter
mInventoryView->getPanel()->setShowFolderState(getCheckShowEmpty() ?
LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
mInventoryView->getPanel()->setFilterTypes(filter);
if (getCheckSinceLogoff())
{
mSpinSinceDays->set(0);
mSpinSinceHours->set(0);
}
U32 days = (U32)mSpinSinceDays->get();
U32 hours = (U32)mSpinSinceHours->get();
if (hours > 24)
{
days += hours / 24;
hours = (U32)hours % 24;
mSpinSinceDays->set((F32)days);
mSpinSinceHours->set((F32)hours);
}
hours += days * 24;
mInventoryView->getPanel()->setHoursAgo(hours);
mInventoryView->getPanel()->setSinceLogoff(getCheckSinceLogoff());
mInventoryView->setFilterTextFromFilter();
LLFloater::draw();
}
void LLFloaterInventoryFinder::onClose(bool app_quitting)
{
if (mInventoryView) mInventoryView->getControl("Inventory.ShowFilters")->setValue(FALSE);
// If you want to reset the filter on close, do it here. This functionality was
// hotly debated - Paulm
#if 0
if (mInventoryView)
{
LLInventoryView::onResetFilter((void *)mInventoryView);
}
#endif
destroy();
}
BOOL LLFloaterInventoryFinder::getCheckShowEmpty()
{
return getChild<LLUICtrl>("check_show_empty")->getValue();
}
BOOL LLFloaterInventoryFinder::getCheckSinceLogoff()
{
return getChild<LLUICtrl>("check_since_logoff")->getValue();
}
void LLFloaterInventoryFinder::onCloseBtn(void* user_data)
{
LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data;
finderp->close();
}
// static
void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
{
LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
if(!self) return;
self->getChild<LLUICtrl>("check_animation")->setValue(TRUE);
self->getChild<LLUICtrl>("check_calling_card")->setValue(TRUE);
self->getChild<LLUICtrl>("check_clothing")->setValue(TRUE);
self->getChild<LLUICtrl>("check_gesture")->setValue(TRUE);
self->getChild<LLUICtrl>("check_landmark")->setValue(TRUE);
self->getChild<LLUICtrl>("check_notecard")->setValue(TRUE);
self->getChild<LLUICtrl>("check_object")->setValue(TRUE);
self->getChild<LLUICtrl>("check_script")->setValue(TRUE);
self->getChild<LLUICtrl>("check_sound")->setValue(TRUE);
self->getChild<LLUICtrl>("check_texture")->setValue(TRUE);
self->getChild<LLUICtrl>("check_snapshot")->setValue(TRUE);
}
//static
void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
{
LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
if(!self) return;
self->getChild<LLUICtrl>("check_animation")->setValue(FALSE);
self->getChild<LLUICtrl>("check_calling_card")->setValue(FALSE);
self->getChild<LLUICtrl>("check_clothing")->setValue(FALSE);
self->getChild<LLUICtrl>("check_gesture")->setValue(FALSE);
self->getChild<LLUICtrl>("check_landmark")->setValue(FALSE);
self->getChild<LLUICtrl>("check_notecard")->setValue(FALSE);
self->getChild<LLUICtrl>("check_object")->setValue(FALSE);
self->getChild<LLUICtrl>("check_script")->setValue(FALSE);
self->getChild<LLUICtrl>("check_sound")->setValue(FALSE);
self->getChild<LLUICtrl>("check_texture")->setValue(FALSE);
self->getChild<LLUICtrl>("check_snapshot")->setValue(FALSE);
}