/** * @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 "llagentbenefits.h" #include "llagentcamera.h" #include "llavataractions.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "lldndbutton.h" #include "llfilepicker.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorygallery.h" #include "llinventorymodelbackgroundfetch.h" #include "llfiltereditor.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterreg.h" #include "llmenubutton.h" #include "lloutfitobserver.h" #include "llpanelmarketplaceinbox.h" #include "llpreviewtexture.h" #include "llresmgr.h" #include "llscrollcontainer.h" #include "llsdserialize.h" #include "llsdparam.h" #include "llspinctrl.h" #include "lltoggleablemenu.h" #include "lltooldraganddrop.h" #include "lltrans.h" #include "llviewermenu.h" #include "llviewertexturelist.h" #include "llviewerinventory.h" #include "llsidepanelinventory.h" #include "llfolderview.h" #include "llradiogroup.h" #include "llenvironment.h" #include "llweb.h" const std::string FILTERS_FILENAME("filters.xml"); const std::string ALL_ITEMS("All Items"); const std::string RECENT_ITEMS("Recent Items"); const std::string WORN_ITEMS("Worn Items"); static LLPanelInjector t_inventory("panel_main_inventory"); ///---------------------------------------------------------------------------- /// LLFloaterInventoryFinder ///---------------------------------------------------------------------------- class LLFloaterInventoryFinder : public LLFloater { public: LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view); virtual void draw(); /*virtual*/ bool postBuild(); void changeFilter(LLInventoryFilter* filter); void updateElementsFromFilter(); bool getCheckShowEmpty(); bool getCheckSinceLogoff(); U32 getDateSearchDirection(); void onCreatorSelfFilterCommit(); void onCreatorOtherFilterCommit(); static void onTimeAgo(LLUICtrl*, void *); static void onCloseBtn(void* user_data); static void selectAllTypes(void* user_data); static void selectNoTypes(void* user_data); private: LLPanelMainInventory* mPanelMainInventory; LLSpinCtrl* mSpinSinceDays; LLSpinCtrl* mSpinSinceHours; LLCheckBoxCtrl* mCreatorSelf; LLCheckBoxCtrl* mCreatorOthers; LLInventoryFilter* mFilter; }; ///---------------------------------------------------------------------------- /// LLPanelMainInventory ///---------------------------------------------------------------------------- LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) : LLPanel(p), mActivePanel(NULL), mWornItemsPanel(NULL), mSavedFolderState(NULL), mFilterText(""), mMenuGearDefault(NULL), mMenuVisibility(NULL), mMenuAddHandle(), mNeedUploadCost(true), mMenuViewDefault(NULL), mSingleFolderMode(false), mForceShowInvLayout(false), mViewMode(MODE_COMBINATION), mListViewRootUpdatedConnection(), mGalleryRootUpdatedConnection() { // Menu Callbacks (non contex menus) mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this)); mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2)); mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); mEnableCallbackRegistrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasSettingsInventory(); }); mEnableCallbackRegistrar.add("Inventory.MaterialsEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasMaterialsInventory(); }); mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(false); } bool LLPanelMainInventory::postBuild() { gInventory.addObserver(this); mFilterTabs = getChild("inventory filter tabs"); mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); mCounterCtrl = getChild("ItemcountText"); //panel->getFilter().markDefault(); // Set up the default inv. panel/filter settings. mAllItemsPanel = getChild(ALL_ITEMS); if (mAllItemsPanel) { // "All Items" is the previous only view, so it gets the InventorySortOrder mAllItemsPanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); mAllItemsPanel->getFilter().markDefault(); mAllItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); mAllItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mAllItemsPanel, _1, _2)); mResortActivePanel = true; } mActivePanel = mAllItemsPanel; mRecentPanel = getChild(RECENT_ITEMS); if (mRecentPanel) { // assign default values until we will be sure that we have setting to restore mRecentPanel->setSinceLogoff(true); mRecentPanel->setSortOrder(LLInventoryFilter::SO_DATE); mRecentPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); LLInventoryFilter& recent_filter = mRecentPanel->getFilter(); recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); recent_filter.setEmptyLookupMessage("InventoryNoMatchingRecentItems"); recent_filter.markDefault(); mRecentPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mRecentPanel, _1, _2)); } mWornItemsPanel = getChild(WORN_ITEMS); if (mWornItemsPanel) { U32 filter_types = 0x0; filter_types |= 0x1 << LLInventoryType::IT_WEARABLE; filter_types |= 0x1 << LLInventoryType::IT_ATTACHMENT; filter_types |= 0x1 << LLInventoryType::IT_OBJECT; mWornItemsPanel->setFilterTypes(filter_types); mWornItemsPanel->setFilterWorn(); mWornItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mWornItemsPanel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS); LLInventoryFilter& worn_filter = mWornItemsPanel->getFilter(); worn_filter.setFilterCategoryTypes(worn_filter.getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); worn_filter.markDefault(); mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2)); } mSearchTypeCombo = getChild("search_type"); if(mSearchTypeCombo) { mSearchTypeCombo->setCommitCallback(boost::bind(&LLPanelMainInventory::onSelectSearchType, this)); } // Now load the stored settings from disk, if available. std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); LL_INFOS("Inventory") << "LLPanelMainInventory::init: reading from " << filterSaveName << LL_ENDL; llifstream file(filterSaveName.c_str()); LLSD savedFilterState; if (file.is_open()) { LLSDSerialize::fromXML(savedFilterState, file); file.close(); // Load the persistent "Recent Items" settings. // Note that the "All Items" settings do not persist. if(mRecentPanel) { if(savedFilterState.has(mRecentPanel->getFilter().getName())) { LLSD recent_items = savedFilterState.get( mRecentPanel->getFilter().getName()); LLInventoryFilter::Params p; LLParamSDParser parser; parser.readSD(recent_items, p); mRecentPanel->getFilter().fromParams(p); mRecentPanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); } } if(mActivePanel) { if(savedFilterState.has(mActivePanel->getFilter().getName())) { LLSD items = savedFilterState.get(mActivePanel->getFilter().getName()); LLInventoryFilter::Params p; LLParamSDParser parser; parser.readSD(items, p); mActivePanel->getFilter().setSearchVisibilityTypes(p); } } } mFilterEditor = getChild("inventory search editor"); if (mFilterEditor) { mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2)); } mGearMenuButton = getChild("options_gear_btn"); mVisibilityMenuButton = getChild("options_visibility_btn"); mViewMenuButton = getChild("view_btn"); mBackBtn = getChild("back_btn"); mForwardBtn = getChild("forward_btn"); mUpBtn = getChild("up_btn"); mViewModeBtn = getChild("view_mode_btn"); mNavigationBtnsPanel = getChild("nav_buttons"); mDefaultViewPanel = getChild("default_inventory_panel"); mCombinationViewPanel = getChild("combination_view_inventory"); mCombinationGalleryLayoutPanel = getChild("comb_gallery_layout"); mCombinationListLayoutPanel = getChild("comb_inventory_layout"); mCombinationLayoutStack = getChild("combination_view_stack"); mCombinationInventoryPanel = getChild("comb_single_folder_inv"); LLInventoryFilter& comb_inv_filter = mCombinationInventoryPanel->getFilter(); comb_inv_filter.setFilterThumbnails(LLInventoryFilter::FILTER_EXCLUDE_THUMBNAILS); comb_inv_filter.markDefault(); mCombinationInventoryPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onCombinationInventorySelectionChanged, this, _1, _2)); mListViewRootUpdatedConnection = mCombinationInventoryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, false)); mCombinationGalleryPanel = getChild("comb_gallery_view_inv"); mCombinationGalleryPanel->setSortOrder(mCombinationInventoryPanel->getSortOrder()); LLInventoryFilter& comb_gallery_filter = mCombinationGalleryPanel->getFilter(); comb_gallery_filter.setFilterThumbnails(LLInventoryFilter::FILTER_ONLY_THUMBNAILS); comb_gallery_filter.markDefault(); mGalleryRootUpdatedConnection = mCombinationGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, true)); mCombinationGalleryPanel->setSelectionChangeCallback(boost::bind(&LLPanelMainInventory::onCombinationGallerySelectionChanged, this, _1)); initListCommandsHandlers(); const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if (menu) { menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); } // Trigger callback for focus received so we can deselect items in inbox/outbox LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this)); return true; } // Destroys the object LLPanelMainInventory::~LLPanelMainInventory( void ) { // Save the filters state. // Some params types cannot be saved this way // for example, LLParamSDParser doesn't know about U64, // so some FilterOps params should be revised. LLSD filterRoot; if (mAllItemsPanel) { LLSD filterState; LLInventoryPanel::InventoryState p; mAllItemsPanel->getFilter().toParams(p.filter); mAllItemsPanel->getRootViewModel().getSorter().toParams(p.sort); if (p.validateBlock(false)) { LLParamSDParser().writeSD(filterState, p); filterRoot[mAllItemsPanel->getName()] = filterState; } } if (mRecentPanel) { LLSD filterState; LLInventoryPanel::InventoryState p; mRecentPanel->getFilter().toParams(p.filter); mRecentPanel->getRootViewModel().getSorter().toParams(p.sort); if (p.validateBlock(false)) { LLParamSDParser().writeSD(filterState, p); filterRoot[mRecentPanel->getName()] = filterState; } } std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); llofstream filtersFile(filterSaveName.c_str()); if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) { LL_WARNS() << "Could not write to filters save file " << filterSaveName << LL_ENDL; } else { filtersFile.close(); } gInventory.removeObserver(this); delete mSavedFolderState; auto menu = mMenuAddHandle.get(); if(menu) { menu->die(); mMenuAddHandle.markDead(); } if (mListViewRootUpdatedConnection.connected()) { mListViewRootUpdatedConnection.disconnect(); } if (mGalleryRootUpdatedConnection.connected()) { mGalleryRootUpdatedConnection.disconnect(); } } LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel() { return mAllItemsPanel; } void LLPanelMainInventory::selectAllItemsPanel() { mFilterTabs->selectFirstTab(); } bool LLPanelMainInventory::isRecentItemsPanelSelected() { return (mRecentPanel == getActivePanel()); } void LLPanelMainInventory::startSearch() { // this forces focus to line editor portion of search editor if (mFilterEditor) { mFilterEditor->focusFirstItem(true); } } bool LLPanelMainInventory::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(); } if(mSingleFolderMode && key == KEY_LEFT) { onBackFolderClicked(); } } return LLPanel::handleKeyHere(key, mask); } //---------------------------------------------------------------------------- // menu callbacks void LLPanelMainInventory::doToSelected(const LLSD& userdata) { getPanel()->doToSelected(userdata); } void LLPanelMainInventory::closeAllFolders() { getPanel()->getRootFolder()->closeAllFolders(); } S32 get_instance_num() { static S32 instance_num = 0; instance_num = (instance_num + 1) % S32_MAX; return instance_num; } LLFloaterSidePanelContainer* LLPanelMainInventory::newWindow() { S32 instance_num = get_instance_num(); if (!gAgentCamera.cameraMouselook()) { LLFloaterSidePanelContainer* floater = LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); LLSidepanelInventory* sidepanel_inventory = floater->findChild("main_panel"); sidepanel_inventory->initInventoryViews(); return floater; } return NULL; } //static void LLPanelMainInventory::newFolderWindow(LLUUID folder_id, LLUUID item_to_select) { LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();) { LLFloaterSidePanelContainer* inventory_container = dynamic_cast(*iter++); if (inventory_container) { LLSidepanelInventory* sidepanel_inventory = dynamic_cast(inventory_container->findChild("main_panel", true)); if (sidepanel_inventory) { LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); if (main_inventory && main_inventory->isSingleFolderMode() && (main_inventory->getCurrentSFVRoot() == folder_id)) { main_inventory->setFocus(true); if(item_to_select.notNull()) { main_inventory->setGallerySelection(item_to_select); } return; } } } } S32 instance_num = get_instance_num(); LLFloaterSidePanelContainer* inventory_container = LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); if(inventory_container) { LLSidepanelInventory* sidepanel_inventory = dynamic_cast(inventory_container->findChild("main_panel", true)); if (sidepanel_inventory) { LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); if (main_inventory) { main_inventory->initSingleFolderRoot(folder_id); main_inventory->toggleViewMode(); if(folder_id.notNull()) { if(item_to_select.notNull()) { main_inventory->setGallerySelection(item_to_select, true); } } } } } } void LLPanelMainInventory::doCreate(const LLSD& userdata) { reset_inventory_filter(); if(mSingleFolderMode) { if(isListViewMode() || isCombinationViewMode()) { LLFolderViewItem* current_folder = getActivePanel()->getRootFolder(); if (current_folder) { if(isCombinationViewMode()) { mForceShowInvLayout = true; } LLHandle handle = getHandle(); std::function callback_created = [handle](const LLUUID& new_id) { gInventory.notifyObservers(); // not really needed, should have been already done LLPanelMainInventory* panel = (LLPanelMainInventory*)handle.get(); if (new_id.notNull() && panel) { // might need to refresh visibility, delay rename panel->mCombInvUUIDNeedsRename = new_id; if (panel->isCombinationViewMode()) { panel->mForceShowInvLayout = true; } LL_DEBUGS("Inventory") << "Done creating inventory: " << new_id << LL_ENDL; } }; menu_create_inventory_item(NULL, getCurrentSFVRoot(), userdata, LLUUID::null, callback_created); } } else { LLHandle handle = getHandle(); std::function callback_created = [handle](const LLUUID &new_id) { gInventory.notifyObservers(); // not really needed, should have been already done if (new_id.notNull()) { LLPanelMainInventory* panel = (LLPanelMainInventory*)handle.get(); if (panel) { panel->setGallerySelection(new_id); LL_DEBUGS("Inventory") << "Done creating inventory: " << new_id << LL_ENDL; } } }; menu_create_inventory_item(NULL, getCurrentSFVRoot(), userdata, LLUUID::null, callback_created); } } else { menu_create_inventory_item(getPanel(), NULL, userdata); } } void LLPanelMainInventory::resetFilters() { LLFloaterInventoryFinder *finder = getFinder(); getCurrentFilter().resetDefault(); if (finder) { finder->updateElementsFromFilter(); } setFilterTextFromFilter(); } void LLPanelMainInventory::resetAllItemsFilters() { LLFloaterInventoryFinder *finder = getFinder(); getAllItemsPanel()->getFilter().resetDefault(); if (finder) { finder->updateElementsFromFilter(); } setFilterTextFromFilter(); } void LLPanelMainInventory::findLinks(const LLUUID& item_id, const std::string& item_name) { mFilterSubString = item_name; LLInventoryFilter &filter = mActivePanel->getFilter(); filter.setFindAllLinksMode(item_name, item_id); mFilterEditor->setText(item_name); mFilterEditor->setFocus(true); } void LLPanelMainInventory::setSortBy(const LLSD& userdata) { U32 sort_order_mask = getActivePanel()->getSortOrder(); std::string sort_type = userdata.asString(); if (sort_type == "name") { sort_order_mask &= ~LLInventoryFilter::SO_DATE; } else if (sort_type == "date") { sort_order_mask |= LLInventoryFilter::SO_DATE; } else if (sort_type == "foldersalwaysbyname") { if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME ) { sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; } else { sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME; } } else if (sort_type == "systemfolderstotop") { if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) { sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; } else { sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; } } if(mSingleFolderMode && !isListViewMode()) { mCombinationGalleryPanel->setSortOrder(sort_order_mask, true); } getActivePanel()->setSortOrder(sort_order_mask); if (isRecentItemsPanelSelected()) { gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask); } else { gSavedSettings.setU32("InventorySortOrder", sort_order_mask); } } void LLPanelMainInventory::onSelectSearchType() { std::string new_type = mSearchTypeCombo->getValue(); if (new_type == "search_by_name") { setSearchType(LLInventoryFilter::SEARCHTYPE_NAME); } if (new_type == "search_by_creator") { setSearchType(LLInventoryFilter::SEARCHTYPE_CREATOR); } if (new_type == "search_by_description") { setSearchType(LLInventoryFilter::SEARCHTYPE_DESCRIPTION); } if (new_type == "search_by_UUID") { setSearchType(LLInventoryFilter::SEARCHTYPE_UUID); } } void LLPanelMainInventory::setSearchType(LLInventoryFilter::ESearchType type) { if(mSingleFolderMode && isGalleryViewMode()) { mCombinationGalleryPanel->setSearchType(type); } if(mSingleFolderMode && isCombinationViewMode()) { mCombinationInventoryPanel->setSearchType(type); mCombinationGalleryPanel->setSearchType(type); } else { getActivePanel()->setSearchType(type); } } void LLPanelMainInventory::updateSearchTypeCombo() { LLInventoryFilter::ESearchType search_type(LLInventoryFilter::SEARCHTYPE_NAME); if(mSingleFolderMode && isGalleryViewMode()) { search_type = mCombinationGalleryPanel->getSearchType(); } else if(mSingleFolderMode && isCombinationViewMode()) { search_type = mCombinationGalleryPanel->getSearchType(); } else { search_type = getActivePanel()->getSearchType(); } switch(search_type) { case LLInventoryFilter::SEARCHTYPE_CREATOR: mSearchTypeCombo->setValue("search_by_creator"); break; case LLInventoryFilter::SEARCHTYPE_DESCRIPTION: mSearchTypeCombo->setValue("search_by_description"); break; case LLInventoryFilter::SEARCHTYPE_UUID: mSearchTypeCombo->setValue("search_by_UUID"); break; case LLInventoryFilter::SEARCHTYPE_NAME: default: mSearchTypeCombo->setValue("search_by_name"); break; } } // static bool LLPanelMainInventory::filtersVisible(void* user_data) { LLPanelMainInventory* self = (LLPanelMainInventory*)user_data; if(!self) return false; return self->getFinder() != NULL; } void LLPanelMainInventory::onClearSearch() { bool initially_active = false; LLFloater *finder = getFinder(); if (mActivePanel && (getActivePanel() != mWornItemsPanel)) { initially_active = mActivePanel->getFilter().isNotDefault(); setFilterSubString(LLStringUtil::null); mActivePanel->setFilterTypes(0xffffffffffffffffULL); mActivePanel->setFilterLinks(LLInventoryFilter::FILTERLINK_INCLUDE_LINKS); } if (finder) { LLFloaterInventoryFinder::selectAllTypes(finder); } // re-open folders that were initially open in case filter was active if (mActivePanel && (mFilterSubString.size() || initially_active) && !mSingleFolderMode) { mSavedFolderState->setApply(true); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); LLOpenFoldersWithSelection opener; mActivePanel->getRootFolder()->applyFunctorRecursively(opener); mActivePanel->getRootFolder()->scrollToShowSelection(); } mFilterSubString = ""; if (mInboxPanel) { mInboxPanel->onClearSearch(); } } void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) { if(mSingleFolderMode && isGalleryViewMode()) { mFilterSubString = search_string; mCombinationGalleryPanel->setFilterSubString(mFilterSubString); return; } if(mSingleFolderMode && isCombinationViewMode()) { mCombinationGalleryPanel->setFilterSubString(search_string); } if (search_string == "") { onClearSearch(); } if (!mActivePanel) { return; } if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { llassert(false); // this should have been done on startup LLInventoryModelBackgroundFetch::instance().start(); } mFilterSubString = search_string; if (mActivePanel->getFilterSubString().empty() && mFilterSubString.empty()) { // current filter and new filter empty, do nothing return; } // save current folder open state if no filter currently applied if (!mActivePanel->getFilter().isNotDefault()) { mSavedFolderState->setApply(false); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); } // set new filter string setFilterSubString(mFilterSubString); if (mInboxPanel) { mInboxPanel->onFilterEdit(search_string); } } //static bool LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, bool backward) { LLPanelMainInventory* active_view = NULL; LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) { LLPanelMainInventory* iv = dynamic_cast(*iter); if (iv) { if (gFocusMgr.childHasKeyboardFocus(iv)) { active_view = iv; break; } } } if (!active_view) { return false; } std::string search_string(find_text); if (search_string.empty()) { return false; } if (active_view->getPanel() && active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward)) { return true; } return false; } void LLPanelMainInventory::onFilterSelected() { // Find my index setActivePanel(); if (!mActivePanel) { return; } if (getActivePanel() == mWornItemsPanel) { mActivePanel->openAllFolders(); } updateSearchTypeCombo(); setFilterSubString(mFilterSubString); LLInventoryFilter& filter = getCurrentFilter(); LLFloaterInventoryFinder *finder = getFinder(); if (finder) { finder->changeFilter(&filter); if (mSingleFolderMode) { finder->setTitle(getLocalizedRootName()); } } if (filter.isActive() && !LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { llassert(false); // this should have been done on startup LLInventoryModelBackgroundFetch::instance().start(); } setFilterTextFromFilter(); } const std::string LLPanelMainInventory::getFilterSubString() { return mActivePanel->getFilterSubString(); } void LLPanelMainInventory::setFilterSubString(const std::string& string) { mActivePanel->setFilterSubString(string); } bool LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { if (mFilterTabs) { // Check to see if we are auto scrolling from the last frame LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); bool needsToScroll = panel->getScrollableContainer()->canAutoScroll(x, y); if (needsToScroll) { mFilterTabs->startDragAndDropDelayTimer(); } } bool handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); return handled; } // virtual void LLPanelMainInventory::changed(U32) { updateItemcountText(); } void LLPanelMainInventory::setFocusOnFilterEditor() { if (mFilterEditor) { mFilterEditor->setFocus(true); } } // virtual void LLPanelMainInventory::draw() { if (mActivePanel && mFilterEditor) { mFilterEditor->setText(mFilterSubString); } 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; } LLPanel::draw(); updateItemcountText(); updateCombinationVisibility(); } void LLPanelMainInventory::updateItemcountText() { bool update = false; if (mSingleFolderMode) { LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items); S32 item_count = items ? (S32)items->size() : 0; S32 cat_count = cats ? (S32)cats->size() : 0; if (mItemCount != item_count) { mItemCount = item_count; update = true; } if (mCategoryCount != cat_count) { mCategoryCount = cat_count; update = true; } } else { if (mItemCount != gInventory.getItemCount()) { mItemCount = gInventory.getItemCount(); update = true; } if (mCategoryCount != gInventory.getCategoryCount()) { mCategoryCount = gInventory.getCategoryCount(); update = true; } EFetchState currentFetchState{ EFetchState::Unknown }; if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) { currentFetchState = EFetchState::Fetching; } else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) { currentFetchState = EFetchState::Complete; } if (mLastFetchState != currentFetchState) { mLastFetchState = currentFetchState; update = true; } } if (mLastFilterText != getFilterText()) { mLastFilterText = getFilterText(); update = true; } if (update) { mItemCountString = ""; LLLocale locale(LLLocale::USER_LOCALE); LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount); mCategoryCountString = ""; LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount); LLStringUtil::format_map_t string_args; string_args["[ITEM_COUNT]"] = mItemCountString; string_args["[CATEGORY_COUNT]"] = mCategoryCountString; string_args["[FILTER]"] = mLastFilterText; std::string text = ""; if (mSingleFolderMode) { text = getString("ItemcountCompleted", string_args); } else { switch (mLastFetchState) { case EFetchState::Fetching: text = getString("ItemcountFetching", string_args); break; case EFetchState::Complete: text = getString("ItemcountCompleted", string_args); break; default: text = getString("ItemcountUnknown", string_args); break; } } mCounterCtrl->setValue(text); mCounterCtrl->setToolTip(text); } } void LLPanelMainInventory::onFocusReceived() { LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); if (!sidepanel_inventory) { LL_WARNS() << "Could not find Inventory Panel in My Inventory floater" << LL_ENDL; return; } sidepanel_inventory->clearSelections(false, true); } void LLPanelMainInventory::setFilterTextFromFilter() { mFilterText = getCurrentFilter().getFilterText(); } void LLPanelMainInventory::toggleFindOptions() { LLFloater *floater = getFinder(); if (!floater) { LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this); mFinderHandle = finder->getHandle(); finder->openFloater(); LLFloater* parent_floater = gFloaterView->getParentFloater(this); if (parent_floater) parent_floater->addDependentFloater(mFinderHandle); if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { llassert(false); // this should have been done on startup LLInventoryModelBackgroundFetch::instance().start(); } if (mSingleFolderMode) { finder->setTitle(getLocalizedRootName()); } } else { floater->closeFloater(); } } void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { mAllItemsPanel->setSelectCallback(cb); mRecentPanel->setSelectCallback(cb); } void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque& items, bool user_action) { updateListCommands(); panel->onSelectionChange(items, user_action); } ///---------------------------------------------------------------------------- /// LLFloaterInventoryFinder ///---------------------------------------------------------------------------- LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); } LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) : LLFloater(LLSD()), mPanelMainInventory(inventory_view), mFilter(&inventory_view->getPanel()->getFilter()) { buildFromFile("floater_inventory_view_finder.xml"); updateElementsFromFilter(); } bool LLFloaterInventoryFinder::postBuild() { const LLRect& viewrect = mPanelMainInventory->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("spin_hours_ago"); childSetCommitCallback("spin_hours_ago", onTimeAgo, this); mSpinSinceDays = getChild("spin_days_ago"); childSetCommitCallback("spin_days_ago", onTimeAgo, this); mCreatorSelf = getChild("check_created_by_me"); mCreatorOthers = getChild("check_created_by_others"); mCreatorSelf->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorSelfFilterCommit, this)); mCreatorOthers->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorOtherFilterCommit, this)); childSetAction("Close", onCloseBtn, this); updateElementsFromFilter(); return true; } void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) { LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; if (!self) return; if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) { self->getChild("check_since_logoff")->setValue(false); U32 days = (U32)self->mSpinSinceDays->get(); U32 hours = (U32)self->mSpinSinceHours->get(); if (hours >= 24) { // Try to handle both cases of spinner clicking and text input in a sensible fashion as best as possible. // There is no way to tell if someone has clicked the spinner to get to 24 or input 24 manually, so in // this case add to days. Any value > 24 means they have input the hours manually, so do not add to the // current day value. if (24 == hours) // Got to 24 via spinner clicking or text input of 24 { days = days + hours / 24; } else // Text input, so do not add to days { days = hours / 24; } hours = (U32)hours % 24; self->mSpinSinceHours->setFocus(false); self->mSpinSinceDays->setFocus(false); self->mSpinSinceDays->set((F32)days); self->mSpinSinceHours->set((F32)hours); self->mSpinSinceHours->setFocus(true); } } } void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) { mFilter = filter; updateElementsFromFilter(); } void LLFloaterInventoryFinder::updateElementsFromFilter() { if (!mFilter) return; // Get data needed for filter display U32 filter_types = (U32)mFilter->getFilterObjectTypes(); LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); U32 hours = mFilter->getHoursAgo(); U32 date_search_direction = mFilter->getDateSearchDirection(); LLInventoryFilter::EFilterCreatorType filter_creator = mFilter->getFilterCreatorType(); bool show_created_by_me = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_SELF)); bool show_created_by_others = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_OTHERS)); // update the ui elements setTitle(mFilter->getName()); getChild("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); getChild("check_calling_card")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD)); getChild("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); getChild("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); getChild("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); getChild("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL)); getChild("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); getChild("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); getChild("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); getChild("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); getChild("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); getChild("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); getChild("check_settings")->setValue((S32)(filter_types & 0x1 << LLInventoryType::IT_SETTINGS)); getChild("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); getChild("check_created_by_me")->setValue(show_created_by_me); getChild("check_created_by_others")->setValue(show_created_by_others); getChild("check_since_logoff")->setValue(mFilter->isSinceLogoff()); mSpinSinceHours->set((F32)(hours % 24)); mSpinSinceDays->set((F32)(hours / 24)); getChild("date_search_direction")->setSelectedIndex(date_search_direction); } void LLFloaterInventoryFinder::draw() { U64 filter = 0xffffffffffffffffULL; bool filtered_by_all_types = true; if (!getChild("check_animation")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_ANIMATION); filtered_by_all_types = false; } if (!getChild("check_calling_card")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD); filtered_by_all_types = false; } if (!getChild("check_clothing")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_WEARABLE); filtered_by_all_types = false; } if (!getChild("check_gesture")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_GESTURE); filtered_by_all_types = false; } if (!getChild("check_landmark")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_LANDMARK); filtered_by_all_types = false; } if (!getChild("check_material")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_MATERIAL); filtered_by_all_types = false; } if (!getChild("check_notecard")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); filtered_by_all_types = false; } if (!getChild("check_object")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_OBJECT); filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT); filtered_by_all_types = false; } if (!getChild("check_script")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_LSL); filtered_by_all_types = false; } if (!getChild("check_sound")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_SOUND); filtered_by_all_types = false; } if (!getChild("check_texture")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_TEXTURE); filtered_by_all_types = false; } if (!getChild("check_snapshot")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT); filtered_by_all_types = false; } if (!getChild("check_settings")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_SETTINGS); filtered_by_all_types = false; } if (!filtered_by_all_types || (mPanelMainInventory->getPanel()->getFilter().getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE)) { // don't include folders in filter, unless I've selected everything or filtering by date filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); } bool is_sf_mode = mPanelMainInventory->isSingleFolderMode(); if (is_sf_mode && mPanelMainInventory->isGalleryViewMode()) { mPanelMainInventory->mCombinationGalleryPanel->getFilter().setShowFolderState(getCheckShowEmpty() ? LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mPanelMainInventory->mCombinationGalleryPanel->getFilter().setFilterObjectTypes(filter); } else { if (is_sf_mode && mPanelMainInventory->isCombinationViewMode()) { mPanelMainInventory->mCombinationGalleryPanel->getFilter().setShowFolderState(getCheckShowEmpty() ? LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mPanelMainInventory->mCombinationGalleryPanel->getFilter().setFilterObjectTypes(filter); } // update the panel, panel will update the filter mPanelMainInventory->getPanel()->setShowFolderState(getCheckShowEmpty() ? LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mPanelMainInventory->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; // A UI element that has focus will not display a new value set to it mSpinSinceHours->setFocus(false); mSpinSinceDays->setFocus(false); mSpinSinceDays->set((F32)days); mSpinSinceHours->set((F32)hours); mSpinSinceHours->setFocus(true); } hours += days * 24; mPanelMainInventory->setFilterTextFromFilter(); if (is_sf_mode && mPanelMainInventory->isGalleryViewMode()) { mPanelMainInventory->mCombinationGalleryPanel->getFilter().setHoursAgo(hours); mPanelMainInventory->mCombinationGalleryPanel->getFilter().setDateRangeLastLogoff(getCheckSinceLogoff()); mPanelMainInventory->mCombinationGalleryPanel->getFilter().setDateSearchDirection(getDateSearchDirection()); } else { if (is_sf_mode && mPanelMainInventory->isCombinationViewMode()) { mPanelMainInventory->mCombinationGalleryPanel->getFilter().setHoursAgo(hours); mPanelMainInventory->mCombinationGalleryPanel->getFilter().setDateRangeLastLogoff(getCheckSinceLogoff()); mPanelMainInventory->mCombinationGalleryPanel->getFilter().setDateSearchDirection(getDateSearchDirection()); } mPanelMainInventory->getPanel()->setHoursAgo(hours); mPanelMainInventory->getPanel()->setSinceLogoff(getCheckSinceLogoff()); mPanelMainInventory->getPanel()->setDateSearchDirection(getDateSearchDirection()); } LLPanel::draw(); } void LLFloaterInventoryFinder::onCreatorSelfFilterCommit() { bool show_creator_self = mCreatorSelf->getValue(); bool show_creator_other = mCreatorOthers->getValue(); if(show_creator_self && show_creator_other) { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_ALL); } else if(show_creator_self) { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_SELF); } else if(!show_creator_self || !show_creator_other) { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_OTHERS); mCreatorOthers->set(true); } } void LLFloaterInventoryFinder::onCreatorOtherFilterCommit() { bool show_creator_self = mCreatorSelf->getValue(); bool show_creator_other = mCreatorOthers->getValue(); if(show_creator_self && show_creator_other) { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_ALL); } else if(show_creator_other) { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_OTHERS); } else if(!show_creator_other || !show_creator_self) { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_SELF); mCreatorSelf->set(true); } } bool LLFloaterInventoryFinder::getCheckShowEmpty() { return getChild("check_show_empty")->getValue(); } bool LLFloaterInventoryFinder::getCheckSinceLogoff() { return getChild("check_since_logoff")->getValue(); } U32 LLFloaterInventoryFinder::getDateSearchDirection() { return getChild("date_search_direction")->getSelectedIndex(); } void LLFloaterInventoryFinder::onCloseBtn(void* user_data) { LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; finderp->closeFloater(); } // static void LLFloaterInventoryFinder::selectAllTypes(void* user_data) { LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; if(!self) return; self->getChild("check_animation")->setValue(true); self->getChild("check_calling_card")->setValue(true); self->getChild("check_clothing")->setValue(true); self->getChild("check_gesture")->setValue(true); self->getChild("check_landmark")->setValue(true); self->getChild("check_material")->setValue(true); self->getChild("check_notecard")->setValue(true); self->getChild("check_object")->setValue(true); self->getChild("check_script")->setValue(true); self->getChild("check_sound")->setValue(true); self->getChild("check_texture")->setValue(true); self->getChild("check_snapshot")->setValue(true); self->getChild("check_settings")->setValue(true); } //static void LLFloaterInventoryFinder::selectNoTypes(void* user_data) { LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; if(!self) return; self->getChild("check_animation")->setValue(false); self->getChild("check_calling_card")->setValue(false); self->getChild("check_clothing")->setValue(false); self->getChild("check_gesture")->setValue(false); self->getChild("check_landmark")->setValue(false); self->getChild("check_material")->setValue(false); self->getChild("check_notecard")->setValue(false); self->getChild("check_object")->setValue(false); self->getChild("check_script")->setValue(false); self->getChild("check_sound")->setValue(false); self->getChild("check_texture")->setValue(false); self->getChild("check_snapshot")->setValue(false); self->getChild("check_settings")->setValue(false); } ////////////////////////////////////////////////////////////////////////////////// // List Commands // void LLPanelMainInventory::initListCommandsHandlers() { childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this)); mViewModeBtn->setCommitCallback(boost::bind(&LLPanelMainInventory::onViewModeClick, this)); mUpBtn->setCommitCallback(boost::bind(&LLPanelMainInventory::onUpFolderClicked, this)); mBackBtn->setCommitCallback(boost::bind(&LLPanelMainInventory::onBackFolderClicked, this)); mForwardBtn->setCommitCallback(boost::bind(&LLPanelMainInventory::onForwardFolderClicked, this)); mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Visible", boost::bind(&LLPanelMainInventory::isActionVisible, this, _2)); mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_BOTTOM_LEFT, true); mMenuViewDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_view_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mViewMenuButton->setMenu(mMenuViewDefault, LLMenuButton::MP_BOTTOM_LEFT, true); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mMenuAddHandle = menu->getHandle(); mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true); // Update the trash button when selected item(s) get worn or taken off. LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); } void LLPanelMainInventory::updateListCommands() { } void LLPanelMainInventory::onAddButtonClick() { // Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed // unless "Always show folders" is checked in the filter options. LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if (menu) { disableAddIfNeeded(); setUploadCostIfNeeded(); showActionMenu(menu,"add_btn"); } } void LLPanelMainInventory::setActivePanel() { // Todo: should cover gallery mode in some way if(mSingleFolderMode && (isListViewMode() || isCombinationViewMode())) { mActivePanel = mCombinationInventoryPanel; } else { mActivePanel = (LLInventoryPanel*)mFilterTabs->getCurrentPanel(); } mViewModeBtn->setEnabled(mSingleFolderMode || (getAllItemsPanel() == getActivePanel())); } void LLPanelMainInventory::initSingleFolderRoot(const LLUUID& start_folder_id) { mCombinationInventoryPanel->initFolderRoot(start_folder_id); } void LLPanelMainInventory::initInventoryViews() { mAllItemsPanel->initializeViewBuilding(); mRecentPanel->initializeViewBuilding(); mWornItemsPanel->initializeViewBuilding(); } void LLPanelMainInventory::toggleViewMode() { if(mSingleFolderMode && isCombinationViewMode()) { mCombinationInventoryPanel->getRootFolder()->setForceArrange(false); } mSingleFolderMode = !mSingleFolderMode; mReshapeInvLayout = true; if (mCombinationGalleryPanel->getRootFolder().isNull()) { mCombinationGalleryPanel->setRootFolder(mCombinationInventoryPanel->getSingleFolderRoot()); mCombinationGalleryPanel->updateRootFolder(); } updatePanelVisibility(); setActivePanel(); updateTitle(); onFilterSelected(); if (mParentSidepanel) { if(mSingleFolderMode) { mParentSidepanel->hideInbox(); } else { mParentSidepanel->toggleInbox(); } } } void LLPanelMainInventory::onViewModeClick() { LLUUID selected_folder; LLUUID new_root_folder; if(mSingleFolderMode) { selected_folder = getCurrentSFVRoot(); } else { LLFolderView* root = getActivePanel()->getRootFolder(); std::set selection_set = root->getSelectionList(); if (selection_set.size() == 1) { LLFolderViewItem* current_item = *selection_set.begin(); if (current_item) { const LLUUID& id = static_cast(current_item->getViewModelItem())->getUUID(); if(gInventory.getCategory(id) != NULL) { new_root_folder = id; } else { const LLViewerInventoryItem* selected_item = gInventory.getItem(id); if (selected_item && selected_item->getParentUUID().notNull()) { new_root_folder = selected_item->getParentUUID(); selected_folder = id; } } } } mCombinationInventoryPanel->initFolderRoot(new_root_folder); } toggleViewMode(); if (mSingleFolderMode && new_root_folder.notNull()) { setSingleFolderViewRoot(new_root_folder, true); if(selected_folder.notNull() && isListViewMode()) { getActivePanel()->setSelection(selected_folder, TAKE_FOCUS_YES); } } else { if(selected_folder.notNull()) { selectAllItemsPanel(); getActivePanel()->setSelection(selected_folder, TAKE_FOCUS_YES); } } } void LLPanelMainInventory::onUpFolderClicked() { const LLViewerInventoryCategory* cat = gInventory.getCategory(getCurrentSFVRoot()); if (cat) { if (cat->getParentUUID().notNull()) { if(isListViewMode()) { mCombinationInventoryPanel->changeFolderRoot(cat->getParentUUID()); } if(isGalleryViewMode()) { mCombinationGalleryPanel->setRootFolder(cat->getParentUUID()); } if(isCombinationViewMode()) { mCombinationInventoryPanel->changeFolderRoot(cat->getParentUUID()); } } } } void LLPanelMainInventory::onBackFolderClicked() { if(isListViewMode()) { mCombinationInventoryPanel->onBackwardFolder(); } if(isGalleryViewMode()) { mCombinationGalleryPanel->onBackwardFolder(); } if(isCombinationViewMode()) { mCombinationInventoryPanel->onBackwardFolder(); } } void LLPanelMainInventory::onForwardFolderClicked() { if(isListViewMode()) { mCombinationInventoryPanel->onForwardFolder(); } if(isGalleryViewMode()) { mCombinationGalleryPanel->onForwardFolder(); } if(isCombinationViewMode()) { mCombinationInventoryPanel->onForwardFolder(); } } void LLPanelMainInventory::setSingleFolderViewRoot(const LLUUID& folder_id, bool clear_nav_history) { if(isListViewMode()) { mCombinationInventoryPanel->changeFolderRoot(folder_id); if(clear_nav_history) { mCombinationInventoryPanel->clearNavigationHistory(); } } else if(isGalleryViewMode()) { mCombinationGalleryPanel->setRootFolder(folder_id); if(clear_nav_history) { mCombinationGalleryPanel->clearNavigationHistory(); } } else if(isCombinationViewMode()) { mCombinationInventoryPanel->changeFolderRoot(folder_id); } updateNavButtons(); } LLUUID LLPanelMainInventory::getSingleFolderViewRoot() { return mCombinationInventoryPanel->getSingleFolderRoot(); } void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) { if (menu) { menu->buildDrawLabels(); menu->updateParent(LLMenuGL::sMenuContainer); LLView* spawning_view = getChild (spawning_view_name); S32 menu_x, menu_y; //show menu in co-ordinates of panel spawning_view->localPointToOtherView(0, 0, &menu_x, &menu_y, this); LLMenuGL::showPopup(this, menu, menu_x, menu_y); } } void LLPanelMainInventory::onClipboardAction(const LLSD& userdata) { std::string command_name = userdata.asString(); getActivePanel()->doToSelected(command_name); } void LLPanelMainInventory::saveTexture(const LLSD& userdata) { LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); if (item_id.isNull()) return; } else { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) { return; } item_id = static_cast(current_item->getViewModelItem())->getUUID(); } LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); if (preview_texture) { preview_texture->openToSave(); } } void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { if (!isActionEnabled(userdata)) return; const std::string command_name = userdata.asString(); if (command_name == "new_window") { newWindow(); } if (command_name == "sort_by_name") { const LLSD arg = "name"; setSortBy(arg); } if (command_name == "sort_by_recent") { const LLSD arg = "date"; setSortBy(arg); } if (command_name == "sort_folders_by_name") { const LLSD arg = "foldersalwaysbyname"; setSortBy(arg); } if (command_name == "sort_system_folders_to_top") { const LLSD arg = "systemfolderstotop"; setSortBy(arg); } if (command_name == "show_filters") { toggleFindOptions(); } if (command_name == "reset_filters") { resetFilters(); } if (command_name == "close_folders") { closeAllFolders(); } if (command_name == "empty_trash") { const std::string notification = "ConfirmEmptyTrash"; gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH); } if (command_name == "empty_lostnfound") { const std::string notification = "ConfirmEmptyLostAndFound"; gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND); } if (command_name == "save_texture") { saveTexture(userdata); } // This doesn't currently work, since the viewer can't change an assetID an item. if (command_name == "regenerate_link") { LLInventoryPanel *active_panel = getActivePanel(); LLFolderViewItem* current_item = active_panel->getRootFolder()->getCurSelectedItem(); if (!current_item) { return; } const LLUUID item_id = static_cast(current_item->getViewModelItem())->getUUID(); LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item) { item->regenerateLink(); } active_panel->setSelection(item_id, TAKE_FOCUS_NO); } if (command_name == "find_original") { if(mSingleFolderMode && isGalleryViewMode()) { LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getFirstSelectedItemID()); if (obj && obj->getIsLinkType()) { show_item_original(obj->getUUID()); } } else { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) { return; } static_cast(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto"); } } if (command_name == "find_links") { if(mSingleFolderMode && isGalleryViewMode()) { LLFloaterSidePanelContainer* inventory_container = newWindow(); if (inventory_container) { LLSidepanelInventory* sidepanel_inventory = dynamic_cast(inventory_container->findChild("main_panel", true)); if (sidepanel_inventory) { LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); if (main_inventory) { LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getFirstSelectedItemID()); if (obj) { main_inventory->findLinks(obj->getUUID(), obj->getName()); } } } } } else { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) { return; } const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); const std::string &item_name = current_item->getViewModelItem()->getName(); findLinks(item_id, item_name); } } if (command_name == "replace_links") { LLSD params; if(mSingleFolderMode && isGalleryViewMode()) { params = LLSD(mCombinationGalleryPanel->getFirstSelectedItemID()); } else { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (current_item) { LLInvFVBridge* bridge = (LLInvFVBridge*)current_item->getViewModelItem(); if (bridge) { LLInventoryObject* obj = bridge->getInventoryObject(); if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getActualType() != LLAssetType::AT_LINK_FOLDER) { params = LLSD(obj->getUUID()); } } } } LLFloaterReg::showInstance("linkreplace", params); } if (command_name == "close_inv_windows") { LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();) { LLFloaterSidePanelContainer* iv = dynamic_cast(*iter++); if (iv) { iv->closeFloater(); } } LLFloaterReg::hideInstance("inventory_settings"); } if (command_name == "toggle_search_outfits") { getCurrentFilter().toggleSearchVisibilityOutfits(); } if (command_name == "toggle_search_trash") { getCurrentFilter().toggleSearchVisibilityTrash(); } if (command_name == "toggle_search_library") { getCurrentFilter().toggleSearchVisibilityLibrary(); } if (command_name == "include_links") { getCurrentFilter().toggleSearchVisibilityLinks(); } if (command_name == "share") { if(mSingleFolderMode && isGalleryViewMode()) { std::set uuids{ mCombinationGalleryPanel->getFirstSelectedItemID()}; LLAvatarActions::shareWithAvatars(uuids, gFloaterView->getParentFloater(this)); } else { LLAvatarActions::shareWithAvatars(this); } } if (command_name == "shop") { LLWeb::loadURL(gSavedSettings.getString("MarketplaceURL")); } if (command_name == "list_view") { setViewMode(MODE_LIST); } if (command_name == "gallery_view") { setViewMode(MODE_GALLERY); } if (command_name == "combination_view") { setViewMode(MODE_COMBINATION); } } void LLPanelMainInventory::onVisibilityChange( bool new_visibility ) { if(!new_visibility) { LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if (menu) { menu->setVisible(false); } getActivePanel()->getRootFolder()->finishRenamingItem(); } } bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) { LLViewerInventoryItem *inv_item = NULL; if(mSingleFolderMode && isGalleryViewMode()) { inv_item = gInventory.getItem(mCombinationGalleryPanel->getFirstSelectedItemID()); } else { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (current_item) { inv_item = dynamic_cast(static_cast(current_item->getViewModelItem())->getInventoryObject()); } } if(inv_item) { bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); LLInventoryType::EType curr_type = inv_item->getInventoryType(); return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); } return false; } bool LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { const std::string command_name = userdata.asString(); if (command_name == "not_empty") { bool status = false; LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (current_item) { const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); LLInventoryModel::cat_array_t* cat_array; LLInventoryModel::item_array_t* item_array; gInventory.getDirectDescendentsOf(item_id, cat_array, item_array); status = (0 == cat_array->size() && 0 == item_array->size()); } return status; } if (command_name == "delete") { return getActivePanel()->isSelectionRemovable(); } if (command_name == "save_texture") { return isSaveTextureEnabled(userdata); } if (command_name == "find_original") { LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); } else{ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return false; item_id = static_cast(current_item->getViewModelItem())->getUUID(); } const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsLinkType() && !item->getIsBrokenLink()) { return true; } return false; } if (command_name == "find_links") { LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); } else{ LLFolderView* root = getActivePanel()->getRootFolder(); std::set selection_set = root->getSelectionList(); if (selection_set.size() != 1) return false; LLFolderViewItem* current_item = root->getCurSelectedItem(); if (!current_item) return false; item_id = static_cast(current_item->getViewModelItem())->getUUID(); } const LLInventoryObject *obj = gInventory.getObject(item_id); if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) { return true; } return false; } // This doesn't currently work, since the viewer can't change an assetID an item. if (command_name == "regenerate_link") { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return false; const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsBrokenLink()) { return true; } return false; } if (command_name == "share") { if(mSingleFolderMode && isGalleryViewMode()) { return can_share_item(mCombinationGalleryPanel->getFirstSelectedItemID()); } else{ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return false; LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel("inventory"); return parent ? parent->canShare() : false; } } if (command_name == "empty_trash") { const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); } if (command_name == "empty_lostnfound") { const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); } return true; } bool LLPanelMainInventory::isActionVisible(const LLSD& userdata) { const std::string param_str = userdata.asString(); if (param_str == "single_folder_view") { return mSingleFolderMode; } if (param_str == "multi_folder_view") { return !mSingleFolderMode; } return true; } bool LLPanelMainInventory::isActionChecked(const LLSD& userdata) { U32 sort_order_mask = (mSingleFolderMode && isGalleryViewMode()) ? mCombinationGalleryPanel->getSortOrder() : getActivePanel()->getSortOrder(); const std::string command_name = userdata.asString(); if (command_name == "sort_by_name") { return ~sort_order_mask & LLInventoryFilter::SO_DATE; } if (command_name == "sort_by_recent") { return sort_order_mask & LLInventoryFilter::SO_DATE; } if (command_name == "sort_folders_by_name") { return sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME; } if (command_name == "sort_system_folders_to_top") { return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; } if (command_name == "toggle_search_outfits") { return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_OUTFITS) != 0; } if (command_name == "toggle_search_trash") { return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0; } if (command_name == "toggle_search_library") { return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0; } if (command_name == "include_links") { return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0; } if (command_name == "list_view") { return isListViewMode(); } if (command_name == "gallery_view") { return isGalleryViewMode(); } if (command_name == "combination_view") { return isCombinationViewMode(); } return false; } void LLPanelMainInventory::setUploadCostIfNeeded() { LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if(mNeedUploadCost && menu) { const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); } } bool is_add_allowed(LLUUID folder_id) { if(!gInventory.isObjectDescendentOf(folder_id, gInventory.getRootFolderID())) { return false; } std::vector not_allowed_types; not_allowed_types.push_back(LLFolderType::FT_LOST_AND_FOUND); not_allowed_types.push_back(LLFolderType::FT_FAVORITE); not_allowed_types.push_back(LLFolderType::FT_MARKETPLACE_LISTINGS); not_allowed_types.push_back(LLFolderType::FT_TRASH); not_allowed_types.push_back(LLFolderType::FT_CURRENT_OUTFIT); not_allowed_types.push_back(LLFolderType::FT_INBOX); for (std::vector::const_iterator it = not_allowed_types.begin(); it != not_allowed_types.end(); ++it) { if(gInventory.isObjectDescendentOf(folder_id, gInventory.findCategoryUUIDForType(*it))) { return false; } } LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) { return false; } return true; } void LLPanelMainInventory::disableAddIfNeeded() { LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if (menu) { bool enable = !mSingleFolderMode || is_add_allowed(getCurrentSFVRoot()); menu->getChild("New Folder")->setEnabled(enable && !isRecentItemsPanelSelected()); menu->getChild("New Script")->setEnabled(enable); menu->getChild("New Note")->setEnabled(enable); menu->getChild("New Gesture")->setEnabled(enable); menu->setItemEnabled("New Clothes", enable); menu->setItemEnabled("New Body Parts", enable); menu->setItemEnabled("New Settings", enable); } } bool LLPanelMainInventory::hasSettingsInventory() { return LLEnvironment::instance().isInventoryEnabled(); } bool LLPanelMainInventory::hasMaterialsInventory() { std::string agent_url = gAgent.getRegionCapability("UpdateMaterialAgentInventory"); std::string task_url = gAgent.getRegionCapability("UpdateMaterialTaskInventory"); return (!agent_url.empty() && !task_url.empty()); } void LLPanelMainInventory::updateTitle() { LLFloater* inventory_floater = gFloaterView->getParentFloater(this); if(inventory_floater) { if(mSingleFolderMode) { inventory_floater->setTitle(getLocalizedRootName()); LLFloaterInventoryFinder *finder = getFinder(); if (finder) { finder->setTitle(getLocalizedRootName()); } } else { inventory_floater->setTitle(getString("inventory_title")); } } updateNavButtons(); } void LLPanelMainInventory::onCombinationRootChanged(bool gallery_clicked) { if(gallery_clicked) { mCombinationInventoryPanel->changeFolderRoot(mCombinationGalleryPanel->getRootFolder()); } else { mCombinationGalleryPanel->setRootFolder(mCombinationInventoryPanel->getSingleFolderRoot()); } mForceShowInvLayout = false; updateTitle(); mReshapeInvLayout = true; } void LLPanelMainInventory::onCombinationGallerySelectionChanged(const LLUUID& category_id) { } void LLPanelMainInventory::onCombinationInventorySelectionChanged(const std::deque& items, bool user_action) { onSelectionChange(mCombinationInventoryPanel, items, user_action); } void LLPanelMainInventory::updatePanelVisibility() { mDefaultViewPanel->setVisible(!mSingleFolderMode); mCombinationViewPanel->setVisible(mSingleFolderMode); mNavigationBtnsPanel->setVisible(mSingleFolderMode); mViewModeBtn->setImageOverlay(mSingleFolderMode ? getString("default_mode_btn") : getString("single_folder_mode_btn")); mViewModeBtn->setEnabled(mSingleFolderMode || (getAllItemsPanel() == getActivePanel())); if (mSingleFolderMode) { if (isCombinationViewMode()) { LLInventoryFilter& comb_inv_filter = mCombinationInventoryPanel->getFilter(); comb_inv_filter.setFilterThumbnails(LLInventoryFilter::FILTER_EXCLUDE_THUMBNAILS); comb_inv_filter.markDefault(); LLInventoryFilter& comb_gallery_filter = mCombinationGalleryPanel->getFilter(); comb_gallery_filter.setFilterThumbnails(LLInventoryFilter::FILTER_ONLY_THUMBNAILS); comb_gallery_filter.markDefault(); // visibility will be controled by updateCombinationVisibility() mCombinationGalleryLayoutPanel->setVisible(true); mCombinationGalleryPanel->setVisible(true); mCombinationListLayoutPanel->setVisible(true); } else { LLInventoryFilter& comb_inv_filter = mCombinationInventoryPanel->getFilter(); comb_inv_filter.setFilterThumbnails(LLInventoryFilter::FILTER_INCLUDE_THUMBNAILS); comb_inv_filter.markDefault(); LLInventoryFilter& comb_gallery_filter = mCombinationGalleryPanel->getFilter(); comb_gallery_filter.setFilterThumbnails(LLInventoryFilter::FILTER_INCLUDE_THUMBNAILS); comb_gallery_filter.markDefault(); mCombinationLayoutStack->setPanelSpacing(0); mCombinationGalleryLayoutPanel->setVisible(mSingleFolderMode && isGalleryViewMode()); mCombinationGalleryPanel->setVisible(mSingleFolderMode && isGalleryViewMode()); // to prevent or process updates mCombinationListLayoutPanel->setVisible(mSingleFolderMode && isListViewMode()); } } else { mCombinationGalleryLayoutPanel->setVisible(false); mCombinationGalleryPanel->setVisible(false); // to prevent updates mCombinationListLayoutPanel->setVisible(false); } } void LLPanelMainInventory::updateCombinationVisibility() { if(mSingleFolderMode && isCombinationViewMode()) { bool is_gallery_empty = !mCombinationGalleryPanel->hasVisibleItems(); bool show_inv_pane = mCombinationInventoryPanel->hasVisibleItems() || is_gallery_empty || mForceShowInvLayout; const S32 DRAG_HANDLE_PADDING = 12; // for drag handle to not overlap gallery when both inventories are visible mCombinationLayoutStack->setPanelSpacing(show_inv_pane ? DRAG_HANDLE_PADDING : 0); mCombinationGalleryLayoutPanel->setVisible(!is_gallery_empty); mCombinationListLayoutPanel->setVisible(show_inv_pane); mCombinationInventoryPanel->getRootFolder()->setForceArrange(!show_inv_pane); if(mCombinationInventoryPanel->hasVisibleItems()) { mForceShowInvLayout = false; } if(is_gallery_empty) { mCombinationGalleryPanel->handleModifiedFilter(); } getActivePanel()->getRootFolder(); if (mReshapeInvLayout && show_inv_pane && (mCombinationGalleryPanel->hasVisibleItems() || mCombinationGalleryPanel->areViewsInitialized()) && mCombinationInventoryPanel->areViewsInitialized()) { mReshapeInvLayout = false; // force drop previous shape (because panel doesn't decrease shape properly) LLRect list_latout = mCombinationListLayoutPanel->getRect(); list_latout.mTop = list_latout.mBottom; // min height is at 100, so it should snap to be bigger mCombinationListLayoutPanel->setShape(list_latout, false); LLRect inv_inner_rect = mCombinationInventoryPanel->getScrollableContainer()->getScrolledViewRect(); S32 inv_height = inv_inner_rect.getHeight() + (mCombinationInventoryPanel->getScrollableContainer()->getBorderWidth() * 2) + mCombinationInventoryPanel->getScrollableContainer()->getSize(); LLRect inner_galery_rect = mCombinationGalleryPanel->getScrollableContainer()->getScrolledViewRect(); S32 gallery_height = inner_galery_rect.getHeight() + (mCombinationGalleryPanel->getScrollableContainer()->getBorderWidth() * 2) + mCombinationGalleryPanel->getScrollableContainer()->getSize(); LLRect layout_rect = mCombinationViewPanel->getRect(); // by default make it take 1/3 of the panel S32 list_default_height = layout_rect.getHeight() / 3; // Don't set height from gallery_default_height - needs to account for a resizer in such case S32 gallery_default_height = layout_rect.getHeight() - list_default_height; if (inv_height > list_default_height && gallery_height < gallery_default_height) { LLRect gallery_latout = mCombinationGalleryLayoutPanel->getRect(); gallery_latout.mTop = gallery_latout.mBottom + gallery_height; mCombinationGalleryLayoutPanel->setShape(gallery_latout, true /*tell stack to account for new shape*/); } else if (inv_height < list_default_height && gallery_height > gallery_default_height) { LLRect list_latout = mCombinationListLayoutPanel->getRect(); list_latout.mTop = list_latout.mBottom + inv_height; mCombinationListLayoutPanel->setShape(list_latout, true /*tell stack to account for new shape*/); } else { LLRect list_latout = mCombinationListLayoutPanel->getRect(); list_latout.mTop = list_latout.mBottom + list_default_height; mCombinationListLayoutPanel->setShape(list_latout, true /*tell stack to account for new shape*/); } } } if (mSingleFolderMode && !isGalleryViewMode() && mCombInvUUIDNeedsRename.notNull() && mCombinationInventoryPanel->areViewsInitialized()) { mCombinationInventoryPanel->setSelectionByID(mCombInvUUIDNeedsRename, true); mCombinationInventoryPanel->getRootFolder()->scrollToShowSelection(); mCombinationInventoryPanel->getRootFolder()->setNeedsAutoRename(true); mCombInvUUIDNeedsRename.setNull(); } } void LLPanelMainInventory::updateNavButtons() { if(isListViewMode()) { mBackBtn->setEnabled(mCombinationInventoryPanel->isBackwardAvailable()); mForwardBtn->setEnabled(mCombinationInventoryPanel->isForwardAvailable()); } if(isGalleryViewMode()) { mBackBtn->setEnabled(mCombinationGalleryPanel->isBackwardAvailable()); mForwardBtn->setEnabled(mCombinationGalleryPanel->isForwardAvailable()); } if(isCombinationViewMode()) { mBackBtn->setEnabled(mCombinationInventoryPanel->isBackwardAvailable()); mForwardBtn->setEnabled(mCombinationInventoryPanel->isForwardAvailable()); } const LLViewerInventoryCategory* cat = gInventory.getCategory(getCurrentSFVRoot()); bool up_enabled = (cat && cat->getParentUUID().notNull()); mUpBtn->setEnabled(up_enabled); } LLSidepanelInventory* LLPanelMainInventory::getParentSidepanelInventory() { LLFloaterSidePanelContainer* inventory_container = dynamic_cast(gFloaterView->getParentFloater(this)); if(inventory_container) { return dynamic_cast(inventory_container->findChild("main_panel", true)); } return NULL; } void LLPanelMainInventory::setViewMode(EViewModeType mode) { if(mode != mViewMode) { std::list forward_history; std::list backward_history; U32 sort_order = 0; switch(mViewMode) { case MODE_LIST: forward_history = mCombinationInventoryPanel->getNavForwardList(); backward_history = mCombinationInventoryPanel->getNavBackwardList(); sort_order = mCombinationInventoryPanel->getSortOrder(); break; case MODE_GALLERY: forward_history = mCombinationGalleryPanel->getNavForwardList(); backward_history = mCombinationGalleryPanel->getNavBackwardList(); sort_order = mCombinationGalleryPanel->getSortOrder(); break; case MODE_COMBINATION: forward_history = mCombinationInventoryPanel->getNavForwardList(); backward_history = mCombinationInventoryPanel->getNavBackwardList(); mCombinationInventoryPanel->getRootFolder()->setForceArrange(false); sort_order = mCombinationInventoryPanel->getSortOrder(); break; } LLUUID cur_root = getCurrentSFVRoot(); mViewMode = mode; updatePanelVisibility(); if(isListViewMode()) { mCombinationInventoryPanel->changeFolderRoot(cur_root); mCombinationInventoryPanel->setNavForwardList(forward_history); mCombinationInventoryPanel->setNavBackwardList(backward_history); mCombinationInventoryPanel->setSortOrder(sort_order); } if(isGalleryViewMode()) { mCombinationGalleryPanel->setRootFolder(cur_root); mCombinationGalleryPanel->setNavForwardList(forward_history); mCombinationGalleryPanel->setNavBackwardList(backward_history); mCombinationGalleryPanel->setSortOrder(sort_order, true); } if(isCombinationViewMode()) { mCombinationInventoryPanel->changeFolderRoot(cur_root); mCombinationGalleryPanel->setRootFolder(cur_root); mCombinationInventoryPanel->setNavForwardList(forward_history); mCombinationInventoryPanel->setNavBackwardList(backward_history); mCombinationGalleryPanel->setNavForwardList(forward_history); mCombinationGalleryPanel->setNavBackwardList(backward_history); mCombinationInventoryPanel->setSortOrder(sort_order); mCombinationGalleryPanel->setSortOrder(sort_order, true); } updateNavButtons(); onFilterSelected(); if((isListViewMode() && (mActivePanel->getFilterSubString() != mFilterSubString)) || (isGalleryViewMode() && (mCombinationGalleryPanel->getFilterSubString() != mFilterSubString))) { onFilterEdit(mFilterSubString); } } } std::string LLPanelMainInventory::getLocalizedRootName() { return mSingleFolderMode ? get_localized_folder_name(getCurrentSFVRoot()) : ""; } LLUUID LLPanelMainInventory::getCurrentSFVRoot() { if(isListViewMode()) { return mCombinationInventoryPanel->getSingleFolderRoot(); } if(isGalleryViewMode()) { return mCombinationGalleryPanel->getRootFolder(); } if(isCombinationViewMode()) { return mCombinationInventoryPanel->getSingleFolderRoot(); } return LLUUID::null; } LLInventoryFilter& LLPanelMainInventory::getCurrentFilter() { if(mSingleFolderMode && isGalleryViewMode()) { return mCombinationGalleryPanel->getFilter(); } else { return mActivePanel->getFilter(); } } void LLPanelMainInventory::setGallerySelection(const LLUUID& item_id, bool new_window) { if(mSingleFolderMode && isGalleryViewMode()) { mCombinationGalleryPanel->changeItemSelection(item_id, true); } else if(mSingleFolderMode && isCombinationViewMode()) { if(mCombinationGalleryPanel->getFilter().checkAgainstFilterThumbnails(item_id)) { mCombinationGalleryPanel->changeItemSelection(item_id, false); scrollToGallerySelection(); } else { mCombinationInventoryPanel->setSelection(item_id, true); scrollToInvPanelSelection(); } } else if (mSingleFolderMode && isListViewMode()) { mCombinationInventoryPanel->setSelection(item_id, true); } } void LLPanelMainInventory::scrollToGallerySelection() { mCombinationGalleryPanel->scrollToShowItem(mCombinationGalleryPanel->getFirstSelectedItemID()); } void LLPanelMainInventory::scrollToInvPanelSelection() { mCombinationInventoryPanel->getRootFolder()->scrollToShowSelection(); } // List Commands // ////////////////////////////////////////////////////////////////////////////////