diff options
52 files changed, 2935 insertions, 3416 deletions
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index fbf23bc3f0..6e54f9d78a 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -275,6 +275,18 @@ void LLInventoryObject::correctInventoryName(std::string& name)  	LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN);  } +time_t LLInventoryObject::getCreationDate() const +{ +	return mCreationDate; +} + +void LLInventoryObject::setCreationDate(time_t creation_date_utc) +{ +	mCreationDate = creation_date_utc; +} + + +  ///----------------------------------------------------------------------------  /// Class LLInventoryItem @@ -297,9 +309,10 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid,  	mDescription(desc),  	mSaleInfo(sale_info),  	mInventoryType(inv_type), -	mFlags(flags), -	mCreationDate(creation_date_utc) +	mFlags(flags)  { +	mCreationDate = creation_date_utc; +  	LLStringUtil::replaceNonstandardASCII(mDescription, ' ');  	LLStringUtil::replaceChar(mDescription, '|', ' ');  	mPermissions.initMasks(inv_type); @@ -312,9 +325,9 @@ LLInventoryItem::LLInventoryItem() :  	mDescription(),  	mSaleInfo(),  	mInventoryType(LLInventoryType::IT_NONE), -	mFlags(0), -	mCreationDate(0) +	mFlags(0)  { +	mCreationDate = 0;  }  LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) : @@ -379,11 +392,6 @@ const std::string& LLInventoryItem::getDescription() const  	return mDescription;  } -time_t LLInventoryItem::getCreationDate() const -{ -	return mCreationDate; -} -  U32 LLInventoryItem::getCRC32() const  {  	// *FIX: Not a real crc - more of a checksum. @@ -440,11 +448,6 @@ void LLInventoryItem::setFlags(U32 flags)  	mFlags = flags;  } -void LLInventoryItem::setCreationDate(time_t creation_date_utc) -{ -	mCreationDate = creation_date_utc; -} -  // Currently only used in the Viewer to handle calling cards  // where the creator is actually used to store the target.  void LLInventoryItem::setCreator(const LLUUID& creator) @@ -506,6 +509,12 @@ U32 LLInventoryItem::getFlags() const  	return mFlags;  } +time_t LLInventoryItem::getCreationDate() const +{ +	return mCreationDate; +} + +  // virtual  void LLInventoryItem::packMessage(LLMessageSystem* msg) const  { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index a5cfe59bda..dc9a09e9d6 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -75,6 +75,7 @@ public:  	virtual LLAssetType::EType getType() const;  	LLAssetType::EType getActualType() const; // bypasses indirection for linked items  	BOOL getIsLinkType() const; +	virtual time_t getCreationDate() const;  	//--------------------------------------------------------------------  	// Mutators @@ -85,6 +86,7 @@ public:  	virtual void rename(const std::string& new_name);  	void setParent(const LLUUID& new_parent);  	void setType(LLAssetType::EType type); +	virtual void setCreationDate(time_t creation_date_utc); // only stored for items  private:  	// in place correction for inventory name string @@ -113,6 +115,7 @@ protected:  	LLUUID mParentUUID; // Parent category.  Root categories have LLUUID::NULL.  	LLAssetType::EType mType;  	std::string mName; +	time_t mCreationDate; // seconds from 1/1/1970, UTC  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,7 +181,6 @@ public:  	void setPermissions(const LLPermissions& perm);  	void setInventoryType(LLInventoryType::EType inv_type);  	void setFlags(U32 flags); -	void setCreationDate(time_t creation_date_utc);  	void setCreator(const LLUUID& creator); // only used for calling cards  	// Check for changes in permissions masks and sale info @@ -224,7 +226,6 @@ protected:  	LLSaleInfo mSaleInfo;  	LLInventoryType::EType mInventoryType;  	U32 mFlags; -	time_t mCreationDate; // seconds from 1/1/1970, UTC  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 487a2e5fe7..48128e0b40 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1542,34 +1542,32 @@ void LLNotifications::addFromCallback(const LLSD& name)  	add(name.asString(), LLSD(), LLSD());  } -LLNotificationPtr LLNotifications::add(const std::string& name,  -									   const LLSD& substitutions,  -									   const LLSD& payload) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload)  {  	LLNotification::Params::Functor functor_p;  	functor_p.name = name;  	return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));	  } -LLNotificationPtr LLNotifications::add(const std::string& name,  -									   const LLSD& substitutions,  -									   const LLSD& payload,  -									   const std::string& functor_name) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, const std::string& functor_name)  {  	LLNotification::Params::Functor functor_p;  	functor_p.name = functor_name; -	return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));	 +	return add(LLNotification::Params().name(name) +										.substitutions(substitutions) +										.payload(payload) +										.functor(functor_p));	  }  //virtual -LLNotificationPtr LLNotifications::add(const std::string& name,  -										const LLSD& substitutions,  -										const LLSD& payload,  -										LLNotificationFunctorRegistry::ResponseFunctor functor) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor)  {  	LLNotification::Params::Functor functor_p;  	functor_p.function = functor; -	return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));	 +	return add(LLNotification::Params().name(name) +										.substitutions(substitutions) +										.payload(payload) +										.functor(functor_p));	  }  // generalized add function that takes a parameter block object for more complex instantiations diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 25e7a31e90..f64f33bc5e 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -278,13 +278,13 @@ const LLInitParam::BaseBlock& get_empty_param_block()  // adds a widget and its param block to various registries  //static  -void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag) +void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name)  {  	// associate parameter block type with template .xml file -	std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type); -	if (existing_tag != NULL) +	std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type); +	if (existing_name != NULL)  	{ -		if(*existing_tag != tag) +		if(*existing_name != name)  		{  			std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl;  			// forcing crash here @@ -293,18 +293,19 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st  		}  		else  		{ -			// widget already registered +			// widget already registered this name  			return;  		}  	} -	LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag); + +	LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, name);  	//FIXME: comment this in when working on schema generation  	//LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);  	//LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>);  }  //static  -const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type) +const std::string* LLUICtrlFactory::getWidgetName(const std::type_info* widget_type)  {  	return LLWidgetNameRegistry::instance().getValue(widget_type);  } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index d612ad5005..b441cb0c9d 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -105,7 +105,7 @@ private:  		ParamDefaults()  		{  			// look up template file for this param block... -			const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK)); +			const std::string* param_block_tag = getWidgetName(&typeid(PARAM_BLOCK));  			if (param_block_tag)  			{	// ...and if it exists, back fill values using the most specific template first  				PARAM_BLOCK params; @@ -303,7 +303,7 @@ private:  	} -	static const std::string* getWidgetTag(const std::type_info* widget_type); +	static const std::string* getWidgetName(const std::type_info* widget_type);  	// this exists to get around dependency on llview  	static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index ce59401e87..d44ccac6e4 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -212,7 +212,7 @@ namespace LLInitParam  		{}  		ParamValue(const default_value_t& other) -			:	T(other), +		:	T(other),  			mValidated(false)  		{} @@ -632,38 +632,38 @@ namespace LLInitParam  		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed  	}; -		//TODO: implement in terms of owned_ptr -		template<typename T> +	//TODO: implement in terms of owned_ptr +	template<typename T>  	class LazyValue -		{ +	{  		public:  		LazyValue() -				: mPtr(NULL) -			{} +		: mPtr(NULL) +		{}  		~LazyValue() -			{ -				delete mPtr; -			} +		{ +			delete mPtr; +		}  		LazyValue(const T& value) -			{ +		{  			mPtr = new T(value);  		}  		LazyValue(const LazyValue& other)  		:	mPtr(NULL) -				{ +		{  			*this = other; -				} +		}  		LazyValue& operator = (const LazyValue& other)  		{  			if (!other.mPtr) -				{ +			{  				delete mPtr; -					mPtr = NULL; -				} +				mPtr = NULL; +			}  			else  			{  				if (!mPtr) @@ -674,9 +674,9 @@ namespace LLInitParam  				{  					*mPtr = *(other.mPtr);  				} -				} -				return *this;  			} +			return *this; +		}  		bool operator==(const LazyValue& other) const  		{ @@ -684,13 +684,13 @@ namespace LLInitParam  			return *mPtr == *other.mPtr;  		} -			bool empty() const -			{ -				return mPtr == NULL; -			} +		bool empty() const +		{ +			return mPtr == NULL; +		} -			void set(const T& other) -			{ +		void set(const T& other) +		{  			if (!mPtr)  			{  				mPtr = new T(other); @@ -701,36 +701,36 @@ namespace LLInitParam  			}  		} -			const T& get() const -			{ +		const T& get() const +		{  			return *ensureInstance(); -			} +		} -			T& get() -			{ +		T& get() +		{  			return *ensureInstance();  		}  		operator const T&() const  		{   			return get();  -			} +		} -		private: -			// lazily allocate an instance of T -			T* ensureInstance() const +	private: +		// lazily allocate an instance of T +		T* ensureInstance() const +		{ +			if (mPtr == NULL)  			{ -				if (mPtr == NULL) -				{ -					mPtr = new T(); -				} -				return mPtr; -			} +				mPtr = new T();			 +                        } +			return mPtr; +		} -		private: +	private: -			mutable T* mPtr; -		}; +		mutable T* mPtr; +	};  	// root class of all parameter blocks @@ -2492,10 +2492,10 @@ namespace LLInitParam  		} EValueAge;  		typedef ParamValue<T>			derived_t; -		typedef CustomParamValue<T>				self_t; -		typedef Block<derived_t>				block_t; +		typedef CustomParamValue<T>		self_t; +		typedef Block<derived_t>		block_t;  		typedef T						default_value_t; -		typedef T								value_t; +		typedef T						value_t;  		typedef void					baseblock_base_class_t; diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h index 36ce6a97b7..3e8d9267cc 100644 --- a/indra/llxuixml/llregistry.h +++ b/indra/llxuixml/llregistry.h @@ -302,6 +302,10 @@ public:  		virtual ~StaticRegistrar() {}  		StaticRegistrar(ref_const_key_t key, ref_const_value_t value)  		{ +			if (singleton_t::instance().exists(key)) +			{ +				llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl; +			}  			singleton_t::instance().mStaticScope->add(key, value);  		}  	}; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e67089c4de..64bc70da58 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -255,6 +255,8 @@ set(viewer_SOURCE_FILES      llfloaterworldmap.cpp      llfolderview.cpp      llfolderviewitem.cpp +    llfolderviewmodel.cpp +    llfolderviewmodelinventory.cpp      llfollowcam.cpp      llfriendcard.cpp      llgesturelistener.cpp @@ -812,7 +814,8 @@ set(viewer_HEADER_FILES      llfloaterwindowsize.h      llfloaterworldmap.h      llfolderview.h -    llfoldervieweventlistener.h +    llfolderviewmodel.h +    llfolderviewmodelinventory.h      llfolderviewitem.h      llfollowcam.h      llfriendcard.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 21367c224d..fb32bcbd60 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -710,23 +710,30 @@ void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avata  //static  std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()  { -	std::set<LLUUID> inventory_selected_uuids; +	std::set<LLFolderViewItem*> inventory_selected;  	LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();  	if (active_panel)  	{ -		inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList(); +		inventory_selected= active_panel->getRootFolder()->getSelectionList();  	} -	if (inventory_selected_uuids.empty()) +	if (inventory_selected.empty())  	{  		LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");  		if (sidepanel_inventory)  		{ -			inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); +			inventory_selected= sidepanel_inventory->getInboxSelectionList();  		}  	} +	std::set<LLUUID> inventory_selected_uuids; +	for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); +		it != end_it; +		++it) +	{ +		inventory_selected_uuids.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +	}  	return inventory_selected_uuids;  } @@ -762,15 +769,15 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  	// check selection in the panel  	LLFolderView* root_folder = inv_panel->getRootFolder(); -	const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList(); -	if (inventory_selected_uuids.empty()) return false; // nothing selected +	const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); +	if (inventory_selected.empty()) return false; // nothing selected  	bool can_share = true; -	std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); -	const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); +	std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(); +	const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end();  	for (; it != it_end; ++it)  	{ -		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); +		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());  		// any category can be offered.  		if (inv_cat)  		{ @@ -778,9 +785,9 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  		}  		// check if inventory item can be given -		LLFolderViewItem* item = root_folder->getItemByID(*it); +		LLFolderViewItem* item = *it;  		if (!item) return false; -		LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener()); +		LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem());  		if (bridge && bridge->canShare())  		{  			continue; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 575b613ccf..4a96de942d 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -38,6 +38,7 @@  #include "lltooltip.h"  #include "llagent.h" +#include "llavatarnamecache.h"  #include "llclipboard.h"  #include "llclipboard.h"  #include "llinventorybridge.h" @@ -45,12 +46,14 @@  #include "llfloatersidepanelcontainer.h"  #include "llfloaterworldmap.h"  #include "lllandmarkactions.h" +#include "lllogininstance.h"  #include "llnotificationsutil.h"  #include "lltoggleablemenu.h"  #include "llviewerinventory.h"  #include "llviewermenu.h"  #include "llviewermenu.h"  #include "lltooldraganddrop.h" +#include "llsdserialize.h"  static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); @@ -317,7 +320,8 @@ public:  		if (item)  		{ -			item->setSortField(mSortField); +			LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); +  			item->setComplete(TRUE);  			item->updateServer(FALSE); @@ -339,8 +343,8 @@ struct LLFavoritesSort  	// TODO - made it customizible using gSavedSettings  	bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b)  	{ -		S32 sortField1 = a->getSortField(); -		S32 sortField2 = b->getSortField(); +		S32 sortField1 = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); +		S32 sortField2 = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID());  		if (!(sortField1 < 0 && sortField2 < 0))  		{ @@ -528,7 +532,7 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)  		mItems.push_back(gInventory.getItem(mDragItemId));  	} -	gInventory.saveItemsOrder(mItems); +	LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);  	LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get(); @@ -587,7 +591,8 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con  		}  		else  		{ -			currItem->setSortField(++sortField); +			LLFavoritesOrderStorage::instance().setSortIndex(currItem, ++sortField); +  			currItem->setComplete(TRUE);  			currItem->updateServer(FALSE); @@ -640,7 +645,7 @@ void LLFavoritesBarCtrl::changed(U32 mask)  		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)  		{ -			(*i)->getSLURL(); +			LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());  		}  		updateButtons();  	} @@ -909,7 +914,7 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it  		S32 sortField = 0;  		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)  		{ -			(*i)->setSortField(++sortField); +			LLFavoritesOrderStorage::instance().setSortIndex((*i), ++sortField);  		}  	} @@ -1355,7 +1360,7 @@ BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array  	// if there is an item without sort order field set, we need to save items order  	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)  	{ -		if ((*i)->getSortField() < 0) +		if (LLFavoritesOrderStorage::instance().getSortIndex((*i)->getUUID()) < 0)  		{  			result = TRUE;  			break; @@ -1390,4 +1395,291 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const  	}  } +const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; +const S32 LLFavoritesOrderStorage::NO_INDEX = -1; + +void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index) +{ +	mSortIndexes[inv_item->getUUID()] = sort_index; +	mIsDirty = true; +	getSLURL(inv_item->getAssetUUID()); +} + +S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) +{ +	sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); +	if (it != mSortIndexes.end()) +	{ +		return it->second; +	} +	return NO_INDEX; +} + +void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) +{ +	mSortIndexes.erase(inv_item_id); +	mIsDirty = true; +} + +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ +	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); +	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + +	LLLandmark* lm = gLandmarkList.getAsset(asset_id, +		boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); +	if (lm) +	{ +		onLandmarkLoaded(asset_id, lm); +	} +} + +// static +void LLFavoritesOrderStorage::destroyClass() +{ +	LLFavoritesOrderStorage::instance().cleanup(); +	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) +	{ +		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); +	} +	else +	{ +		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); +	} +} + +void LLFavoritesOrderStorage::load() +{ +	// load per-resident sorting information +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); + +	LLSD settings_llsd; +	llifstream file; +	file.open(filename); +	if (file.is_open()) +	{ +		LLSDSerialize::fromXML(settings_llsd, file); +	} + +	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); +		iter != settings_llsd.endMap(); ++iter) +	{ +		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); +	} +} + +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ +	// Do not change the file if we are not logged in yet. +	if (!LLLoginInstance::getInstance()->authSuccess()) +	{ +		llwarns << "Cannot save favorites: not logged in" << llendl; +		return; +	} + +	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); +	if (user_dir.empty()) +	{ +		llwarns << "Cannot save favorites: empty user dir name" << llendl; +		return; +	} + +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	llifstream in_file; +	in_file.open(filename); +	LLSD fav_llsd; +	if (in_file.is_open()) +	{ +		LLSDSerialize::fromXML(fav_llsd, in_file); +	} + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	LLSD user_llsd; +	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) +	{ +		LLSD value; +		value["name"] = (*it)->getName(); +		value["asset_id"] = (*it)->getAssetUUID(); + +		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); +		if (slurl_iter != mSLURLs.end()) +		{ +			lldebugs << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl; +			value["slurl"] = slurl_iter->second; +			user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; +		} +		else +		{ +			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; +		} +	} + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; +	fav_llsd[av_name.getLegacyName()] = user_llsd; + +	llofstream file; +	file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, file); +} + +void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() +{ +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	LLSD fav_llsd; +	llifstream file; +	file.open(filename); +	if (!file.is_open()) return; +	LLSDSerialize::fromXML(fav_llsd, file); + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; +	if (fav_llsd.has(av_name.getLegacyName())) +	{ +		fav_llsd.erase(av_name.getLegacyName()); +	} + +	llofstream out_file; +	out_file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, out_file); + +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ +	if (!landmark) return; + +	LLVector3d pos_global; +	if (!landmark->getGlobalPos(pos_global)) +	{ +		// If global position was unknown on first getGlobalPos() call +		// it should be set for the subsequent calls. +		landmark->getGlobalPos(pos_global); +	} + +	if (!pos_global.isExactlyZero()) +	{ +		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, +			boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); +	} +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ +	lldebugs << "Saving landmark SLURL: " << slurl << llendl; +	mSLURLs[asset_id] = slurl; +} + +void LLFavoritesOrderStorage::save() +{ +	// nothing to save if clean +	if (!mIsDirty) return; + +	// If we quit from the login screen we will not have an SL account +	// name.  Don't try to save, otherwise we'll dump a file in +	// C:\Program Files\SecondLife\ or similar. JC +	std::string user_dir = gDirUtilp->getLindenUserDir(); +	if (!user_dir.empty()) +	{ +		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); +		LLSD settings_llsd; + +		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) +		{ +			settings_llsd[iter->first.asString()] = iter->second; +		} + +		llofstream file; +		file.open(filename); +		LLSDSerialize::toPrettyXML(settings_llsd, file); +	} +} + +void LLFavoritesOrderStorage::cleanup() +{ +	// nothing to clean +	if (!mIsDirty) return; + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	IsNotInFavorites is_not_in_fav(items); + +	sort_index_map_t  aTempMap; +	//copy unremoved values from mSortIndexes to aTempMap +	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  +		inserter(aTempMap, aTempMap.begin()), +		is_not_in_fav); + +	//Swap the contents of mSortIndexes and aTempMap +	mSortIndexes.swap(aTempMap); +} + +void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items ) +{ +	int sortField = 0; + +	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field +	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) +	{ +		LLViewerInventoryItem* item = *i; + +		setSortIndex(item, ++sortField); + +		item->setComplete(TRUE); +		item->updateServer(FALSE); + +		gInventory.updateItem(item); + +		// Tell the parent folder to refresh its sort order. +		gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); +	} + +	gInventory.notifyObservers(); +} + +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: +	bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) +	{ +		return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID())  +			< LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); +	} +}; + +// * @param source_item_id - LLUUID of the source item to be moved into new position +// * @param target_item_id - LLUUID of the target item before which source item should be placed. +void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLIsType is_type(LLAssetType::AT_LANDMARK); +	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + +	// ensure items are sorted properly before changing order. EXT-3498 +	std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); + +	// update order +	gInventory.updateItemsOrder(items, source_item_id, target_item_id); + +	saveItemsOrder(items); +} + +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ +	if (mTargetLandmarkId.isNull()) return; + +	LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +}  // EOF diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 2f75b3bb0e..60e02b661e 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -33,6 +33,7 @@  #include "llinventoryobserver.h"  #include "llinventorymodel.h" +#include "llviewerinventory.h"  class LLMenuItemCallGL;  class LLToggleableMenu; @@ -161,5 +162,115 @@ private:  	boost::signals2::connection mEndDragConnection;  }; +class AddFavoriteLandmarkCallback : public LLInventoryCallback +{ +public: +	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} +	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } + +private: +	void fire(const LLUUID& inv_item); + +	LLUUID mTargetLandmarkId; +}; + +/** + * Class to store sorting order of favorites landmarks in a local file. EXT-3985. + * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. + * Data are stored in user home directory. + */ +class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> +	, public LLDestroyClass<LLFavoritesOrderStorage> +{ +	LOG_CLASS(LLFavoritesOrderStorage); +public: +	/** +	 * Sets sort index for specified with LLUUID favorite landmark +	 */ +	void setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index); + +	/** +	 * Gets sort index for specified with LLUUID favorite landmark +	 */ +	S32 getSortIndex(const LLUUID& inv_item_id); +	void removeSortIndex(const LLUUID& inv_item_id); + +	void getSLURL(const LLUUID& asset_id); + +	// Saves current order of the passed items using inventory item sort field. +	// Resets 'items' sort fields and saves them on server. +	// Is used to save order for Favorites folder. +	void saveItemsOrder(const LLInventoryModel::item_array_t& items); + +	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + +	/** +	 * Implementation of LLDestroyClass. Calls cleanup() instance method. +	 * +	 * It is important this callback is called before gInventory is cleaned. +	 * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), +	 * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. +	 * @see cleanup() +	 */ +	static void destroyClass(); + +	const static S32 NO_INDEX; +private: +	friend class LLSingleton<LLFavoritesOrderStorage>; +	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } +	~LLFavoritesOrderStorage() { save(); } + +	/** +	 * Removes sort indexes for items which are not in Favorites bar for now. +	 */ +	void cleanup(); + +	const static std::string SORTING_DATA_FILE_NAME; + +	void load(); +	void save(); + +	void saveFavoritesSLURLs(); + +	// Remove record of current user's favorites from file on disk. +	void removeFavoritesRecordOfUser(); + +	void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark); +	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); + +	typedef std::map<LLUUID, S32> sort_index_map_t; +	sort_index_map_t mSortIndexes; + +	typedef std::map<LLUUID, std::string> slurls_map_t; +	slurls_map_t mSLURLs; + +	bool mIsDirty; + +	struct IsNotInFavorites +	{ +		IsNotInFavorites(const LLInventoryModel::item_array_t& items) +			: mFavoriteItems(items) +		{ + +		} + +		/** +		 * Returns true if specified item is not found among inventory items +		 */ +		bool operator()(const sort_index_map_t::value_type& id_index_pair) const +		{ +			LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); +			if (item.isNull()) return true; + +			LLInventoryModel::item_array_t::const_iterator found_it = +				std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); + +			return found_it == mFavoriteItems.end(); +		} +	private: +		LLInventoryModel::item_array_t mFavoriteItems; +	}; + +};  #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index c55970ad69..04a55b261c 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -250,7 +250,8 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)  	mOutboxInventoryPanel->setShape(inventory_placeholder_rect);  	// Set the sort order newest to oldest -	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME);	 + +	mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME);	  	mOutboxInventoryPanel->getFilter()->markDefault();  	fetchOutboxContents(); @@ -386,7 +387,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	// Determine if the mouse is inside the inventory panel itself or just within the floater  	bool pointInInventoryPanel = false;  	bool pointInInventoryPanelChild = false; -	LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); +	LLFolderView* root_folder = mOutboxInventoryPanel->getRootFolder();  	if (mOutboxInventoryPanel->getVisible())  	{  		S32 inv_x, inv_y; @@ -443,10 +444,10 @@ void LLFloaterOutbox::onOutboxChanged()  {  	llassert(!mOutboxId.isNull()); -	if (mOutboxInventoryPanel) -	{ -		mOutboxInventoryPanel->requestSort(); -	} +	//if (mOutboxInventoryPanel) +	//{ +	//	mOutboxInventoryPanel->requestSort(); +	//}  	fetchOutboxContents(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 57fc3f7efd..90c78d98b0 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -27,16 +27,13 @@  #include "llviewerprecompiledheaders.h"  #include "llfolderview.h" +#include "llfolderview.h"  #include "llcallbacklist.h"  #include "llinventorybridge.h"  #include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h"  #include "llinventorypanel.h"  #include "llfoldertype.h" -#include "llfloaterinventory.h"// hacked in for the bonus context menu items.  #include "llkeyboard.h"  #include "lllineeditor.h"  #include "llmenugl.h" @@ -64,7 +61,6 @@  #include "llfontgl.h"  #include "llgl.h"   #include "llrender.h" -#include "llinventory.h"  // Third-party library includes  #include <algorithm> @@ -94,42 +90,6 @@ enum {  F32 LLFolderView::sAutoOpenTime = 1.f; -void delete_selected_item(void* user_data); -void copy_selected_item(void* user_data); -void open_selected_items(void* user_data); -void properties_selected_items(void* user_data); -void paste_items(void* user_data); - - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to sort their items -// (and only their items, not folders) by a certain function. -class LLSetItemSortFunction : public LLFolderViewFunctor -{ -public: -	LLSetItemSortFunction(U32 ordering) -		: mSortOrder(ordering) {} -	virtual ~LLSetItemSortFunction() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); - -	U32 mSortOrder; -}; - - -// Set the sort order. -void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) -{ -	folder->setItemSortOrder(mSortOrder); -} - -// Do nothing. -void LLSetItemSortFunction::doItem(LLFolderViewItem* item) -{ -	return; -} -  //---------------------------------------------------------------------------  // Tells all folders in a folderview to close themselves @@ -154,7 +114,6 @@ public:  }; -// Set the sort order.  void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder)  {  	folder->setOpenArrangeRecursively(mOpen); @@ -177,7 +136,7 @@ const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const  		LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView);  		if (folder_view)  		{ -			S32 height = folder_view->mRunningHeight; +			S32 height = folder_view->getRect().getHeight();  			rect = mScrolledView->getRect();  			rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); @@ -200,7 +159,6 @@ LLFolderView::Params::Params()  	use_label_suffix("use_label_suffix"),  	allow_multiselect("allow_multiselect", true),  	show_empty_message("show_empty_message", true), -	show_load_status("show_load_status", true),  	use_ellipses("use_ellipses", false)  {  	folder_indentation = -4; @@ -210,7 +168,6 @@ LLFolderView::Params::Params()  // Default constructor  LLFolderView::LLFolderView(const Params& p)  :	LLFolderViewFolder(p), -	mRunningHeight(0),  	mScrollContainer( NULL ),  	mPopupMenuHandle(),  	mAllowMultiSelect(p.allow_multiselect), @@ -224,9 +181,7 @@ LLFolderView::LLFolderView(const Params& p)  	mNeedsAutoSelect( FALSE ),  	mAutoSelectOverride(FALSE),  	mNeedsAutoRename(FALSE), -	mDebugFilters(FALSE),  	mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME),	// This gets overridden by a pref immediately -	mFilter( new LLInventoryFilter(p.title) ),  	mShowSelectionContext(FALSE),  	mShowSingleSelection(FALSE),  	mArrangeGeneration(0), @@ -237,17 +192,17 @@ LLFolderView::LLFolderView(const Params& p)  	mParentPanel(p.parent_panel),  	mUseEllipses(p.use_ellipses),  	mDraggingOverItem(NULL), -	mStatusTextBox(NULL) +	mStatusTextBox(NULL), +	mShowItemLinkOverlays(p.show_item_link_overlays), +	mViewModel(p.view_model)  { +	mViewModel->setFolderView(this);  	mRoot = this; -	mShowLoadStatus = p.show_load_status(); -  	LLRect rect = p.rect;  	LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);  	setRect( rect );  	reshape(rect.getWidth(), rect.getHeight()); -	mIsOpen = TRUE; // this view is always open.  	mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH);  	mAutoOpenCandidate = NULL;  	mAutoOpenTimer.stop(); @@ -304,7 +259,7 @@ LLFolderView::LLFolderView(const Params& p)  	menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));  	mPopupMenuHandle = menu->getHandle(); -	mListener->openItem(); +	mViewModelItem->openItem();  }  // Destroys the object @@ -332,10 +287,8 @@ LLFolderView::~LLFolderView( void )  	mItems.clear();  	mFolders.clear(); -	mItemMap.clear(); - -	delete mFilter; -	mFilter = NULL; +	delete mViewModel; +	mViewModel = NULL;  }  BOOL LLFolderView::canFocusChildren() const @@ -343,31 +296,13 @@ BOOL LLFolderView::canFocusChildren() const  	return FALSE;  } -static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); - -void LLFolderView::setSortOrder(U32 order) -{ -	if (order != mSortOrder) -	{ -		LLFastTimer t(FTM_SORT); -		 -		mSortOrder = order; - -		sortBy(order); -		arrangeAll(); -	} -} - - -U32 LLFolderView::getSortOrder() const -{ -	return mSortOrder; -} -  BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)  { +	LLFolderViewFolder::addFolder(folder); + +	mFolders.remove(folder);  	// enforce sort order of My Inventory followed by Library -	if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID()) +	if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID())  	{  		mFolders.push_back(folder);  	} @@ -375,13 +310,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)  	{  		mFolders.insert(mFolders.begin(), folder);  	} -	folder->setShowLoadStatus(mShowLoadStatus); -	folder->setOrigin(0, 0); -	folder->reshape(getRect().getWidth(), 0); -	folder->setVisible(FALSE); -	addChild( folder ); -	folder->dirtyFilter(); -	folder->requestArrange(); +  	return TRUE;  } @@ -402,145 +331,39 @@ void LLFolderView::openTopLevelFolders()  	}  } -void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ -	// call base class to do proper recursion -	LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); -	// make sure root folder is always open -	mIsOpen = TRUE; -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -  // This view grows and shrinks to enclose all of its children items and folders. -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) +// *width should be 0 +// conform show folder state works +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height )  { -	if (getListener()->getUUID().notNull()) -	{ -		if (mNeedsSort) -		{ -			mFolders.sort(mSortFunction); -			mItems.sort(mSortFunction); -			mNeedsSort = false; -		} -	} - -	LLFastTimer t2(FTM_ARRANGE); - -	filter_generation = mFilter->getMinRequiredGeneration();  	mMinWidth = 0; +	S32 target_height; -	mHasVisibleChildren = hasFilteredDescendants(filter_generation); -	// arrange always finishes, so optimistically set the arrange generation to the most current -	mLastArrangeGeneration = getRoot()->getArrangeGeneration(); +	LLFolderViewFolder::arrange(&mMinWidth, &target_height); -	LLInventoryFilter::EFolderShow show_folder_state = -		getRoot()->getFilter()->getShowFolderState(); - -	S32 total_width = LEFT_PAD; -	S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; -	S32 target_height = running_height; -	S32 parent_item_height = getRect().getHeight(); - -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		LLFolderViewFolder* folderp = (*fit); -		if (getDebugFilters()) -		{ -			folderp->setVisible(TRUE); -		} -		else -		{ -			folderp->setVisible((show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? -								 (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)))); -		} - -		if (folderp->getVisible()) -		{ -			S32 child_height = 0; -			S32 child_width = 0; -			S32 child_top = parent_item_height - running_height; -			 -			target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - -			mMinWidth = llmax(mMinWidth, child_width); -			total_width = llmax( total_width, child_width ); -			running_height += child_height; -			folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); -		} -	} - -	for (items_t::iterator iter = mItems.begin(); -		 iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		LLFolderViewItem* itemp = (*iit); -		itemp->setVisible(itemp->getFiltered(filter_generation)); - -		if (itemp->getVisible()) -		{ -			S32 child_width = 0; -			S32 child_height = 0; -			S32 child_top = parent_item_height - running_height; -			 -			target_height += itemp->arrange( &child_width, &child_height, filter_generation ); -			itemp->reshape(itemp->getRect().getWidth(), child_height); - -			mMinWidth = llmax(mMinWidth, child_width); -			total_width = llmax( total_width, child_width ); -			running_height += child_height; -			itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); -		} -	} - -	if(!mHasVisibleChildren)// is there any filtered items ? -	{ -		//Nope. We need to display status textbox, let's reserve some place for it -		running_height = mStatusTextBox->getTextPixelHeight(); -		target_height = running_height; -	} - -	mRunningHeight = running_height;  	LLRect scroll_rect = mScrollContainer->getContentWindowRect(); -	reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); +	reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) );  	LLRect new_scroll_rect = mScrollContainer->getContentWindowRect();  	if (new_scroll_rect.getWidth() != scroll_rect.getWidth())  	{ -		reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); +		reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) );  	}  	// move item renamer text field to item's new position  	updateRenamerPosition(); -	mTargetHeight = (F32)target_height;  	return llround(mTargetHeight);  } -const std::string LLFolderView::getFilterSubString(BOOL trim) -{ -	return mFilter->getFilterSubString(trim); -} - -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); -void LLFolderView::filter( LLInventoryFilter& filter ) +void LLFolderView::filter( LLFolderViewFilter& filter )  {  	LLFastTimer t2(FTM_FILTER);  	filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); -	if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) -	{ -		mPassedFilter = FALSE; -		mMinWidth = 0; -		LLFolderViewFolder::filter(filter); -	} -	else -	{ -		mPassedFilter = TRUE; -	} +	getViewModelItem()->filter(filter);  }  void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -552,7 +375,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)  		scroll_rect = mScrollContainer->getContentWindowRect();  	}  	width = llmax(mMinWidth, scroll_rect.getWidth()); -	height = llmax(mRunningHeight, scroll_rect.getHeight()); +	height = llmax(llround(mCurHeight), scroll_rect.getHeight());  	// Restrict width within scroll container's width  	if (mUseEllipses && mScrollContainer) @@ -651,30 +474,6 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,  	return rv;  } -void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ -	LLFolderViewItem* itemp = getItemByID(obj_id); -	if(itemp && itemp->getListener()) -	{ -		itemp->arrangeAndSet(TRUE, take_keyboard_focus); -		mSelectThisID.setNull(); -		return; -	} -	else -	{ -		// save the desired item to be selected later (if/when ready) -		mSelectThisID = obj_id; -	} -} - -void LLFolderView::updateSelection() -{ -	if (mSelectThisID.notNull()) -	{ -		setSelectionByID(mSelectThisID, false); -	} -} -  BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected)  {  	BOOL rv = FALSE; @@ -725,9 +524,6 @@ void LLFolderView::sanitizeSelection()  	// and we want to preserve context  	LLFolderViewItem* original_selected_item = getCurSelectedItem(); -	// Cache "Show all folders" filter setting -	BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); -  	std::vector<LLFolderViewItem*> items_to_remove;  	selected_items_t::iterator item_iter;  	for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) @@ -735,23 +531,14 @@ void LLFolderView::sanitizeSelection()  		LLFolderViewItem* item = *item_iter;  		// ensure that each ancestor is open and potentially passes filtering -		BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item +		BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item  		// modify with parent open and filters states  		LLFolderViewFolder* parent_folder = item->getParentFolder(); -		if ( parent_folder ) +		// Move up through parent folders and see what's visible +		while(parent_folder)  		{ -			if ( show_all_folders ) -			{	// "Show all folders" is on, so this folder is visible -				visible = TRUE; -			} -			else -			{	// Move up through parent folders and see what's visible -				while(parent_folder) -				{ -					visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); -					parent_folder = parent_folder->getParentFolder(); -				} -			} +			visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); +			parent_folder = parent_folder->getParentFolder();  		}  		//  deselect item if any ancestor is closed or didn't pass filter requirements. @@ -802,7 +589,7 @@ void LLFolderView::sanitizeSelection()  				parent_folder;  				parent_folder = parent_folder->getParentFolder())  			{ -				if (parent_folder->potentiallyVisible()) +				if (parent_folder->getViewModelItem()->potentiallyVisible())  				{  					// give initial selection to first ancestor folder that potentially passes the filter  					if (!new_selection) @@ -841,18 +628,12 @@ void LLFolderView::clearSelection()  	}  	mSelectedItems.clear(); -	mSelectThisID.setNull();  } -std::set<LLUUID> LLFolderView::getSelectionList() const -{ -	std::set<LLUUID> selection; -	for (selected_items_t::const_iterator item_it = mSelectedItems.begin();  -		 item_it != mSelectedItems.end();  -		 ++item_it) +std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const  	{ -		selection.insert((*item_it)->getListener()->getUUID()); -	} +	std::set<LLFolderViewItem*> selection; +	std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin()));  	return selection;  } @@ -868,7 +649,7 @@ BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source)  		{  			EDragAndDropType type = DAD_NONE;  			LLUUID id = LLUUID::null; -			can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); +			can_drag = can_drag && (*item_it)->getViewModelItem()->startDrag(&type, &id);  			types.push_back(type);  			cargo_ids.push_back(id); @@ -886,16 +667,6 @@ void LLFolderView::commitRename( const LLSD& data )  void LLFolderView::draw()  { -	static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white); -	if (mDebugFilters) -	{ -		std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", -										mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); -		LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2,  -			getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f),  -			LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); -	} -  	//LLFontGL* font = getLabelFontForStyle(mLabelStyle);  	// if cursor has moved off of me during drag and drop @@ -929,28 +700,13 @@ void LLFolderView::draw()  		mSearchString.clear();  	} -	if (hasVisibleChildren() -		|| mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) +	if (hasVisibleChildren())  	{ -		mStatusText.clear();  		mStatusTextBox->setVisible( FALSE );  	}  	else if (mShowEmptyMessage)  	{ -		if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) -		{ -			mStatusText = LLTrans::getString("Searching"); -		} -		else -		{ -			if (getFilter()) -			{ -				LLStringUtil::format_map_t args; -				args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); -				mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args); -			} -		} -		mStatusTextBox->setValue(mStatusText); +		mStatusTextBox->setValue(getFolderViewModel()->getStatusText());  		mStatusTextBox->setVisible( TRUE );  		// firstly reshape message textbox with current size. This is necessary to @@ -967,7 +723,11 @@ void LLFolderView::draw()  			// This will indirectly call ::arrange and reshape of the status textbox.  			// We should call this method to also notify parent about required rect.  			// See EXT-7564, EXT-7047. -			arrangeFromRoot(); +			S32 height = 0; +			S32 width = 0; +			S32 total_height = arrange( &width, &height ); +			notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); +  			LLUI::popMatrix();  			LLUI::pushMatrix();  			LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); @@ -994,7 +754,7 @@ void LLFolderView::finishRenamingItem( void )  	closeRenamer(); -	// List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. +	// List is re-sorted alphabetically, so scroll to make sure the selected item is visible.  	scrollToShowSelection();  } @@ -1106,16 +866,16 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL  			}  			if(parent)  			{ -				if (parent->removeItem(item_to_delete)) +				if (item_to_delete->remove())  				{  					// change selection on successful delete  					if (new_selection)  					{ -						setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); +						getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus());  					}  					else  					{ -						setSelectionFromRoot(NULL, mParentPanel->hasFocus()); +						getRoot()->setSelection(NULL, mParentPanel->hasFocus());  					}  				}  			} @@ -1123,8 +883,8 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL  		}  		else if (count > 1)  		{ -			LLDynamicArray<LLFolderViewEventListener*> listeners; -			LLFolderViewEventListener* listener; +			LLDynamicArray<LLFolderViewModelItem*> listeners; +			LLFolderViewModelItem* listener;  			LLFolderViewItem* last_item = items[count - 1];  			LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE);  			while(new_selection && new_selection->isSelected()) @@ -1141,22 +901,22 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL  			}  			if (new_selection)  			{ -				setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); +				getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus());  			}  			else  			{ -				setSelectionFromRoot(NULL, mParentPanel->hasFocus()); +				getRoot()->setSelection(NULL, mParentPanel->hasFocus());  			}  			for(S32 i = 0; i < count; ++i)  			{ -				listener = items[i]->getListener(); -				if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) +				listener = items[i]->getViewModelItem(); +				if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItem*>::FAIL))  				{  					listeners.put(listener);  				}  			} -			listener = listeners.get(0); +			listener = static_cast<LLFolderViewModelItem*>(listeners.get(0));  			if(listener)  			{  				listener->removeBatch(listeners); @@ -1187,13 +947,13 @@ void LLFolderView::openSelectedItems( void )  				// IT_{OBJECT,ATTACHMENT} creates LLProperties  				// floaters; others create LLPreviews.  Put  				// each one in the right type of container. -				LLFolderViewEventListener* listener = (*item_it)->getListener(); +				LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem());  				bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT);  				if (is_prop)  					LLFloater::setFloaterHost(multi_propertiesp);  				else  					LLFloater::setFloaterHost(multi_previewp); -				(*item_it)->openItem(); +				listener->openItem();  			}  			LLFloater::setFloaterHost(NULL); @@ -1207,30 +967,31 @@ void LLFolderView::openSelectedItems( void )  void LLFolderView::propertiesSelectedItems( void )  { -	if(getVisible() && getEnabled()) -	{ -		if (mSelectedItems.size() == 1) -		{ -			LLFolderViewItem* folder_item = mSelectedItems.front(); -			if(!folder_item) return; -			folder_item->getListener()->showProperties(); -		} -		else -		{ -			LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - -			LLFloater::setFloaterHost(multi_propertiesp); - -			selected_items_t::iterator item_it; -			for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -			{ -				(*item_it)->getListener()->showProperties(); -			} - -			LLFloater::setFloaterHost(NULL); -			multi_propertiesp->openFloater(LLSD()); -		} -	} +	//TODO RN: get working again +	//if(getVisible() && getEnabled()) +	//{ +	//	if (mSelectedItems.size() == 1) +	//	{ +	//		LLFolderViewItem* folder_item = mSelectedItems.front(); +	//		if(!folder_item) return; +	//		folder_item->getViewModelItem()->showProperties(); +	//	} +	//	else +	//	{ +	//		LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + +	//		LLFloater::setFloaterHost(multi_propertiesp); + +	//		selected_items_t::iterator item_it; +	//		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) +	//		{ +	//			(*item_it)->getViewModelItem()->showProperties(); +	//		} + +	//		LLFloater::setFloaterHost(NULL); +	//		multi_propertiesp->openFloater(LLSD()); +	//	} +	//}  }  void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) @@ -1327,7 +1088,7 @@ BOOL LLFolderView::canCopy() const  	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)  	{  		const LLFolderViewItem* item = *selected_it; -		if (!item->getListener()->isItemCopyable()) +		if (!item->getViewModelItem()->isItemCopyable())  		{  			return FALSE;  		} @@ -1343,11 +1104,11 @@ void LLFolderView::copy()  	S32 count = mSelectedItems.size();  	if(getVisible() && getEnabled() && (count > 0))  	{ -		LLFolderViewEventListener* listener = NULL; +		LLFolderViewModelItem* listener = NULL;  		selected_items_t::iterator item_it;  		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  		{ -			listener = (*item_it)->getListener(); +			listener = (*item_it)->getViewModelItem();  			if(listener)  			{  				listener->copyToClipboard(); @@ -1367,7 +1128,7 @@ BOOL LLFolderView::canCut() const  	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)  	{  		const LLFolderViewItem* item = *selected_it; -		const LLFolderViewEventListener* listener = item->getListener(); +		const LLFolderViewModelItem* listener = item->getViewModelItem();  		if (!listener || !listener->isItemRemovable())  		{ @@ -1384,11 +1145,11 @@ void LLFolderView::cut()  	S32 count = mSelectedItems.size();  	if(getVisible() && getEnabled() && (count > 0))  	{ -		LLFolderViewEventListener* listener = NULL; +		LLFolderViewModelItem* listener = NULL;  		selected_items_t::iterator item_it;  		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  		{ -			listener = (*item_it)->getListener(); +			listener = (*item_it)->getViewModelItem();  			if(listener)  			{  				listener->cutToClipboard(); @@ -1413,11 +1174,11 @@ BOOL LLFolderView::canPaste() const  		{  			// *TODO: only check folders and parent folders of items  			const LLFolderViewItem* item = (*item_it); -			const LLFolderViewEventListener* listener = item->getListener(); +			const LLFolderViewModelItem* listener = item->getViewModelItem();  			if(!listener || !listener->isClipboardPasteable())  			{  				const LLFolderViewFolder* folderp = item->getParentFolder(); -				listener = folderp->getListener(); +				listener = folderp->getViewModelItem();  				if (!listener || !listener->isClipboardPasteable())  				{  					return FALSE; @@ -1435,24 +1196,24 @@ void LLFolderView::paste()  	if(getVisible() && getEnabled())  	{  		// find set of unique folders to paste into -		std::set<LLFolderViewItem*> folder_set; +		std::set<LLFolderViewFolder*> folder_set;  		selected_items_t::iterator selected_it;  		for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)  		{  			LLFolderViewItem* item = *selected_it; -			LLFolderViewEventListener* listener = item->getListener(); -			if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) +			LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); +			if (folder == NULL)  			{  				item = item->getParentFolder();  			} -			folder_set.insert(item); +			folder_set.insert(folder);  		} -		std::set<LLFolderViewItem*>::iterator set_iter; +		std::set<LLFolderViewFolder*>::iterator set_iter;  		for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter)  		{ -			LLFolderViewEventListener* listener = (*set_iter)->getListener(); +			LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem();  			if(listener && listener->isClipboardPasteable())  			{  				listener->pasteFromClipboard(); @@ -1474,8 +1235,8 @@ void LLFolderView::startRenamingSelectedItem( void )  	{  		item = mSelectedItems.front();  	} -	if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && -	   item->getListener()->isItemRenameable()) +	if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && +	   item->getViewModelItem()->isItemRenameable())  	{  		mRenameItem = item; @@ -1588,12 +1349,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )  					if (next->isSelected())  					{  						// shrink selection -						changeSelectionFromRoot(last_selected, FALSE); +						getRoot()->changeSelection(last_selected, FALSE);  					}  					else if (last_selected->getParentFolder() == next->getParentFolder())  					{  						// grow selection -						changeSelectionFromRoot(next, TRUE); +						getRoot()->changeSelection(next, TRUE);  					}  				}  			} @@ -1652,12 +1413,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )  					if (prev->isSelected())  					{  						// shrink selection -						changeSelectionFromRoot(last_selected, FALSE); +						getRoot()->changeSelection(last_selected, FALSE);  					}  					else if (last_selected->getParentFolder() == prev->getParentFolder())  					{  						// grow selection -						changeSelectionFromRoot(prev, TRUE); +						getRoot()->changeSelection(prev, TRUE);  					}  				}  			} @@ -1784,7 +1545,7 @@ BOOL LLFolderView::canDoDelete() const  	for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)  	{ -		if (!(*item_it)->getListener()->isItemRemovable()) +		if (!(*item_it)->getViewModelItem()->isItemRemovable())  		{  			return FALSE;  		} @@ -1851,7 +1612,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc  			}  		} -		const std::string current_item_label(search_item->getSearchableLabel()); +		const std::string current_item_label(search_item->getViewModelItem()->getSearchableName());  		S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size());  		if (!current_item_label.compare(0, search_string_length, upper_case_string))  		{ @@ -1895,7 +1656,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )  	S32 count = mSelectedItems.size();  	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();  	if (   handled -		&& ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible +		&& ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible  		&& menu )  	{  		if (mCallbackRegistrar) @@ -1968,15 +1729,9 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	// when drop is not handled by child, it should be handled  	// by the folder which is the hierarchy root. -	if (!handled -		&& getListener()->getUUID().notNull()) -		{ -			handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); -		} - -	if (handled) +	if (!handled)  	{ -		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; +		handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);  	}  	return handled; @@ -2076,55 +1831,6 @@ void LLFolderView::setShowSingleSelection(BOOL show)  	}  } -void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) -{ -	mItemMap[id] = itemp; -} - -void LLFolderView::removeItemID(const LLUUID& id) -{ -	mItemMap.erase(id); -} - -LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); -LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) -{ -	LLFastTimer _(FTM_GET_ITEM_BY_ID); -	if (id == getListener()->getUUID()) -	{ -		return this; -	} - -	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; -	map_it = mItemMap.find(id); -	if (map_it != mItemMap.end()) -	{ -		return map_it->second; -	} - -	return NULL; -} - -LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) -{ -	if (id == getListener()->getUUID()) -	{ -		return this; -	} - -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end(); -		 ++iter) -	{ -		LLFolderViewFolder *folder = (*iter); -		if (folder->getListener()->getUUID() == id) -		{ -			return folder; -		} -	} -	return NULL; -} -  bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)  {  	std::string action = userdata.asString(); @@ -2140,7 +1846,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)  		return true;  	}  	if (("copy" == action) || ("cut" == action)) -	{ +	{	  		// Clear the clipboard before we start adding things on it  		LLClipboard::instance().reset();  	} @@ -2155,7 +1861,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)  	} -	std::set<LLUUID> selected_items = getSelectionList(); +	std::set<LLFolderViewItem*> selected_items = getSelectionList();  	LLMultiPreview* multi_previewp = NULL;  	LLMultiProperties* multi_propertiesp = NULL; @@ -2176,13 +1882,13 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)  		LLFloater::setFloaterHost(multi_propertiesp);  	} -	std::set<LLUUID>::iterator set_iter; +	std::set<LLFolderViewItem*>::iterator set_iter;  	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)  	{ -		LLFolderViewItem* folder_item = getItemByID(*set_iter); +		LLFolderViewItem* folder_item = *set_iter;  		if(!folder_item) continue; -		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); +		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();  		if(!bridge) continue;  		bridge->performAction(model, action);  	} @@ -2216,21 +1922,14 @@ void LLFolderView::doIdle()  	LLFastTimer t2(FTM_INVENTORY); -	BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); -	if (debug_filters != getDebugFilters()) -	{ -		mDebugFilters = debug_filters; -		arrangeAll(); -	} - -	if (mFilter->isModified() && mFilter->isNotDefault()) +	if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault())  	{  		mNeedsAutoSelect = TRUE;  	} -	mFilter->clearModified(); +	getFolderViewModel()->getFilter()->clearModified();  	// filter to determine visibility before arranging -	filterFromRoot(); +	filter(*(getFolderViewModel()->getFilter()));  	// automatically show matching items, and select first one if we had a selection  	if (mNeedsAutoSelect) @@ -2238,7 +1937,7 @@ void LLFolderView::doIdle()  		LLFastTimer t3(FTM_AUTO_SELECT);  		// select new item only if a filtered item not currently selected  		LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); -		if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyFiltered())) +		if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible()))  		{  			// these are named variables to get around gcc not binding non-const references to rvalues  			// and functor application is inherently non-const to allow for stateful functors @@ -2248,7 +1947,7 @@ void LLFolderView::doIdle()  		// Open filtered folders for folder views with mAutoSelectOverride=TRUE.  		// Used by LLPlacesFolderView. -		if (mAutoSelectOverride && !mFilter->getFilterSubString().empty()) +		if (getFolderViewModel()->getFilter()->showAllResults())  		{  			// these are named variables to get around gcc not binding non-const references to rvalues  			// and functor application is inherently non-const to allow for stateful functors @@ -2259,8 +1958,8 @@ void LLFolderView::doIdle()  		scrollToShowSelection();  	} -	BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration()  -						&& !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +	BOOL filter_finished = getViewModelItem()->passedFilter() +						&& mViewModel->contentsReady();  	if (filter_finished   		|| gFocusMgr.childHasKeyboardFocus(inventory_panel)   		|| gFocusMgr.childHasMouseCapture(inventory_panel)) @@ -2330,7 +2029,10 @@ void LLFolderView::doIdle()  		sanitizeSelection();  		if( needsArrange() )  		{ -			arrangeFromRoot(); +			S32 height = 0; +			S32 width = 0; +			S32 total_height = arrange( &width, &height ); +			notifyParent(LLSD().with("action", "size_changes").with("height", total_height));  		}  	} @@ -2535,77 +2237,17 @@ void LLFolderView::onRenamerLost()  	if( mRenameItem )  	{ -		setSelectionFromRoot( mRenameItem, TRUE ); +		setSelection( mRenameItem, TRUE );  		mRenameItem = NULL;  	}  } -LLInventoryFilter* LLFolderView::getFilter() -{ -	return mFilter; -} - -void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) -{ -	mFilter->setFilterPermissions(filter_perm_mask); -} - -U32 LLFolderView::getFilterObjectTypes() const -{ -	return mFilter->getFilterObjectTypes(); -} - -PermissionMask LLFolderView::getFilterPermissions() const -{ -	return mFilter->getFilterPermissions(); -} - -BOOL LLFolderView::isFilterModified() -{ -	return mFilter->isNotDefault(); -} - -void delete_selected_item(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->removeSelectedItems(); -	} -} - -void copy_selected_item(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->copy(); -	} -} - -void paste_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->paste(); -	} -} - -void open_selected_items(void* user_data) +S32 LLFolderView::getItemHeight()  { -	if(user_data) +	if(!hasVisibleChildren())  	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->openSelectedItems(); -	} -} - -void properties_selected_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->propertiesSelectedItems(); +		//We need to display status textbox, let's reserve some place for it +		return llmax(0, mStatusTextBox->getTextPixelHeight());  	} +	return 0;  } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index dc3d02eac6..8a0317f840 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -48,9 +48,10 @@  #include "lltooldraganddrop.h"  #include "llviewertexture.h" -class LLFolderViewEventListener; +class LLFolderViewModelInterface;  class LLFolderViewFolder;  class LLFolderViewItem; +class LLFolderViewFilter;  class LLInventoryModel;  class LLPanel;  class LLLineEditor; @@ -95,8 +96,9 @@ public:  		Optional<bool>			use_label_suffix,  								allow_multiselect,  								show_empty_message, -								show_load_status, -								use_ellipses; +								use_ellipses, +								show_item_link_overlays; +		Mandatory<LLFolderViewModelInterface*>	view_model;  		Params();  	}; @@ -108,69 +110,53 @@ public:  	virtual BOOL canFocusChildren() const; +	virtual const LLFolderView*	getRoot() const { return this; }  	virtual LLFolderView*	getRoot() { return this; } -	// FolderViews default to sort by name. This will change that, -	// and resort the items if necessary. -	void setSortOrder(U32 order); +	LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } +	const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } +  	void setFilterPermMask(PermissionMask filter_perm_mask);  	typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;  	void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }  	void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } -	// filter is never null -	LLInventoryFilter* getFilter(); -	const std::string getFilterSubString(BOOL trim = FALSE); -	U32 getFilterObjectTypes() const; -	PermissionMask getFilterPermissions() const; -	// *NOTE: use getFilter()->getShowFolderState(); -	//LLInventoryFilter::EFolderShow getShowFolderState(); -	U32 getSortOrder() const; -	BOOL isFilterModified(); -  	bool getAllowMultiSelect() { return mAllowMultiSelect; }  	// Close all folders in the view  	void closeAllFolders();  	void openTopLevelFolders(); -	virtual void toggleOpen() {}; -	virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse);  	virtual BOOL addFolder( LLFolderViewFolder* folder);  	// Find width and height of this object and its children. Also  	// makes sure that this view and its children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); +	virtual S32 arrange( S32* width, S32* height ); +	virtual S32 getItemHeight();  	void arrangeAll() { mArrangeGeneration++; }  	S32 getArrangeGeneration() { return mArrangeGeneration; } -	// Apply filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); +	// applies filters to control visibility of items +	virtual void filter( LLFolderViewFilter& filter);  	// Get the last selected item  	virtual LLFolderViewItem* getCurSelectedItem( void );  	// Record the selected item and pass it down the hierarchy.  	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, -		BOOL take_keyboard_focus); - -	// Used by menu callbacks -	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); +		BOOL take_keyboard_focus = TRUE); -	// Called once a frame to update the selection if mSelectThisID has been set -	void updateSelection(); - -	// This method is used to toggle the selection of an item.  -	// Walks children and keeps track of selected objects. +	// This method is used to toggle the selection of an item. Walks +	// children, and keeps track of selected objects.  	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); -	virtual std::set<LLUUID> getSelectionList() const; +	virtual std::set<LLFolderViewItem*> getSelectionList() const;  	// Make sure if ancestor is selected, descendents are not  	void sanitizeSelection(); -	void clearSelection(); +	virtual void clearSelection();  	void addToSelectionList(LLFolderViewItem* item);  	void removeFromSelectionList(LLFolderViewItem* item); @@ -193,6 +179,7 @@ public:  	void autoOpenItem(LLFolderViewFolder* item);  	void closeAutoOpenedFolders();  	BOOL autoOpenTest(LLFolderViewFolder* item); +	BOOL isOpen() const { return TRUE; } // root folder always open  	// Copy & paste  	virtual void	copy(); @@ -241,11 +228,6 @@ public:  	F32  getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }  	bool getUseEllipses() { return mUseEllipses; } -	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); -	void removeItemID(const LLUUID& id); -	LLFolderViewItem* getItemByID(const LLUUID& id); -	LLFolderViewFolder* getFolderByID(const LLUUID& id); -	  	bool doToSelected(LLInventoryModel* model, const LLSD& userdata);  	void	doIdle();						// Real idle routine @@ -257,9 +239,9 @@ public:  	void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; }  	void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } -	void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } +	bool showItemLinkOverlays() { return mShowItemLinkOverlays; } -	BOOL getDebugFilters() { return mDebugFilters; } +	void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }  	LLPanel* getParentPanel() { return mParentPanel; }  	// DEBUG only @@ -312,15 +294,14 @@ protected:  	BOOL							mAutoSelectOverride;  	BOOL							mNeedsAutoRename;  	bool							mUseLabelSuffix; +	bool							mShowItemLinkOverlays; -	BOOL							mDebugFilters;  	U32								mSortOrder;  	LLDepthStack<LLFolderViewFolder>	mAutoOpenItems;  	LLFolderViewFolder*				mAutoOpenCandidate;  	LLFrameTimer					mAutoOpenTimer;  	LLFrameTimer					mSearchTimer;  	std::string						mSearchString; -	LLInventoryFilter*				mFilter;  	BOOL							mShowSelectionContext;  	BOOL							mShowSingleSelection;  	LLFrameTimer					mMultiSelectionFadeTimer; @@ -330,13 +311,11 @@ protected:  	signal_t						mReshapeSignal;  	S32								mSignalSelectCallback;  	S32								mMinWidth; -	S32								mRunningHeight; -	std::map<LLUUID, LLFolderViewItem*> mItemMap;  	BOOL							mDragAndDropThisFrame; -	LLUUID							mSelectThisID; // if non null, select this item -	  	LLPanel*						mParentPanel; +	 +	LLFolderViewModelInterface*		mViewModel;  	/**  	 * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. @@ -357,8 +336,66 @@ public:  }; -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b); -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFunctor +// +// Simple abstract base class for applying a functor to folders and +// items in a folder view hierarchy. This is suboptimal for algorithms +// that only work folders or only work on items, but I'll worry about +// that later when it's determined to be too slow. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFolderViewFunctor +{ +public: +	virtual ~LLFolderViewFunctor() {} +	virtual void doFolder(LLFolderViewFolder* folder) = 0; +	virtual void doItem(LLFolderViewItem* item) = 0; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: +	LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} +	virtual ~LLSelectFirstFilteredItem() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item); +	BOOL wasItemSelected() { return mItemSelected; } +protected: +	BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: +	LLOpenFilteredFolders()  {} +	virtual ~LLOpenFilteredFolders() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: +	LLSaveFolderState() : mApply(FALSE) {} +	virtual ~LLSaveFolderState() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item) {} +	void setApply(BOOL apply); +	void clearOpenFolders() { mOpenFolders.clear(); } +protected: +	std::set<LLUUID> mOpenFolders; +	BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: +	LLOpenFoldersWithSelection() {} +	virtual ~LLOpenFoldersWithSelection() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item); +};  // Flags for buildContextMenu()  const U32 SUPPRESS_OPEN_ITEM = 0x1; diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h deleted file mode 100644 index 06682dcbf1..0000000000 --- a/indra/newview/llfoldervieweventlistener.h +++ /dev/null @@ -1,103 +0,0 @@ -/**  - * @file llfoldervieweventlistener.h - * - * $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$ - */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H - -#include "lldarray.h"	// *TODO: convert to std::vector -#include "llfoldertype.h" -#include "llfontgl.h"	// just for StyleFlags enum -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" - - -class LLFolderViewItem; -class LLFolderView; -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLScrollContainer; -class LLUIImage; -class LLUUID; - -// This is an abstract base class that users of the folderview classes -// would use to catch the useful events emitted from the folder -// views. -class LLFolderViewEventListener -{ -public: -	virtual ~LLFolderViewEventListener( void ) {} -	virtual const std::string& getName() const = 0; -	virtual const std::string& getDisplayName() const = 0; -	virtual const LLUUID& getUUID() const = 0; -	virtual time_t getCreationDate() const = 0;	// UTC seconds -	virtual PermissionMask getPermissionMask() const = 0; -	virtual LLFolderType::EType getPreferredType() const = 0; -	virtual LLPointer<LLUIImage> getIcon() const = 0; -	virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } -	virtual LLFontGL::StyleFlags getLabelStyle() const = 0; -	virtual std::string getLabelSuffix() const = 0; -	virtual void openItem( void ) = 0; -	virtual void closeItem( void ) = 0; -	virtual void previewItem( void ) = 0; -	virtual void selectItem(void) = 0; -	virtual void showProperties(void) = 0; -	virtual BOOL isItemRenameable() const = 0; -	virtual BOOL renameItem(const std::string& new_name) = 0; -	virtual BOOL isItemMovable( void ) const = 0;		// Can be moved to another folder -	virtual BOOL isItemRemovable( void ) const = 0;		// Can be destroyed -	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. -	virtual BOOL removeItem() = 0; -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; -	virtual void move( LLFolderViewEventListener* parent_listener ) = 0; -	virtual BOOL isItemCopyable() const = 0; -	virtual BOOL copyToClipboard() const = 0; -	virtual BOOL cutToClipboard() const = 0; -	virtual BOOL isClipboardPasteable() const = 0; -	virtual void pasteFromClipboard() = 0; -	virtual void pasteLinkFromClipboard() = 0; -	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; -	virtual BOOL isUpToDate() const = 0; -	virtual BOOL hasChildren() const = 0; -	virtual LLInventoryType::EType getInventoryType() const = 0; -	virtual void performAction(LLInventoryModel* model, std::string action) = 0; -	virtual LLWearableType::EType getWearableType() const = 0; -	 -	// This method should be called when a drag begins. returns TRUE -	// if the drag can begin, otherwise FALSE. -	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; -	 -	// This method will be called to determine if a drop can be -	// performed, and will set drop to TRUE if a drop is -	// requested. Returns TRUE if a drop is possible/happened, -	// otherwise FALSE. -	virtual BOOL dragOrDrop(MASK mask, BOOL drop, -							EDragAndDropType cargo_type, -							void* cargo_data, -							std::string& tooltip_msg) = 0; -}; - -#endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 8ae779326c..80893c3037 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -29,10 +29,10 @@  // viewer includes  #include "llfolderview.h"		// Items depend extensively on LLFolderViews -#include "llfoldervieweventlistener.h" +#include "llfolderview.h" +#include "llfolderviewmodel.h"  #include "llviewerfoldertype.h"  #include "llinventorybridge.h"	// for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfilter.h"  #include "llinventoryfunctions.h"  #include "llinventorymodelbackgroundfetch.h"  #include "llpanel.h" @@ -91,10 +91,7 @@ void LLFolderViewItem::cleanupClass()  // NOTE: Optimize this, we call it a *lot* when opening a large inventory  LLFolderViewItem::Params::Params() -:	icon(), -	icon_open(), -	icon_overlay(), -	root(), +:	root(),  	listener(),  	folder_arrow_image("folder_arrow_image"),  	folder_indentation("folder_indentation"), @@ -117,22 +114,19 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)  	mHasVisibleChildren(FALSE),  	mIndentation(0),  	mItemHeight(p.item_height), -	mPassedFilter(FALSE), -	mLastFilterGeneration(-1), -	mStringMatchOffset(std::string::npos), +	//TODO RN: create interface for string highlighting +	//mStringMatchOffset(std::string::npos),  	mControlLabelRotation(0.f),  	mDragAndDropTarget(FALSE), -	mIsLoading(FALSE),  	mLabel(p.name),  	mRoot(p.root), -	mCreationDate(p.creation_date), -	mIcon(p.icon), -	mIconOpen(p.icon_open), -	mIconOverlay(p.icon_overlay), -	mListener(p.listener), -	mShowLoadStatus(false), +	mViewModelItem(p.listener),  	mIsMouseOverTitle(false)  { +	if (mViewModelItem) +	{ +		mViewModelItem->setFolderViewItem(this); +	}  }  BOOL LLFolderViewItem::postBuild() @@ -144,8 +138,8 @@ BOOL LLFolderViewItem::postBuild()  // Destroys the object  LLFolderViewItem::~LLFolderViewItem( void )  { -	delete mListener; -	mListener = NULL; +	delete mViewModelItem; +	mViewModelItem = NULL;  }  LLFolderView* LLFolderViewItem::getRoot() @@ -153,6 +147,10 @@ LLFolderView* LLFolderViewItem::getRoot()  	return mRoot;  } +const LLFolderView* LLFolderViewItem::getRoot() const +{ +	return mRoot; +}  // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor.  BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor )  { @@ -214,146 +212,47 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)  	return itemp;  } -// is this item something we think we should be showing? -// for example, if we haven't gotten around to filtering it yet, then the answer is yes -// until we find out otherwise -BOOL LLFolderViewItem::potentiallyVisible() -{ -	// we haven't been checked against min required filter -	// or we have and we passed -	return potentiallyFiltered(); -} - -BOOL LLFolderViewItem::potentiallyFiltered() +BOOL LLFolderViewItem::passedFilter(S32 filter_generation)   { -	return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); +	return getViewModelItem()->passedFilter(filter_generation);  } -BOOL LLFolderViewItem::getFiltered()  +void LLFolderViewItem::refresh()  {  -	return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();  -} +	LLFolderViewModelItem& vmi = *getViewModelItem(); -BOOL LLFolderViewItem::getFiltered(S32 filter_generation)  -{ -	return mPassedFilter && mLastFilterGeneration >= filter_generation; -} +	mLabel = vmi.getDisplayName(); -void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) -{ -	mPassedFilter = filtered; -	mLastFilterGeneration = filter_generation; -} +	setToolTip(mLabel); +	mIcon = vmi.getIcon(); +	mIconOpen = vmi.getIconOpen(); +	mIconOverlay = vmi.getIconOverlay(); -void LLFolderViewItem::setIcon(LLUIImagePtr icon) -{ -	mIcon = icon; -} - -// refresh information from the listener -void LLFolderViewItem::refreshFromListener() -{ -	if(mListener) +	if (mRoot->useLabelSuffix())  	{ -		mLabel = mListener->getDisplayName(); -		LLFolderType::EType preferred_type = mListener->getPreferredType(); - -		// *TODO: to be removed when database supports multi language. This is a -		// temporary attempt to display the inventory folder in the user locale. -		// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID -		//		it uses the same way to find localized string - -		// HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) -		// Translation of Accessories folder in Library inventory folder -		bool accessories = false; -		if(mLabel == std::string("Accessories")) -		{ -			//To ensure that Accessories folder is in Library we have to check its parent folder. -			//Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model -			LLInventoryCategory* cat = gInventory.getCategory(mListener->getUUID()); -			if(cat) -			{ -				const LLUUID& parent_folder_id = cat->getParentUUID(); -				accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); -			} -		} - -		//"Accessories" inventory category has folder type FT_NONE. So, this folder -		//can not be detected as protected with LLFolderType::lookupIsProtectedType -		if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) -		{ -			LLTrans::findString(mLabel, "InvFolder " + mLabel); -		}; - -		setToolTip(mLabel); -		setIcon(mListener->getIcon()); -		time_t creation_date = mListener->getCreationDate(); -		if ((creation_date > 0) && (mCreationDate != creation_date)) -		{ -			setCreationDate(creation_date); -			dirtyFilter(); -		} -		if (mRoot && mRoot->useLabelSuffix()) -		{ -			mLabelStyle = mListener->getLabelStyle(); -			mLabelSuffix = mListener->getLabelSuffix(); -		} +		mLabelStyle = vmi.getLabelStyle(); +		mLabelSuffix = vmi.getLabelSuffix();  	} -} - -void LLFolderViewItem::refresh() -{ -	refreshFromListener(); -	std::string searchable_label(mLabel); -	searchable_label.append(mLabelSuffix); -	LLStringUtil::toUpper(searchable_label); +	//TODO RN: make sure this logic still fires +	//std::string searchable_label(mLabel); +	//searchable_label.append(mLabelSuffix); +	//LLStringUtil::toUpper(searchable_label); -	if (mSearchableLabel.compare(searchable_label)) -	{ -		mSearchableLabel.assign(searchable_label); -		dirtyFilter(); -		// some part of label has changed, so overall width has potentially changed, and sort order too -		if (mParentFolder) -		{ -			mParentFolder->requestSort(); -			mParentFolder->requestArrange(); -		} -	} +	//if (mSearchableLabel.compare(searchable_label)) +	//{ +	//	mSearchableLabel.assign(searchable_label); +	//	vmi.dirtyFilter(); +	//	// some part of label has changed, so overall width has potentially changed, and sort order too +	//	if (mParentFolder) +	//	{ +	//		mParentFolder->requestSort(); +	//		mParentFolder->requestArrange(); +	//	} +	//}  	mLabelWidthDirty = true; -} - -void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ -	functor(mListener); -} - -// This function is called when items are added or view filters change. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::filterFromRoot( void ) -{ -	LLFolderViewItem* root = getRoot(); - -	root->filter(*((LLFolderView*)root)->getFilter()); -} - -// This function is called when the folder view is dirty. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::arrangeFromRoot() -{ -	LLFolderViewItem* root = getRoot(); - -	S32 height = 0; -	S32 width = 0; -	S32 total_height = root->arrange( &width, &height, 0 ); - -	LLSD params; -	params["action"] = "size_changes"; -	params["height"] = total_height; -	getParent()->notifyParent(params); +	vmi.dirtyFilter();  }  // Utility function for LLFolderView @@ -367,7 +266,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,  	}  	if(set_selection)  	{ -		setSelectionFromRoot(this, TRUE, take_keyboard_focus); +		getRoot()->setSelection(this, TRUE, take_keyboard_focus);  		if(root)  		{  			root->scrollToShowSelection(); @@ -375,57 +274,23 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,  	}		  } -// This function clears the currently selected item, and records the -// specified selected item appropriately for display and use in the -// UI. If open is TRUE, then folders are opened up along the way to -// the selection. -void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, -											BOOL openitem, -											BOOL take_keyboard_focus) -{ -	if (getRoot()) -	{ -		getRoot()->setSelection(selection, openitem, take_keyboard_focus); -	} -    else if (mListener) -    { -        mListener->selectItem(); -    } -} - -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ -	getRoot()->changeSelection(selection, selected); -} -std::set<LLUUID> LLFolderViewItem::getSelectionList() const +std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const  { -	std::set<LLUUID> selection; +	std::set<LLFolderViewItem*> selection;  	return selection;  } -EInventorySortGroup LLFolderViewItem::getSortGroup()  const -{  -	return SG_ITEM;  -} -  // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder)  { -	if (!folder) -	{ -		return FALSE; -	} -	mParentFolder = folder; -	root->addItemID(getListener()->getUUID(), this);  	return folder->addItem(this);  }  // Finds width and height of this object and its children.  Also  // makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewItem::arrange( S32* width, S32* height )  {  	const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();  	S32 indentation = p.folder_indentation(); @@ -457,40 +322,6 @@ S32 LLFolderViewItem::getItemHeight()  	return mItemHeight;  } -void LLFolderViewItem::filter( LLInventoryFilter& filter) -{ -	const BOOL previous_passed_filter = mPassedFilter; -	const BOOL passed_filter = filter.check(this); - -	// If our visibility will change as a result of this filter, then -	// we need to be rearranged in our parent folder -	if (mParentFolder) -	{ -		if (getVisible() != passed_filter -			||	previous_passed_filter != passed_filter ) -			mParentFolder->requestArrange(); -	} - -	setFiltered(passed_filter, filter.getCurrentGeneration()); -	mStringMatchOffset = filter.getStringMatchOffset(); -	filter.decrementFilterCount(); - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -	} -} - -void LLFolderViewItem::dirtyFilter() -{ -	mLastFilterGeneration = -1; -	// bubble up dirty flag all the way to root -	if (getParentFolder()) -	{ -		getParentFolder()->setCompletedFilterGeneration(-1, TRUE); -	} -} -  // *TODO: This can be optimized a lot by simply recording that it is  // selected in the appropriate places, and assuming that set selection  // means 'deselect' for a leaf item. Do this optimization after @@ -535,45 +366,31 @@ void LLFolderViewItem::selectItem(void)  {  	if (mIsSelected == FALSE)  	{ -		if (mListener) -		{ -			mListener->selectItem(); -		} +		getViewModelItem()->selectItem();  		mIsSelected = TRUE;  	}  }  BOOL LLFolderViewItem::isMovable()  { -	if( mListener ) -	{ -		return mListener->isItemMovable(); -	} -	else -	{ -		return TRUE; -	} +	return getViewModelItem()->isItemMovable();  }  BOOL LLFolderViewItem::isRemovable()  { -	if( mListener ) -	{ -		return mListener->isItemRemovable(); -	} -	else -	{ -		return TRUE; -	} +	return getViewModelItem()->isItemRemovable();  }  void LLFolderViewItem::destroyView()  { +	getRoot()->removeFromSelectionList(this); +  	if (mParentFolder)  	{  		// removeView deletes me -		mParentFolder->removeView(this); +		mParentFolder->extractItem(this);  	} +	delete this;  }  // Call through to the viewed object and return true if it can be @@ -585,45 +402,25 @@ BOOL LLFolderViewItem::remove()  	{  		return FALSE;  	} -	if(mListener) -	{ -		return mListener->removeItem(); -	} -	return TRUE; +	return getViewModelItem()->removeItem();  }  // Build an appropriate context menu for the item.  void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)  { -	if(mListener) -	{ -		mListener->buildContextMenu(menu, flags); -	} +	getViewModelItem()->buildContextMenu(menu, flags);  }  void LLFolderViewItem::openItem( void )  { -	if( mListener ) -	{ -		mListener->openItem(); -	} -} - -void LLFolderViewItem::preview( void ) -{ -	if (mListener) -	{ -		mListener->previewItem(); -	} +	getViewModelItem()->openItem();  }  void LLFolderViewItem::rename(const std::string& new_name)  {  	if( !new_name.empty() )  	{ -		if( mListener ) -		{ -			mListener->renameItem(new_name); +		getViewModelItem()->renameItem(new_name);  			if(mParentFolder)  			{ @@ -631,26 +428,10 @@ void LLFolderViewItem::rename(const std::string& new_name)  			}  		}  	} -} - -const std::string& LLFolderViewItem::getSearchableLabel() const -{ -	return mSearchableLabel; -} - -LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) -{ -	if (!getListener()) return NULL; -	return gInventory.getItem(getListener()->getUUID()); -}  const std::string& LLFolderViewItem::getName( void ) const  { -	if(mListener) -	{ -		return mListener->getName(); -	} -	return mLabel; +	return getViewModelItem()->getName();  }  // LLView functionality @@ -658,7 +439,7 @@ BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask )  {  	if(!mIsSelected)  	{ -		setSelectionFromRoot(this, FALSE); +		getRoot()->setSelection(this, FALSE);  	}  	make_ui_sound("UISndClick");  	return TRUE; @@ -679,7 +460,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )  	{  		if(mask & MASK_CONTROL)  		{ -			changeSelectionFromRoot(this, !mIsSelected); +			getRoot()->changeSelection(this, !mIsSelected);  		}  		else if (mask & MASK_SHIFT)  		{ @@ -687,7 +468,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )  		}  		else  		{ -			setSelectionFromRoot(this, FALSE); +			getRoot()->setSelection(this, FALSE);  		}  		make_ui_sound("UISndClick");  	} @@ -726,21 +507,12 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  				// *TODO: push this into listener and remove  				// dependency on llagent -				if (mListener -					&& gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID())) -				{ -					src = LLToolDragAndDrop::SOURCE_AGENT; -				} -				else if (mListener -					&& gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID())) -				{ -					src = LLToolDragAndDrop::SOURCE_LIBRARY; -				} +				src = getViewModelItem()->getDragSource();  				can_drag = root->startDrag(src);  				if (can_drag)  				{ -					// if (mListener) mListener->startDrag(); +					// if (getViewModelItem()) getViewModelItem()->startDrag();  					// RN: when starting drag and drop, clear out last auto-open  					root->autoOpenTest(NULL);  					root->setShowSelectionContext(TRUE); @@ -769,7 +541,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  	{  		if (getRoot())  		{ -			getRoot()->setShowSelectionContext(FALSE); +		getRoot()->setShowSelectionContext(FALSE);  		}  		gViewerWindow->setCursor(UI_CURSOR_ARROW);  		// let parent handle this then... @@ -780,7 +552,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask )  { -	preview(); +	getViewModelItem()->openItem();  	return TRUE;  } @@ -797,7 +569,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )  		//...then select  		if(mask & MASK_CONTROL)  		{ -			changeSelectionFromRoot(this, !mIsSelected); +			getRoot()->changeSelection(this, !mIsSelected);  		}  		else if (mask & MASK_SHIFT)  		{ @@ -805,7 +577,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )  		}  		else  		{ -			setSelectionFromRoot(this, FALSE); +			getRoot()->setSelection(this, FALSE);  		}  	} @@ -815,7 +587,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )  	{  		if (getRoot())  		{ -			getRoot()->setShowSelectionContext(FALSE); +		getRoot()->setShowSelectionContext(FALSE);  		}  		gFocusMgr.setMouseCapture( NULL );  	} @@ -833,11 +605,8 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  										 EAcceptance* accept,  										 std::string& tooltip_msg)  { -	BOOL accepted = FALSE;  	BOOL handled = FALSE; -	if(mListener) -	{ -		accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); +	BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg);  		handled = accepted;  		if (accepted)  		{ @@ -848,7 +617,6 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  		{  			*accept = ACCEPT_NO;  		} -	}  	if(mParentFolder && !handled)  	{  		// store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. @@ -883,17 +651,12 @@ void LLFolderViewItem::draw()  	const S32 FOCUS_LEFT = 1;  	const LLFontGL* font = getLabelFontForStyle(mLabelStyle); -	const LLUUID uuid = (getListener() ? getListener()->getUUID() : LLUUID::null); -	const BOOL in_inventory = (uuid.notNull() ? gInventory.isObjectDescendentOf(uuid, gInventory.getRootFolderID()) : FALSE); -	const BOOL in_library   = (uuid.notNull() ? gInventory.isObjectDescendentOf(uuid, gInventory.getLibraryRootFolderID()) : FALSE); +	getViewModelItem()->update();  	//--------------------------------------------------------------------------------//  	// Draw open folder arrow  	// -	const bool up_to_date = mListener && mListener->isUpToDate(); -	const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter... -										|| (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) -	if (possibly_has_children) +	if (hasVisibleChildren() || getViewModelItem()->hasChildren())  	{  		LLUIImage* arrow_image = default_params.folder_arrow_image;  		gl_draw_scaled_rotated_image( @@ -990,8 +753,6 @@ void LLFolderViewItem::draw()  		mDragAndDropTarget = FALSE;  	} -	const LLViewerInventoryItem *item = getInventoryItem(); -	const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType();  	//--------------------------------------------------------------------------------//  	// Draw open icon  	// @@ -1005,7 +766,7 @@ void LLFolderViewItem::draw()   		mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);   	} -	if (highlight_link) +	if (mIconOverlay && getRoot()->showItemLinkOverlays())  	{  		mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);  	} @@ -1019,31 +780,15 @@ void LLFolderViewItem::draw()  	}  	LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; -	if (highlight_link) color = sLinkColor; -	if (in_library) color = sLibraryColor; +	//TODO RN: implement this in terms of getColor() +	//if (highlight_link) color = sLinkColor; +	//if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor;  	F32 right_x  = 0;  	F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD;  	F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation);  	//--------------------------------------------------------------------------------// -	// Highlight filtered text -	// -	if (getRoot() && getRoot()->getDebugFilters()) -	{ -		if (!getFiltered() && !possibly_has_children) -		{ -			color.mV[VALPHA] *= 0.5f; -		} -		LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ?  -			LLColor4(0.5f, 0.8f, 0.5f, 1.f) :  -			LLColor4(0.8f, 0.5f, 0.5f, 1.f); -		LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, -												 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -												 S32_MAX, S32_MAX, &right_x, FALSE ); -		text_left = right_x; -	} -	//--------------------------------------------------------------------------------//  	// Draw the actual label text  	//  	font->renderUTF8(mLabel, 0, text_left, y, color, @@ -1051,30 +796,6 @@ void LLFolderViewItem::draw()  					 S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);  	//--------------------------------------------------------------------------------// -	// Draw "Loading..." text -	// -	bool root_is_loading = false; -	if (in_inventory) -	{ -		root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress();  -	} -	if (in_library) -	{ -		root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); -	} -	if ((mIsLoading -		&&	mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) -			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive() -				&&	root_is_loading -				&&	mShowLoadStatus)) -	{ -		std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; -		font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, -						 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,  -						 S32_MAX, S32_MAX, &right_x, FALSE); -	} - -	//--------------------------------------------------------------------------------//  	// Draw label suffix  	//  	if (!mLabelSuffix.empty()) @@ -1087,28 +808,39 @@ void LLFolderViewItem::draw()  	//--------------------------------------------------------------------------------//  	// Highlight string match  	// -	if (mStringMatchOffset != std::string::npos) +	//TODO RN: expose interface for highlighting +	//if (mStringMatchOffset != std::string::npos) +	//{ +	//	// don't draw backgrounds for zero-length strings +	//	S32 filter_string_length = getRoot()->getFilterSubString().size(); +	//	if (filter_string_length > 0) +	//	{ +	//		std::string combined_string = mLabel + mLabelSuffix; +	//		S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; +	//		S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; +	//		S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); +	//		S32 top = getRect().getHeight() - TOP_PAD; +	//	 +	//		LLUIImage* box_image = default_params.selection_image; +	//		LLRect box_rect(left, top, right, bottom); +	//		box_image->draw(box_rect, sFilterBGColor); +	//		F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); +	//		F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; +	//		font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, +	//						  sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, +	//						  filter_string_length, S32_MAX, &right_x, FALSE ); +	//	} +	//} +} + +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const  	{ -		// don't draw backgrounds for zero-length strings -		S32 filter_string_length = (getRoot() ? getRoot()->getFilterSubString().size() : 0); -		if (filter_string_length > 0) +	return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void )  		{ -			std::string combined_string = mLabel + mLabelSuffix; -			S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; -			S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; -			S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); -			S32 top = getRect().getHeight() - TOP_PAD; -		 -			LLUIImage* box_image = default_params.selection_image; -			LLRect box_rect(left, top, right, bottom); -			box_image->draw(box_rect, sFilterBGColor); -			F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); -			F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; -			font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, -							  sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -							  filter_string_length, S32_MAX, &right_x, FALSE ); -		} -	} +	return getRoot()->getFolderViewModel();  } @@ -1117,20 +849,14 @@ void LLFolderViewItem::draw()  ///----------------------------------------------------------------------------  LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):  -	LLFolderViewItem( p ),	// 0 = no create time +	LLFolderViewItem( p ),  	mIsOpen(FALSE),  	mExpanderHighlighted(FALSE),  	mCurHeight(0.f),  	mTargetHeight(0.f),  	mAutoOpenCountdown(0.f), -	mSubtreeCreationDate(0), -	mAmTrash(LLFolderViewFolder::UNKNOWN),  	mLastArrangeGeneration( -1 ), -	mLastCalculatedWidth(0), -	mCompletedFilterGeneration(-1), -	mMostFilteredDescendantGeneration(-1), -	mNeedsSort(false), -	mPassedFolderFilter(FALSE) +	mLastCalculatedWidth(0)  {  } @@ -1142,44 +868,26 @@ LLFolderViewFolder::~LLFolderViewFolder( void )  	gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()  } -void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) -{ -	mPassedFolderFilter = filtered; -	mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) -{ -	return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); -} -  // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) -{ -	if (!folder) +BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)  	{ -		return FALSE; -	} -	mParentFolder = folder; -	root->addItemID(getListener()->getUUID(), this);  	return folder->addFolder(this);  } +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); +  // Finds width and height of this object and its children. Also  // makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewFolder::arrange( S32* width, S32* height )  {  	// sort before laying out contents -	if (mNeedsSort) -	{ -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -		mNeedsSort = false; -	} +	getRoot()->getFolderViewModel()->sort(this); + +	LLFastTimer t2(FTM_ARRANGE);  	// evaluate mHasVisibleChildren  	mHasVisibleChildren = false; -	if (hasFilteredDescendants(filter_generation)) +	if (getViewModelItem()->descendantsPassedFilter())  	{  		// We have to verify that there's at least one child that's not filtered out  		bool found = false; @@ -1187,7 +895,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  		for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit)  		{  			LLFolderViewItem* itemp = (*iit); -			found = (itemp->getFiltered(filter_generation)); +			found = itemp->passedFilter();  			if (found)  				break;  		} @@ -1197,10 +905,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  			for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)  			{  				LLFolderViewFolder* folderp = (*fit); -				found = ( folderp->getListener() -								&&	(folderp->getFiltered(filter_generation) -									 ||	(folderp->getFilteredFolder(filter_generation)  -										 && folderp->hasFilteredDescendants(filter_generation)))); +				found = folderp->passedFilter();  				if (found)  					break;  			} @@ -1210,13 +915,12 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  	}  	// calculate height as a single item (without any children), and reshapes rectangle to match -	LLFolderViewItem::arrange( width, height, filter_generation ); +	LLFolderViewItem::arrange( width, height );  	// clamp existing animated height so as to never get smaller than a single item  	mCurHeight = llmax((F32)*height, mCurHeight);  	// initialize running height value as height of single item in case we have no children -	*height = getItemHeight();  	F32 running_height = (F32)*height;  	F32 target_height = (F32)*height; @@ -1226,7 +930,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  		// set last arrange generation first, in case children are animating  		// and need to be arranged again  		mLastArrangeGeneration = getRoot()->getArrangeGeneration(); -		if (mIsOpen) +		if (isOpen())  		{  			// Add sizes of children  			S32 parent_item_height = getRect().getHeight(); @@ -1234,17 +938,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  			for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)  			{  				LLFolderViewFolder* folderp = (*fit); -				if (getRoot()->getDebugFilters()) -				{ -					folderp->setVisible(TRUE); -				} -				else -				{ -					folderp->setVisible( folderp->getListener() -										&&	(folderp->getFiltered(filter_generation) -											||	(folderp->getFilteredFolder(filter_generation)  -												&& folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter -				} +				folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter  				if (folderp->getVisible())  				{ @@ -1252,7 +946,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  					S32 child_height = 0;  					S32 child_top = parent_item_height - llround(running_height); -					target_height += folderp->arrange( &child_width, &child_height, filter_generation ); +					target_height += folderp->arrange( &child_width, &child_height );  					running_height += (F32)child_height;  					*width = llmax(*width, child_width); @@ -1263,14 +957,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  				iit != mItems.end(); ++iit)  			{  				LLFolderViewItem* itemp = (*iit); -				if (getRoot()->getDebugFilters()) -				{ -					itemp->setVisible(TRUE); -				} -				else -				{ -					itemp->setVisible(itemp->getFiltered(filter_generation)); -				} +				itemp->setVisible(itemp->passedFilter());  				if (itemp->getVisible())  				{ @@ -1278,7 +965,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  					S32 child_height = 0;  					S32 child_top = parent_item_height - llround(running_height); -					target_height += itemp->arrange( &child_width, &child_height, filter_generation ); +					target_height += itemp->arrange( &child_width, &child_height );  					// don't change width, as this item is as wide as its parent folder by construction  					itemp->reshape( itemp->getRect().getWidth(), child_height); @@ -1302,7 +989,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)  	// animate current height towards target height  	if (llabs(mCurHeight - mTargetHeight) > 1.f)  	{ -		mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); +		mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT));  		requestArrange(); @@ -1353,247 +1040,24 @@ BOOL LLFolderViewFolder::needsArrange()  void LLFolderViewFolder::requestSort()  { -	mNeedsSort = true; -	// whenever item order changes, we need to lay things out again -	requestArrange(); +	getViewModelItem()->requestSort();  } -void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) -{ -	//mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); -	mCompletedFilterGeneration = generation; -	// only aggregate up if we are a lower (older) value -	if (recurse_up -		&& mParentFolder -		&& generation < mParentFolder->getCompletedFilterGeneration()) -	{ -		mParentFolder->setCompletedFilterGeneration(generation, TRUE); -	} -} +//TODO RN: get height resetting working +//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) +//{ +//	// if this folder is now filtered, but wasn't before +//	// (it just passed) +//	if (passed && !passedFilter(filter_generation)) +//	{ +//		// reset current height, because last time we drew it +//		// it might have had more visible items than now +//		mCurHeight = 0.f; +//	} +// +//	LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); +//} -void LLFolderViewFolder::filter( LLInventoryFilter& filter) -{ -	S32 filter_generation = filter.getCurrentGeneration(); -	// if failed to pass filter newer than must_pass_generation -	// you will automatically fail this time, so we only -	// check against items that have passed the filter -	S32 must_pass_generation = filter.getMustPassGeneration(); -	 -	bool autoopen_folders = (filter.hasFilterString()); - -	// if we have already been filtered against this generation, skip out -	if (getCompletedFilterGeneration() >= filter_generation) -	{ -		return; -	} - -	// filter folder itself -	if (getLastFilterGeneration() < filter_generation) -	{ -		if (getLastFilterGeneration() >= must_pass_generation	// folder has been compared to a valid precursor filter -			&& !mPassedFilter)									// and did not pass the filter -		{ -			// go ahead and flag this folder as done -			mLastFilterGeneration = filter_generation; -			mStringMatchOffset = std::string::npos; -		} -		else // filter self only on first pass through -		{ -			// filter against folder rules -			filterFolder(filter); -			// and then item rules -			LLFolderViewItem::filter( filter ); -		} -	} - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -		mStatusText += llformat("(%d)", mCompletedFilterGeneration); -		mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); -	} - -	// all descendants have been filtered later than must pass generation -	// but none passed -	if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) -	{ -		// don't traverse children if we've already filtered them since must_pass_generation -		// and came back with nothing -		return; -	} - -	// we entered here with at least one filter iteration left -	// check to see if we have any more before continuing on to children -	if (filter.getFilterCount() < 0) -	{ -		return; -	} - -	// when applying a filter, matching folders get their contents downloaded first -	if (filter.isNotDefault() -		&& getFiltered(filter.getMinRequiredGeneration()) -		&&	(mListener -			&& !gInventory.isCategoryComplete(mListener->getUUID()))) -	{ -		LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID()); -	} - -	// now query children -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end(); -		 ++iter) -	{ -		LLFolderViewFolder* folder = (*iter); -		// have we run out of iterations this frame? -		if (filter.getFilterCount() < 0) -		{ -			break; -		} - -		// mMostFilteredDescendantGeneration might have been reset -		// in which case we need to update it even for folders that -		// don't need to be filtered anymore -		if (folder->getCompletedFilterGeneration() >= filter_generation) -		{ -			// track latest generation to pass any child items -			if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) -			{ -				mMostFilteredDescendantGeneration = filter_generation; -				requestArrange(); -			} -			// just skip it, it has already been filtered -			continue; -		} - -		// update this folders filter status (and children) -		folder->filter( filter ); - -		// track latest generation to pass any child items -		if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation)) -		{ -			mMostFilteredDescendantGeneration = filter_generation; -			requestArrange(); -			if (getRoot()->needsAutoSelect() && autoopen_folders) -			{ -				folder->setOpenArrangeRecursively(TRUE); -			} -		} -	} - -	for (items_t::iterator iter = mItems.begin(); -		 iter != mItems.end(); -		 ++iter) -	{ -		LLFolderViewItem* item = (*iter); -		if (filter.getFilterCount() < 0) -		{ -			break; -		} -		if (item->getLastFilterGeneration() >= filter_generation) -		{ -			if (item->getFiltered()) -			{ -				mMostFilteredDescendantGeneration = filter_generation; -				requestArrange(); -			} -			continue; -		} - -		if (item->getLastFilterGeneration() >= must_pass_generation &&  -			!item->getFiltered(must_pass_generation)) -		{ -			// failed to pass an earlier filter that was a subset of the current one -			// go ahead and flag this item as done -			item->setFiltered(FALSE, filter_generation); -			continue; -		} - -		item->filter( filter ); - -		if (item->getFiltered(filter.getMinRequiredGeneration())) -		{ -			mMostFilteredDescendantGeneration = filter_generation; -			requestArrange(); -		} -	} - -	// if we didn't use all filter iterations -	// that means we filtered all of our descendants -	// instead of exhausting the filter count for this frame -	if (filter.getFilterCount() > 0) -	{ -		// flag this folder as having completed filter pass for all descendants -		setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); -	} -} - -void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter) -{ -	const BOOL previous_passed_filter = mPassedFolderFilter; -	const BOOL passed_filter = filter.checkFolder(this); - -	// If our visibility will change as a result of this filter, then -	// we need to be rearranged in our parent folder -	if (mParentFolder) -	{ -		if (getVisible() != passed_filter -			|| previous_passed_filter != passed_filter ) -		{ -			mParentFolder->requestArrange(); -		} -	} - -	setFilteredFolder(passed_filter, filter.getCurrentGeneration()); -	filter.decrementFilterCount(); - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -	} -} - -void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) -{ -	// if this folder is now filtered, but wasn't before -	// (it just passed) -	if (filtered && !mPassedFilter) -	{ -		// reset current height, because last time we drew it -		// it might have had more visible items than now -		mCurHeight = 0.f; -	} - -	LLFolderViewItem::setFiltered(filtered, filter_generation); -} - -void LLFolderViewFolder::dirtyFilter() -{ -	// we're a folder, so invalidate our completed generation -	setCompletedFilterGeneration(-1, FALSE); -	LLFolderViewItem::dirtyFilter(); -} - -BOOL LLFolderViewFolder::getFiltered()  -{  -	return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration())  -		&& LLFolderViewItem::getFiltered();  -} - -BOOL LLFolderViewFolder::getFiltered(S32 filter_generation)  -{ -	return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation); -} - -BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) -{  -	return mMostFilteredDescendantGeneration >= filter_generation;  -} - - -BOOL LLFolderViewFolder::hasFilteredDescendants() -{ -	return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); -}  // Passes selection information on to children and record selection  // information if necessary. @@ -1947,14 +1411,6 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)  void LLFolderViewFolder::destroyView()  { -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		LLFolderViewItem* item = (*iit); -		getRoot()->removeItemID(item->getListener()->getUUID()); -	} -  	std::for_each(mItems.begin(), mItems.end(), DeletePointer());  	mItems.clear(); @@ -1964,41 +1420,7 @@ void LLFolderViewFolder::destroyView()  		folderp->destroyView(); // removes entry from mFolders  	} -	//deleteAllChildren(); - -	if (mParentFolder) -	{ -		mParentFolder->removeView(this); -	} -} - -// remove the specified item (and any children) if possible. Return -// TRUE if the item was deleted. -BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) -{ -	if(item->remove()) -	{ -		return TRUE; -	} -	return FALSE; -} - -// simply remove the view (and any children) Don't bother telling the -// listeners. -void LLFolderViewFolder::removeView(LLFolderViewItem* item) -{ -	if (!item || item->getParentFolder() != this) -	{ -		return; -	} -	// deselect without traversing hierarchy -	if (item->isSelected()) -	{ -		item->deselectItem(); -	} -	getRoot()->removeFromSelectionList(item); -	extractItem(item); -	delete item; +	LLFolderViewItem::destroyView();  }  // extractItem() removes the specified item from the folder, but @@ -2024,106 +1446,16 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )  		mItems.erase(it);  	}  	//item has been removed, need to update filter -	dirtyFilter(); +	getViewModelItem()->removeChild(item->getViewModelItem()); +	getViewModelItem()->dirtyFilter();  	//because an item is going away regardless of filter status, force rearrange  	requestArrange(); -	getRoot()->removeItemID(item->getListener()->getUUID());  	removeChild(item);  } -bool LLFolderViewFolder::isTrash() const -{ -	if (mAmTrash == LLFolderViewFolder::UNKNOWN) -	{ -		mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; -	} -	return mAmTrash == LLFolderViewFolder::TRASH; -} - -void LLFolderViewFolder::sortBy(U32 order) -{ -	if (!mSortFunction.updateSort(order)) -	{ -		// No changes. -		return; -	} - -	// Propagate this change to sub folders -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->sortBy(order); -	} - -	// Don't sort the topmost folders (My Inventory and Library) -	if (mListener->getUUID().notNull()) -	{ -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -	} - -	if (order & LLInventoryFilter::SO_DATE) -	{ -		time_t latest = 0; - -		if (!mItems.empty()) -		{ -			LLFolderViewItem* item = *(mItems.begin()); -			latest = item->getCreationDate(); -		} - -		if (!mFolders.empty()) -		{ -			LLFolderViewFolder* folder = *(mFolders.begin()); -			if (folder->getCreationDate() > latest) -			{ -				latest = folder->getCreationDate(); -			} -		} -		mSubtreeCreationDate = latest; -	} -} - -void LLFolderViewFolder::setItemSortOrder(U32 ordering) -{ -	if (mSortFunction.updateSort(ordering)) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			(*fit)->setItemSortOrder(ordering); -		} - -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -	} -} - -EInventorySortGroup LLFolderViewFolder::getSortGroup() const -{ -	if (isTrash()) -	{ -		return SG_TRASH_FOLDER; -	} - -	if( mListener ) -	{ -		if(LLFolderType::lookupIsProtectedType(mListener->getPreferredType())) -		{ -			return SG_SYSTEM_FOLDER; -		} -	} - -	return SG_NORMAL_FOLDER; -} -  BOOL LLFolderViewFolder::isMovable()  { -	if( mListener ) -	{ -		if( !(mListener->isItemMovable()) ) +	if( !(getViewModelItem()->isItemMovable()) )  		{  			return FALSE;  		} @@ -2147,16 +1479,13 @@ BOOL LLFolderViewFolder::isMovable()  				return FALSE;  			}  		} -	}  	return TRUE;  }  BOOL LLFolderViewFolder::isRemovable()  { -	if( mListener ) -	{ -		if( !(mListener->isItemRemovable()) ) +	if( !(getViewModelItem()->isItemRemovable()) )  		{  			return FALSE;  		} @@ -2180,13 +1509,18 @@ BOOL LLFolderViewFolder::isRemovable()  				return FALSE;  			}  		} -	}  	return TRUE;  }  // this is an internal method used for adding items to folders.   BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)  { +	if (item->getParentFolder()) +	{ +		item->getParentFolder()->extractItem(item); +	} +	item->setParentFolder(this); +  	mItems.push_back(item);  	item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); @@ -2194,39 +1528,27 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)  	addChild(item); -	item->dirtyFilter(); - -	// Update the folder creation date if the folder has no creation date -	bool setting_date = false; -	const time_t item_creation_date = item->getCreationDate(); -	if ((item_creation_date > 0) && (mCreationDate == 0)) -	{ -		setCreationDate(item_creation_date); -		setting_date = true; -	} +	item->getViewModelItem()->dirtyFilter();  	// Handle sorting  	requestArrange();  	requestSort(); -	// Traverse parent folders and update creation date and resort, if necessary -	LLFolderViewFolder* parentp = getParentFolder(); -	while (parentp) -	{ -		// Update the parent folder creation date -		if (setting_date && (parentp->mCreationDate == 0)) -		{ -			parentp->setCreationDate(item_creation_date); -		} +	getViewModelItem()->addChild(item->getViewModelItem()); -		if (parentp->mSortFunction.isByDate()) -		{ -			// parent folder doesn't have a time stamp yet, so get it from us -			parentp->requestSort(); -		} +	//TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria +	//// Traverse parent folders and update creation date and resort, if necessary +	//LLFolderViewFolder* parentp = this; +	//while (parentp) +	//{ +	//	if (parentp->mSortFunction.isByDate()) +	//	{ +	//		// parent folder doesn't have a time stamp yet, so get it from us +	//		parentp->requestSort(); +	//	} -		parentp = parentp->getParentFolder(); -	} +	//	parentp = parentp->getParentFolder(); +	//}  	return TRUE;  } @@ -2234,26 +1556,27 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)  // this is an internal method used for adding items to folders.   BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)  { +	if (folder->mParentFolder) +	{ +		folder->mParentFolder->extractItem(folder); +	} +	folder->mParentFolder = this;  	mFolders.push_back(folder);  	folder->setOrigin(0, 0);  	folder->reshape(getRect().getWidth(), 0);  	folder->setVisible(FALSE);  	addChild( folder ); -	folder->dirtyFilter(); +	folder->getViewModelItem()->dirtyFilter();  	// rearrange all descendants too, as our indentation level might have changed -	folder->requestArrange(TRUE); +	folder->requestArrange();  	requestSort(); -	LLFolderViewFolder* parentp = getParentFolder(); -	while (parentp && !parentp->mSortFunction.isByDate()) -	{ -		// parent folder doesn't have a time stamp yet, so get it from us -		parentp->requestSort(); -		parentp = parentp->getParentFolder(); -	} + +	getViewModelItem()->addChild(folder->getViewModelItem()); +  	return TRUE;  } -void LLFolderViewFolder::requestArrange(BOOL include_descendants)	 +void LLFolderViewFolder::requestArrange()  {   	mLastArrangeGeneration = -1;   	// flag all items up to root @@ -2261,21 +1584,11 @@ void LLFolderViewFolder::requestArrange(BOOL include_descendants)  	{  		mParentFolder->requestArrange();  	} - -	if (include_descendants) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end(); -			++iter) -		{ -			(*iter)->requestArrange(TRUE); -		} -	}  }  void LLFolderViewFolder::toggleOpen()  { -	setOpen(!mIsOpen); +	setOpen(!isOpen());  }  // Force a folder open or closed @@ -2286,18 +1599,15 @@ void LLFolderViewFolder::setOpen(BOOL openitem)  void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)  { -	BOOL was_open = mIsOpen; +	BOOL was_open = isOpen();  	mIsOpen = openitem; -	if (mListener) -	{  		if(!was_open && openitem)  		{ -			mListener->openItem(); +		getViewModelItem()->openItem();  		}  		else if(was_open && !openitem)  		{ -			mListener->closeItem(); -		} +		getViewModelItem()->closeItem();  	}  	if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) @@ -2316,7 +1626,7 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r  		mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);  	} -	if (was_open != mIsOpen) +	if (was_open != isOpen())  	{  		requestArrange();  	} @@ -2329,7 +1639,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask,  													EAcceptance* accept,  													std::string& tooltip_msg)  { -	BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); +	BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg);  	if (accepted)   	{  		mDragAndDropTarget = TRUE; @@ -2385,23 +1695,6 @@ void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor)  	}  } -void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ -	functor(mListener); -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->applyListenerFunctorRecursively(functor); -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		(*iit)->applyListenerFunctorRecursively(functor); -	} -} -  // LLView functionality  BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,  										   BOOL drop, @@ -2412,7 +1705,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,  {  	BOOL handled = FALSE; -	if (mIsOpen) +	if (isOpen())  	{  		handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL);  	} @@ -2434,7 +1727,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask,  													   EAcceptance* accept,  													   std::string& tooltip_msg)  { -	BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +	BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg);  	if (accepted)   	{ @@ -2458,11 +1751,8 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask,  BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask )  {  	BOOL handled = FALSE; -	// fetch contents of this folder, as context menu can depend on contents -	// still, user would have to open context menu again to see the changes -	gInventory.fetchDescendentsOf(mListener->getUUID()); -	if( mIsOpen ) +	if( isOpen() )  	{  		handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;  	} @@ -2492,7 +1782,7 @@ BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask)  BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )  {  	BOOL handled = FALSE; -	if( mIsOpen ) +	if( isOpen() )  	{  		handled = childrenHandleMouseDown(x,y,mask) != NULL;  	} @@ -2516,17 +1806,17 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )  BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )  {  	/* Disable outfit double click to wear -	const LLUUID &cat_uuid = getListener()->getUUID(); +	const LLUUID &cat_uuid = getViewModelItem()->getUUID();  	const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);  	if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)  	{ -		getListener()->performAction(NULL, NULL,"replaceoutfit"); +		getViewModelItem()->performAction(NULL, NULL,"replaceoutfit");  		return TRUE;  	}  	*/  	BOOL handled = FALSE; -	if( mIsOpen ) +	if( isOpen() )  	{  		handled = childrenHandleDoubleClick( x, y, mask ) != NULL;  	} @@ -2540,7 +1830,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )  		}  		else  		{ -			setSelectionFromRoot(this, FALSE); +			getRoot()->setSelection(this, FALSE);  			toggleOpen();  		}  		handled = TRUE; @@ -2554,7 +1844,7 @@ void LLFolderViewFolder::draw()  	{  		mControlLabelRotation = mAutoOpenCountdown * -90.f;  	} -	else if (mIsOpen) +	else if (isOpen())  	{  		mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f));  	} @@ -2563,31 +1853,10 @@ void LLFolderViewFolder::draw()  		mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f));  	} -	bool possibly_has_children = false; -	bool up_to_date = mListener && mListener->isUpToDate(); -	if(!up_to_date -		&& mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) -	{ -		possibly_has_children = true; -	} - - -	BOOL loading = (mIsOpen -					&& possibly_has_children -					&& !up_to_date ); - -	if ( loading && !mIsLoading ) -	{ -		// Measure how long we've been in the loading state -		mTimeSinceRequestStart.reset(); -	} - -	mIsLoading = loading; -  	LLFolderViewItem::draw();  	// draw children if root folder, or any other folder that is open or animating to closed state -	if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) +	if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight ))  	{  		LLView::draw();  	} @@ -2595,22 +1864,6 @@ void LLFolderViewFolder::draw()  	mExpanderHighlighted = FALSE;  } -time_t LLFolderViewFolder::getCreationDate() const -{ -	return llmax<time_t>(mCreationDate, mSubtreeCreationDate); -} - - -BOOL	LLFolderViewFolder::potentiallyVisible() -{ -	// folder should be visible by it's own filter status -	return LLFolderViewItem::potentiallyVisible() 	 -		// or one or more of its descendants have passed the minimum filter requirement -		|| hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) -		// or not all of its descendants have been checked against minimum filter requirement -		|| getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration();  -} -  // this does prefix traversal, as folders are listed above their contents  LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children )  { @@ -2822,48 +2075,35 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it  	return result;  } - -bool LLInventorySort::updateSort(U32 order) -{ -	if (order != mSortOrder) -	{ -		mSortOrder = order; -		mByDate = (order & LLInventoryFilter::SO_DATE); -		mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); -		mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); -		return true; -	} -	return false; -} - -bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const  {  	// ignore sort order for landmarks in the Favorites folder.  	// they should be always sorted as in Favorites bar. See EXT-719 -	if (a->getSortGroup() == SG_ITEM -		&& b->getSortGroup() == SG_ITEM -		&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK -		&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) -	{ - -		static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - -		LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); -		LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); - -		if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) -		{ -			// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem -			// or to LLInvFVBridge -			LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a->getListener()))->getItem(); -			LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b->getListener()))->getItem(); -			if (!aitem || !bitem) -				return false; -			S32 a_sort = aitem->getSortField(); -			S32 b_sort = bitem->getSortField(); -			return a_sort < b_sort; -		} -	} +	//TODO RN: fix sorting in favorites folder +	//if (a->getSortGroup() == SG_ITEM +	//	&& b->getSortGroup() == SG_ITEM +	//	&& a->getInventoryType() == LLInventoryType::IT_LANDMARK +	//	&& b->getInventoryType() == LLInventoryType::IT_LANDMARK) +	//{ + +	//	static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + +	//	LLUUID a_uuid = a->getParentFolder()->getUUID(); +	//	LLUUID b_uuid = b->getParentFolder()->getUUID(); + +	//	if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) +	//	{ +	//		// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem +	//		// or to LLInvFVBridge +	//		LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); +	//		LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); +	//		if (!aitem || !bitem) +	//			return false; +	//		S32 a_sort = aitem->getSortField(); +	//		S32 b_sort = bitem->getSortField(); +	//		return a_sort < b_sort; +	//	} +	//}  	// We sort by name if we aren't sorting by date  	// OR if these are folders and we are sorting folders by name. @@ -2891,7 +2131,7 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde  	if (by_name)  	{ -		S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); +		S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName());  		if (0 == compare)  		{  			return (a->getCreationDate() > b->getCreationDate()); @@ -2903,13 +2143,11 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde  	}  	else  	{ -		// BUG: This is very very slow.  The getCreationDate() is log n in number -		// of inventory items.  		time_t first_create = a->getCreationDate();  		time_t second_create = b->getCreationDate();  		if (first_create == second_create)  		{ -			return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); +			return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0);  		}  		else  		{ @@ -2917,3 +2155,4 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde  		}  	}  } + diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 3c7592046a..581ec7239e 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -30,51 +30,12 @@  #include "lldarray.h"  // *TODO: Eliminate, forward declare  #include "lluiimage.h" -class LLFontGL;  class LLFolderView; -class LLFolderViewEventListener; +class LLFolderViewModelItem;  class LLFolderViewFolder;  class LLFolderViewFunctor; -class LLFolderViewItem; -class LLFolderViewListenerFunctor; -class LLInventoryFilter; -class LLMenuGL; -class LLUIImage; -class LLViewerInventoryItem; - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{  -	SG_SYSTEM_FOLDER,  -	SG_TRASH_FOLDER,  -	SG_NORMAL_FOLDER,  -	SG_ITEM  -}; - -// *TODO: do we really need one sort object per folder? -// can we just have one of these per LLFolderView ? -class LLInventorySort -{ -public: -	LLInventorySort()  -		: mSortOrder(0), -		mByDate(false), -		mSystemToTop(false), -		mFoldersByName(false) { } - -	// Returns true if order has changed -	bool updateSort(U32 order); -	U32 getSort() { return mSortOrder; } -	bool isByDate() { return mByDate; } - -	bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); -private: -	U32  mSortOrder; -	bool mByDate; -	bool mSystemToTop; -	bool mFoldersByName; -}; +class LLFolderViewFilter; +class LLFolderViewModelInterface;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLFolderViewItem @@ -91,19 +52,16 @@ public:  	struct Params : public LLInitParam::Block<Params, LLView::Params>  	{ -		Optional<LLUIImage*>					icon; -		Optional<LLUIImage*>					icon_open;  // used for folders -		Optional<LLUIImage*>					icon_overlay;  // for links -		Optional<LLFolderView*>					root; -		Mandatory<LLFolderViewEventListener*>	listener; +		Optional<LLUIImage*>						folder_arrow_image, +													selection_image; +		Optional<LLFolderView*>						root; +		Mandatory<LLFolderViewModelItem*>			listener; -		Optional<LLUIImage*>					folder_arrow_image; -		Optional<S32>							folder_indentation; // pixels -		Optional<LLUIImage*>					selection_image; -		Optional<S32>							item_height; // pixels -		Optional<S32>							item_top_pad; // pixels +		Optional<S32>								folder_indentation, // pixels +													item_height, +													item_top_pad; -		Optional<S32>							creation_date; //UTC seconds +		Optional<time_t>							creation_date;  		Params();  	}; @@ -121,52 +79,38 @@ public:  	static const F32 FOLDER_CLOSE_TIME_CONSTANT;  	static const F32 FOLDER_OPEN_TIME_CONSTANT; -	// Mostly for debugging printout purposes. -	const std::string& getSearchableLabel() { return mSearchableLabel; } -	 -	BOOL isLoading() const { return mIsLoading; } -  private:  	BOOL						mIsSelected;  protected:  	friend class LLUICtrlFactory; -	friend class LLFolderViewEventListener; +	friend class LLFolderViewModelItem;  	LLFolderViewItem(const Params& p);  	std::string					mLabel; -	std::string					mSearchableLabel;  	S32							mLabelWidth;  	bool						mLabelWidthDirty; -	time_t						mCreationDate;  	LLFolderViewFolder*			mParentFolder; -	LLFolderViewEventListener*	mListener; +	LLFolderViewModelItem*		mViewModelItem;  	BOOL						mIsCurSelection;  	BOOL						mSelectPending;  	LLFontGL::StyleFlags		mLabelStyle;  	std::string					mLabelSuffix;  	LLUIImagePtr				mIcon; -	std::string					mStatusText;  	LLUIImagePtr				mIconOpen;  	LLUIImagePtr				mIconOverlay;  	BOOL						mHasVisibleChildren;  	S32							mIndentation;  	S32							mItemHeight; -	BOOL						mPassedFilter; -	S32							mLastFilterGeneration; -	std::string::size_type		mStringMatchOffset; + +	//TODO RN: create interface for string highlighting +	//std::string::size_type		mStringMatchOffset;  	F32							mControlLabelRotation;  	LLFolderView*				mRoot;  	BOOL						mDragAndDropTarget; -	BOOL                        mIsLoading; -	LLTimer                     mTimeSinceRequestStart; -	bool						mShowLoadStatus;  	bool						mIsMouseOverTitle; -	// helper function to change the selection from the root. -	void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); -  	// this is an internal method used for adding items to folders. A  	// no-op at this level, but reimplemented in derived classes.  	virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } @@ -174,47 +118,23 @@ protected:  	static LLFontGL* getLabelFontForStyle(U8 style); -	virtual void setCreationDate(time_t creation_date_utc)	{ mCreationDate = creation_date_utc; } -  public:  	BOOL postBuild(); -	// This function clears the currently selected item, and records -	// the specified selected item appropriately for display and use -	// in the UI. If open is TRUE, then folders are opened up along -	// the way to the selection. -	void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, -		BOOL take_keyboard_focus = TRUE); - -	// This function is called when the folder view is dirty. It's -	// implemented here but called by derived classes when folding the -	// views. -	void arrangeFromRoot(); -	void filterFromRoot( void ); -	 +	virtual void openItem( void ); +  	void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus);  	virtual ~LLFolderViewItem( void );  	// addToFolder() returns TRUE if it succeeds. FALSE otherwise -	enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; -	virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - -	virtual EInventorySortGroup getSortGroup() const; +	virtual BOOL addToFolder(LLFolderViewFolder* folder);  	// Finds width and height of this object and it's children.  Also  	// makes sure that this view and it's children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); +	virtual S32 arrange( S32* width, S32* height );  	virtual S32 getItemHeight(); -	// applies filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); - -	// updates filter serial number and optionally propagated value up to root -	S32		getLastFilterGeneration() { return mLastFilterGeneration; } - -	virtual void	dirtyFilter(); -  	// If 'selection' is 'this' then note that otherwise ignore.  	// Returns TRUE if this item ends up being selected.  	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -231,7 +151,7 @@ public:  	virtual void selectItem();  	// gets multiple-element selection -	virtual std::set<LLUUID> getSelectionList() const; +	virtual std::set<LLFolderViewItem*> getSelectionList() const;  	// Returns true is this object and all of its children can be removed (deleted by user)  	virtual BOOL isRemovable(); @@ -252,74 +172,56 @@ public:  	BOOL hasVisibleChildren() { return mHasVisibleChildren; } -	void setShowLoadStatus(bool status) { mShowLoadStatus = status; } -  	// Call through to the viewed object and return true if it can be  	// removed. Returns true if it's removed.  	//virtual BOOL removeRecursively(BOOL single_item);  	BOOL remove();  	// Build an appropriate context menu for the item.	Flags unused. -	void buildContextMenu(LLMenuGL& menu, U32 flags); +	void buildContextMenu(class LLMenuGL& menu, U32 flags);  	// This method returns the actual name of the thing being  	// viewed. This method will ask the viewed object itself.  	const std::string& getName( void ) const; -	const std::string& getSearchableLabel( void ) const; -  	// This method returns the label displayed on the view. This  	// method was primarily added to allow sorting on the folder  	// contents possible before the entire view has been constructed.  	const std::string& getLabel() const { return mLabel; } -	// Used for sorting, like getLabel() above. -	virtual time_t getCreationDate() const { return mCreationDate; }  	LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; }  	const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } +	void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } +  	LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE );  	LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); -	const LLFolderViewEventListener* getListener( void ) const { return mListener; } -	LLFolderViewEventListener* getListener( void ) { return mListener; } -	 -	// Gets the inventory item if it exists (null otherwise) -	LLViewerInventoryItem * getInventoryItem(void); +	const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } +	LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } + +	const LLFolderViewModelInterface* getFolderViewModel( void ) const; +	LLFolderViewModelInterface* getFolderViewModel( void );  	// just rename the object.  	void rename(const std::string& new_name); -	// open -	virtual void openItem( void ); -	virtual void preview(void);  	// Show children (unfortunate that this is called "open")  	virtual void setOpen(BOOL open = TRUE) {}; -  	virtual BOOL isOpen() const { return FALSE; }  	virtual LLFolderView*	getRoot(); +	virtual const LLFolderView*	getRoot() const;  	BOOL			isDescendantOf( const LLFolderViewFolder* potential_ancestor );  	S32				getIndentation() { return mIndentation; } -	virtual BOOL	potentiallyVisible(); // do we know for a fact that this item won't be displayed? -	virtual BOOL	potentiallyFiltered(); // do we know for a fact that this item has been filtered out? - -	virtual BOOL	getFiltered(); -	virtual BOOL	getFiltered(S32 filter_generation); -	virtual void	setFiltered(BOOL filtered, S32 filter_generation); - -	// change the icon -	void setIcon(LLUIImagePtr icon); +	virtual BOOL	passedFilter(S32 filter_generation = -1);  	// refresh information from the object being viewed. -	void refreshFromListener();  	virtual void refresh(); -	virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); -  	// LLView functionality  	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );  	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); @@ -343,11 +245,6 @@ private:  	static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts  }; - -// function used for sorting. -typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); - -  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLFolderViewFolder  // @@ -363,10 +260,6 @@ protected:  	friend class LLUICtrlFactory;  public: -	typedef enum e_trash -	{ -		UNKNOWN, TRASH, NOT_TRASH -	} ETrash;  	typedef std::list<LLFolderViewItem*> items_t;  	typedef std::list<LLFolderViewFolder*> folders_t; @@ -374,21 +267,16 @@ public:  protected:  	items_t mItems;  	folders_t mFolders; -	LLInventorySort	mSortFunction;  	BOOL		mIsOpen;  	BOOL		mExpanderHighlighted;  	F32			mCurHeight;  	F32			mTargetHeight;  	F32			mAutoOpenCountdown; -	time_t		mSubtreeCreationDate; -	mutable ETrash mAmTrash;  	S32			mLastArrangeGeneration;  	S32			mLastCalculatedWidth; -	S32			mCompletedFilterGeneration;  	S32			mMostFilteredDescendantGeneration;  	bool		mNeedsSort; -	bool		mPassedFolderFilter;  public:  	typedef enum e_recurse_type @@ -402,48 +290,25 @@ public:  	virtual ~LLFolderViewFolder( void ); -	virtual BOOL	potentiallyVisible(); -  	LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE );  	LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE  );  	// addToFolder() returns TRUE if it succeeds. FALSE otherwise -	virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); +	virtual BOOL addToFolder(LLFolderViewFolder* folder);  	// Finds width and height of this object and it's children.  Also  	// makes sure that this view and it's children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); +	virtual S32 arrange( S32* width, S32* height );  	BOOL needsArrange(); -	void requestSort(); -	// Returns the sort group (system, trash, folder) for this folder. -	virtual EInventorySortGroup getSortGroup() const; - -	virtual void	setCompletedFilterGeneration(S32 generation, BOOL recurse_up); -	virtual S32		getCompletedFilterGeneration() { return mCompletedFilterGeneration; } - -	BOOL hasFilteredDescendants(S32 filter_generation); -	BOOL hasFilteredDescendants(); - -	// applies filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); -	virtual void setFiltered(BOOL filtered, S32 filter_generation); -	virtual BOOL getFiltered(); -	virtual BOOL getFiltered(S32 filter_generation); - -	virtual void dirtyFilter(); -	 -	// folder-specific filtering (filter status propagates top down instead of bottom up) -	void filterFolder(LLInventoryFilter& filter); -	void setFilteredFolder(bool filtered, S32 filter_generation); -	bool getFilteredFolder(S32 filter_generation); +	bool descendantsPassedFilter(S32 filter_generation = -1);  	// Passes selection information on to children and record  	// selection information if necessary.  	// Returns TRUE if this object (or a child) ends up being selected.  	// If 'openitem' is TRUE then folders are opened up along the way to the selection. -	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); +	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE);  	// This method is used to change the selection of an item.  	// Recursively traverse all children; if 'selection' is 'this' then change @@ -469,25 +334,13 @@ public:  	//virtual BOOL removeRecursively(BOOL single_item);  	//virtual BOOL remove(); -	// remove the specified item (and any children) if -	// possible. Return TRUE if the item was deleted. -	BOOL removeItem(LLFolderViewItem* item); - -	// simply remove the view (and any children) Don't bother telling -	// the listeners. -	void removeView(LLFolderViewItem* item); -  	// extractItem() removes the specified item from the folder, but  	// doesn't delete it. -	void extractItem( LLFolderViewItem* item ); +	virtual void extractItem( LLFolderViewItem* item );  	// This function is called by a child that needs to be resorted.  	void resort(LLFolderViewItem* item); -	void setItemSortOrder(U32 ordering); -	void sortBy(U32); -	//BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); -  	void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; }  	// folders can be opened. This will usually be called by internal @@ -498,8 +351,9 @@ public:  	virtual void setOpen(BOOL openitem = TRUE);  	// Called when a child is refreshed. -	// don't rearrange child folder contents unless explicitly requested -	virtual void requestArrange(BOOL include_descendants = FALSE); +	virtual void requestArrange(); + +	virtual void requestSort();  	// internal method which doesn't update the entire view. This  	// method was written because the list iterators destroy the state @@ -519,7 +373,6 @@ public:  		std::string& tooltip_msg);  	void applyFunctorRecursively(LLFolderViewFunctor& functor); -	virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);  	// Just apply this functor to the folder's immediate children.  	void applyFunctorToChildren(LLFolderViewFunctor& functor); @@ -545,32 +398,22 @@ public:  									   std::string& tooltip_msg);  	virtual void draw(); -	time_t getCreationDate() const; -	bool isTrash() const; - -	folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); } -	folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); } +	folders_t::iterator getFoldersBegin() { return mFolders.begin(); } +	folders_t::iterator getFoldersEnd() { return mFolders.end(); }  	folders_t::size_type getFoldersCount() const { return mFolders.size(); }  	items_t::const_iterator getItemsBegin() const { return mItems.begin(); }  	items_t::const_iterator getItemsEnd() const { return mItems.end(); }  	items_t::size_type getItemsCount() const { return mItems.size(); } +  	LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse);  	void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse,  std::vector<LLFolderViewItem*>& items); -}; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewListenerFunctor -// -// This simple abstract base class can be used to applied to all -// listeners in a hierarchy. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewListenerFunctor -{  public: -	virtual ~LLFolderViewListenerFunctor() {} -	virtual void operator()(LLFolderViewEventListener* listener) = 0; +	//WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead +	template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } +	template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); }  }; +  #endif  // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp new file mode 100644 index 0000000000..92db84156e --- /dev/null +++ b/indra/newview/llfolderviewmodel.cpp @@ -0,0 +1,54 @@ +/**  + * @file llfolderviewmodel.cpp + * @brief Implementation of the view model collection of classes. + * + * $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 "llfolderviewmodel.h" +#include "lltrans.h" +#include "llviewercontrol.h" + +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ +	return item->getSortVersion() < mTargetSortVersion; +} + +std::string LLFolderViewModelCommon::getStatusText() +{ +	if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) +	{ +		return LLTrans::getString("Searching"); +	} +	else +	{ +		return getFilter()->getEmptyLookupMessage(); +	} +} + +void LLFolderViewModelCommon::filter() +{ +	getFilter()->setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); +	mFolderView->getViewModelItem()->filter(*getFilter()); +} diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h new file mode 100644 index 0000000000..8a16ec3eff --- /dev/null +++ b/indra/newview/llfolderviewmodel.h @@ -0,0 +1,365 @@ +/**  + * @file llfolderviewmodel.h + * + * $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$ + */ +#ifndef LLFOLDERVIEWEVENTLISTENER_H +#define LLFOLDERVIEWEVENTLISTENER_H + +#include "lldarray.h"	// *TODO: convert to std::vector +#include "llfoldertype.h" +#include "llfontgl.h"	// just for StyleFlags enum +#include "llfolderview.h" +#include "llfolderviewitem.h" +#include "llinventorytype.h" +#include "llpermissionsflags.h" +#include "llpointer.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ +	SG_SYSTEM_FOLDER, +	SG_TRASH_FOLDER, +	SG_NORMAL_FOLDER, +	SG_ITEM +}; + +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLUIImage; +class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; + +class LLFolderViewFilter +{ +public: +	enum EFilterModified +	{ +		FILTER_NONE,				// nothing to do, already filtered +		FILTER_RESTART,				// restart filtering from scratch +		FILTER_LESS_RESTRICTIVE,	// existing filtered items will certainly pass this filter +		FILTER_MORE_RESTRICTIVE		// if you didn't pass the previous filter, you definitely won't pass this one +	}; + +public: + +	LLFolderViewFilter() {} +	virtual ~LLFolderViewFilter() {} + +	// +-------------------------------------------------------------------+ +	// + Execution And Results +	// +-------------------------------------------------------------------+ +	virtual bool 				check(const LLFolderViewModelItem* item) = 0; +	virtual bool				check(const LLInventoryItem* item) = 0; +	virtual bool				checkFolder(const LLFolderViewModelItem* folder) const = 0; +	virtual bool				checkFolder(const LLUUID& folder_id) const = 0; + +	virtual void 				setEmptyLookupMessage(const std::string& message) = 0; +	virtual std::string			getEmptyLookupMessage() const = 0; + +	virtual bool				showAllResults() const = 0; + +	// +-------------------------------------------------------------------+ +	// + Status +	// +-------------------------------------------------------------------+ +	virtual bool 				isActive() const = 0; +	virtual bool 				isModified() const = 0; +	virtual void 				clearModified() = 0; +	virtual const std::string& 	getName() const = 0; +	virtual const std::string& 	getFilterText() = 0; +	//RN: this is public to allow system to externally force a global refilter +	virtual void 				setModified(EFilterModified behavior = FILTER_RESTART) = 0; + +	// +-------------------------------------------------------------------+ +	// + Count +	// +-------------------------------------------------------------------+ +	virtual void 				setFilterCount(S32 count) = 0; +	virtual S32 				getFilterCount() const = 0; +	virtual void 				decrementFilterCount() = 0; + +	// +-------------------------------------------------------------------+ +	// + Default +	// +-------------------------------------------------------------------+ +	virtual bool 				isDefault() const = 0; +	virtual bool 				isNotDefault() const = 0; +	virtual void 				markDefault() = 0; +	virtual void 				resetDefault() = 0; + +	// +-------------------------------------------------------------------+ +	// + Generation +	// +-------------------------------------------------------------------+ +	virtual S32 				getCurrentGeneration() const = 0; +	virtual S32 				getFirstSuccessGeneration() const = 0; +	virtual S32 				getFirstRequiredGeneration() const = 0; +}; + +class LLFolderViewModelInterface +{ +public: +	virtual void requestSortAll() = 0; + +	virtual void sort(class LLFolderViewFolder*) = 0; +	virtual void filter() = 0; + +	virtual bool contentsReady() = 0; +	virtual void setFolderView(LLFolderView* folder_view) = 0; +	virtual LLFolderViewFilter* getFilter() = 0; +	virtual const LLFolderViewFilter* getFilter() const = 0; +	virtual std::string getStatusText() = 0; +}; + +class LLFolderViewModelCommon : public LLFolderViewModelInterface +{ +public: +	LLFolderViewModelCommon() +	:	mTargetSortVersion(0), +		mFolderView(NULL) +	{} + +	virtual void requestSortAll() +	{ +		// sort everything +		mTargetSortVersion++; +	} +	virtual std::string getStatusText(); +	virtual void filter(); + +	void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + +protected: +	bool needsSort(class LLFolderViewModelItem* item); + +	S32 mTargetSortVersion; +	LLFolderView* mFolderView; + +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: +	LLFolderViewModel(){} +	virtual ~LLFolderViewModel() {} +	 +	typedef SORT_TYPE		SortType; +	typedef ITEM_TYPE		ItemType; +	typedef FOLDER_TYPE		FolderType; +	typedef FILTER_TYPE		FilterType; +	 +	virtual SortType& getSorter()					 { return mSorter; } +	virtual const SortType& getSorter() const 		 { return mSorter; } +	virtual void setSorter(const SortType& sorter) 	 { mSorter = sorter; requestSortAll(); } + +	virtual FilterType* getFilter() 				 { return &mFilter; } +	virtual const FilterType* getFilter() const		 { return &mFilter; } +	virtual void setFilter(const FilterType& filter) { mFilter = filter; } + +	// TODO RN: remove this and put all filtering logic in view model +	// add getStatusText and isFiltering() +	virtual bool contentsReady()					{ return true; } + + +	struct ViewModelCompare +	{ +		ViewModelCompare(const SortType& sorter) +		:	mSorter(sorter) +		{} +		 +		bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const +		{ +			return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); +		} + +		bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const +		{ +			return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); +		} + +		const SortType& mSorter; +	}; + +	void sort(LLFolderViewFolder* folder) +	{ +		if (needsSort(folder->getViewModelItem())) +		{ +			folder->sortFolders(ViewModelCompare(getSorter())); +			folder->sortItems(ViewModelCompare(getSorter())); +			folder->getViewModelItem()->setSortVersion(mTargetSortVersion); +			folder->requestArrange(); +		} +	} + +protected: +	SortType		mSorter; +	FilterType		mFilter; +}; + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: +	virtual ~LLFolderViewModelItem( void ) {}; + +	virtual void update() {}	//called when drawing +	virtual const std::string& getName() const = 0; +	virtual const std::string& getDisplayName() const = 0; +	virtual const std::string& getSearchableName() const = 0; + +	virtual LLPointer<LLUIImage> getIcon() const = 0; +	virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); } +	virtual LLPointer<LLUIImage> getIconOverlay() const { return NULL; } + +	virtual LLFontGL::StyleFlags getLabelStyle() const = 0; +	virtual std::string getLabelSuffix() const = 0; + +	virtual void openItem( void ) = 0; +	virtual void closeItem( void ) = 0; +	virtual void selectItem(void) = 0; + +	virtual BOOL isItemRenameable() const = 0; +	virtual BOOL renameItem(const std::string& new_name) = 0; + +	virtual BOOL isItemMovable( void ) const = 0;		// Can be moved to another folder +	virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + +	virtual BOOL isItemRemovable( void ) const = 0;		// Can be destroyed +	virtual BOOL removeItem() = 0; +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; + +	virtual BOOL isItemCopyable() const = 0; +	virtual BOOL copyToClipboard() const = 0; +	virtual BOOL cutToClipboard() const = 0; + +	virtual BOOL isClipboardPasteable() const = 0; +	virtual void pasteFromClipboard() = 0; +	virtual void pasteLinkFromClipboard() = 0; + +	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; +	 +	virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + +	virtual bool filter( LLFolderViewFilter& filter) = 0; +	virtual bool passedFilter(S32 filter_generation = -1) = 0; +	virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; +	virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; +	virtual void dirtyFilter() = 0; + +	virtual S32	getLastFilterGeneration() const = 0; + +	// This method should be called when a drag begins. returns TRUE +	// if the drag can begin, otherwise FALSE. +	virtual LLToolDragAndDrop::ESource getDragSource() const = 0; +	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; +	 +	virtual bool hasChildren() const = 0; +	virtual void addChild(LLFolderViewModelItem* child) = 0; +	virtual void removeChild(LLFolderViewModelItem* child) = 0; + +	// This method will be called to determine if a drop can be +	// performed, and will set drop to TRUE if a drop is +	// requested. Returns TRUE if a drop is possible/happened, +	// otherwise FALSE. +	virtual BOOL dragOrDrop(MASK mask, BOOL drop, +							EDragAndDropType cargo_type, +							void* cargo_data, +							std::string& tooltip_msg) = 0; + +	virtual void requestSort() = 0; +	virtual S32 getSortVersion() = 0; +	virtual void setSortVersion(S32 version) = 0; +	virtual void setParent(LLFolderViewModelItem* parent) = 0; + +protected: + +	friend class LLFolderViewItem; +	virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; + +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: +	LLFolderViewModelItemCommon() +	:	mSortVersion(-1), +		mPassedFilter(true), +		mPassedFolderFilter(true), +		mFolderViewItem(NULL), +		mLastFilterGeneration(-1), +		mMostFilteredDescendantGeneration(-1), +		mParent(NULL) +	{ +		std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); +	} + +	void requestSort() { mSortVersion = -1; } +	S32 getSortVersion() { return mSortVersion; } +	void setSortVersion(S32 version) { mSortVersion = version;} + +	S32	getLastFilterGeneration() const { return mLastFilterGeneration; } +	void dirtyFilter() +	{ +		mLastFilterGeneration = -1; + +		// bubble up dirty flag all the way to root +		if (mParent) +		{ +			mParent->dirtyFilter(); +		}	 +	} +	virtual void addChild(LLFolderViewModelItem* child)  +	{  +		mChildren.push_back(child);  +		child->setParent(this);  +	} +	virtual void removeChild(LLFolderViewModelItem* child)  +	{  +		mChildren.remove(child);  +		child->setParent(NULL);  +	} + +protected: +	virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } + +	S32						mSortVersion; +	bool					mPassedFilter; +	bool					mPassedFolderFilter; + +	S32						mLastFilterGeneration; +	S32						mMostFilteredDescendantGeneration; + + +	typedef std::list<LLFolderViewModelItem*> child_list_t; +	child_list_t			mChildren; +	LLFolderViewModelItem*	mParent; + +	void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} +	LLFolderViewItem*		mFolderViewItem; +}; + + +#endif diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp new file mode 100644 index 0000000000..7ee1a10b15 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -0,0 +1,225 @@ +/*  + * @file llfolderviewmodelinventory.cpp + * @brief Implementation of the inventory-specific view model + * + * $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 "llfolderviewmodelinventory.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" + +// +// class LLFolderViewModelInventory +// +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ +	LLFastTimer _(FTM_INVENTORY_SORT); + +	if (!needsSort(folder->getViewModelItem())) return; + +	LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); +	if (modelp->getUUID().isNull()) return; + +	for (std::list<LLFolderViewFolder*>::iterator it =   folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); +		it != end_it; +		++it) +	{ +		LLFolderViewFolder* child_folderp = *it; +		sort(child_folderp); + +		if (child_folderp->getFoldersCount() > 0) +		{ +			time_t most_recent_folder_time = +				static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); +			LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); +			if (most_recent_folder_time > modelp->getCreationDate()) +			{ +				modelp->setCreationDate(most_recent_folder_time); +			} +		} +		if (child_folderp->getItemsCount() > 0)			 +		{ +			time_t most_recent_item_time = +				static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); + +			LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); +			if (most_recent_item_time > modelp->getCreationDate()) +			{ +				modelp->setCreationDate(most_recent_item_time); +			} +		} +	} +	base_t::sort(folder); +} + +bool LLFolderViewModelInventory::contentsReady() +{ +	return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + +void LLFolderViewModelItemInventory::requestSort() +{ +	LLFolderViewModelItemCommon::requestSort(); +	if (mRootViewModel->getSorter().isByDate()) +	{ +		// sort by date potentially affects parent folders which use a date +		// derived from newest item in them +		if (mParent) +		{ +			mParent->requestSort(); +		} +	} +} + +bool LLFolderViewModelItemInventory::potentiallyVisible() +{ +	return passedFilter() // we've passed the filter +		|| getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet +		|| descendantsPassedFilter(); +} + +bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation)  +{  +	if (filter_generation < 0 && mRootViewModel)  +		filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + +	return mPassedFolderFilter  +		&& mLastFilterGeneration >= filter_generation +		&& (mPassedFilter || descendantsPassedFilter(filter_generation)); +} + +bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) +{  +	if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); +	return mMostFilteredDescendantGeneration >= filter_generation;  +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) +{ +	mPassedFilter = passed; +	mPassedFolderFilter = passed_folder; +	mLastFilterGeneration = filter_generation; +} + +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ +	bool passed_filter_before = item->passedFilter(); +	S32 filter_generation = filter.getCurrentGeneration(); +	S32 must_pass_generation = filter.getFirstRequiredGeneration(); + +	if (item->getLastFilterGeneration() < filter_generation) +	{ +		if (item->getLastFilterGeneration() >= must_pass_generation  +			&& !item->passedFilter(must_pass_generation)) +		{ +			// failed to pass an earlier filter that was a subset of the current one +			// go ahead and flag this item as done +			item->filter(filter); +			if (item->passedFilter()) +			{ +				llerrs << "Invalid shortcut in inventory filtering!" << llendl; +			} +			item->setPassedFilter(false, false, filter_generation); +		} +		else +		{ +			item->filter( filter ); +		} +	} + +	// track latest generation to pass any child items, for each folder up to root +	if (item->passedFilter()) +	{ +		LLFolderViewModelItemInventory* view_model = this; +		 +		while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) +		{ +			view_model->mMostFilteredDescendantGeneration = filter_generation; +			view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); +		} +		 +		return !passed_filter_before; +	} +	else // !item->passedfilter() +	{ +		return passed_filter_before; +	} +} + +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ +	bool changed = false; + +	if(!mChildren.empty() +		&& (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass +			|| descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement +	{ +		// now query children +		for (child_list_t::iterator iter = mChildren.begin(); +			iter != mChildren.end() && filter.getFilterCount() > 0; +			++iter) +		{ +			changed |= filterChildItem((*iter), filter); +		} +	} + +	if (changed) +	{ +		//TODO RN: ensure this still happens, but without dependency on folderview +		LLFolderViewFolder* folder = static_cast<LLFolderViewFolder*>(mFolderViewItem); +		folder->requestArrange(); +	} + +	// if we didn't use all filter iterations +	// that means we filtered all of our descendants +	// so filter ourselves now +	if (filter.getFilterCount() > 0) +	{ +		filter.decrementFilterCount(); + +		const BOOL passed_filter = filter.check(this); +		const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)  +								? filter.checkFolder(this) +								: true; + +		setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); +		//TODO RN: create interface for string highlighting +		//mStringMatchOffset = filter.getStringMatchOffset(this); +	} +	return changed; +} + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ +	return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ +	return &mInventoryViewModel; +} + diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h new file mode 100644 index 0000000000..a8fe3f57ea --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.h @@ -0,0 +1,107 @@ +/**  + * @file llfolderviewmodelinventory.h + * @brief view model implementation specific to inventory + * class definition + * + * $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$ + */ + +#ifndef LL_LLFOLDERVIEWMODELINVENTORY_H +#define LL_LLFOLDERVIEWMODELINVENTORY_H + +#include "llinventoryfilter.h" + +class LLFolderViewModelItemInventory +	:	public LLFolderViewModelItemCommon +{ +public: +	LLFolderViewModelItemInventory() +		:	mRootViewModel(NULL) +	{} +	void setRootViewModel(class LLFolderViewModelInventory* root_view_model) +	{ +		mRootViewModel = root_view_model; +	} +	virtual const LLUUID& getUUID() const = 0; +	virtual time_t getCreationDate() const = 0;	// UTC seconds +	virtual void setCreationDate(time_t creation_date_utc) = 0; +	virtual PermissionMask getPermissionMask() const = 0; +	virtual LLFolderType::EType getPreferredType() const = 0; +	virtual void showProperties(void) = 0; +	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual. +	virtual BOOL isUpToDate() const = 0; +	virtual bool hasChildren() const = 0; +	virtual LLInventoryType::EType getInventoryType() const = 0; +	virtual void performAction(LLInventoryModel* model, std::string action)   = 0; +	virtual LLWearableType::EType getWearableType() const = 0; +	virtual EInventorySortGroup getSortGroup() const = 0; +	virtual LLInventoryObject* getInventoryObject() const = 0; +	virtual void requestSort(); +	virtual bool potentiallyVisible(); +	virtual bool passedFilter(S32 filter_generation = -1); +	virtual bool descendantsPassedFilter(S32 filter_generation = -1); +	virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); +	virtual bool filter( LLFolderViewFilter& filter); +	virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); +protected: +	class LLFolderViewModelInventory* mRootViewModel; +}; + +class LLInventorySort +{ +public: +	LLInventorySort(U32 order = 0) +		:	mSortOrder(order), +		mByDate(false), +		mSystemToTop(false), +		mFoldersByName(false) +	{ +		mByDate = (order & LLInventoryFilter::SO_DATE); +		mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); +		mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); +	} + +	bool isByDate() const { return mByDate; } +	U32 getSortOrder() const { return mSortOrder; } + +	bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; +private: +	U32  mSortOrder; +	bool mByDate; +	bool mSystemToTop; +	bool mFoldersByName; +}; + +class LLFolderViewModelInventory +	:	public LLFolderViewModel<LLInventorySort,   LLFolderViewModelItemInventory, LLFolderViewModelItemInventory,   LLInventoryFilter> +{ +public: +	typedef LLFolderViewModel<LLInventorySort,   LLFolderViewModelItemInventory, LLFolderViewModelItemInventory,   LLInventoryFilter> base_t; + +	virtual ~LLFolderViewModelInventory() {} + +	void sort(LLFolderViewFolder* folder); + +	bool contentsReady(); + +}; +#endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 11401d6c68..a64ddd185d 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -47,13 +47,13 @@ static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All";  // helper functions  // NOTE: For now Friends & All folders are created as protected folders of the LLFolderType::FT_CALLINGCARD type. -// So, their names will be processed in the LLFolderViewItem::refreshFromListener() to be localized +// So, their names will be processed in the LLFolderViewItem::refresh() to be localized  // using "InvFolder LABEL_NAME" as LLTrans::findString argument.  // We must use in this file their hard-coded names to ensure found them on different locales. EXT-5829.  // These hard-coded names will be stored in InventoryItems but shown localized in FolderViewItems -// If hack in the LLFolderViewItem::refreshFromListener() to localize protected folder is removed +// If hack in the LLFolderViewItem::refresh() to localize protected folder is removed  // or these folders are not protected these names should be localized in another place/way.  inline const std::string get_friend_folder_name()  { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b86c453d61..002278601a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -37,6 +37,7 @@  #include "llappearancemgr.h"  #include "llattachmentsmgr.h"  #include "llavataractions.h"  +#include "llfavoritesbar.h" // management of favorites folder  #include "llfloateropenobject.h"  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h" @@ -115,10 +116,10 @@ void teleport_via_landmark(const LLUUID& asset_id);  static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);  static bool check_category(LLInventoryModel* model,  						   const LLUUID& cat_id, -						   LLFolderView* active_folder_view, +						   LLInventoryPanel* active_panel,  						   LLInventoryFilter* filter);  static bool check_item(const LLUUID& item_id, -					   LLFolderView* active_folder_view, +					   LLInventoryPanel* active_panel,  					   LLInventoryFilter* filter);  // Helper functions @@ -208,7 +209,11 @@ const std::string& LLInvFVBridge::getName() const  const std::string& LLInvFVBridge::getDisplayName() const  { -	return getName(); +	if(mDisplayName.empty()) +	{ +		buildDisplayName(); +	} +	return mDisplayName;  }  // Folders have full perms @@ -227,9 +232,24 @@ LLFolderType::EType LLInvFVBridge::getPreferredType() const  // Folders don't have creation dates.  time_t LLInvFVBridge::getCreationDate() const  { -	return 0; +	LLInventoryObject* objectp = getInventoryObject(); +	if (objectp) +	{ +		return objectp->getCreationDate(); +	} +	return (time_t)0; +} + +void LLInvFVBridge::setCreationDate(time_t creation_date_utc) +{ +	LLInventoryObject* objectp = getInventoryObject(); +	if (objectp) +	{ +		objectp->setCreationDate(creation_date_utc); +	}  } +  // Can be destroyed (or moved to trash)  BOOL LLInvFVBridge::isItemRemovable() const  { @@ -283,7 +303,7 @@ void LLInvFVBridge::showProperties()  	*/  } -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)  {  	// Deactivate gestures when moving them into Trash  	LLInvFVBridge* bridge; @@ -292,11 +312,11 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	LLViewerInventoryCategory* cat = NULL;  	LLInventoryModel::cat_array_t	descendent_categories;  	LLInventoryModel::item_array_t	descendent_items; -	S32 count = batch.count(); +	S32 count = batch.size();  	S32 i,j;  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if (item) @@ -309,7 +329,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	}  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());  		if (cat) @@ -327,7 +347,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	removeBatchNoCheck(batch);  } -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) +void  LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>&  batch)  {  	// this method moves a bunch of items and folders to the trash. As  	// per design guidelines for the inventory model, the message is @@ -343,14 +363,14 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	uuid_vec_t move_ids;  	LLInventoryModel::update_map_t update;  	bool start_new_message = true; -	S32 count = batch.count(); +	S32 count = batch.size();  	S32 i;  	// first, hide any 'preview' floaters that correspond to the items  	// being deleted.  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if(item) @@ -363,7 +383,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if(item) @@ -404,7 +424,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());  		if(cat) @@ -876,6 +896,12 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const  	return panel ? panel->getModel() : NULL;  } +LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const +{ +	LLInventoryPanel* panel = mInventoryPanel.get(); +	return panel ? panel->getFilter() : NULL; +} +  BOOL LLInvFVBridge::isItemInTrash() const  {  	LLInventoryModel* model = getInventoryModel(); @@ -1000,6 +1026,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  										   LLAssetType::EType actual_asset_type,  										   LLInventoryType::EType inv_type,  										   LLInventoryPanel* inventory, +										   LLFolderViewModelInventory* view_model,  										   LLFolderView* root,  										   const LLUUID& uuid,  										   U32 flags) @@ -1125,12 +1152,13 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  		default:  			llinfos << "Unhandled asset type (llassetstorage.h): "  					<< (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << llendl; -			break; +			break;	  	}  	if (new_listener)  	{  		new_listener->mInvType = inv_type; +		new_listener->setRootViewModel(view_model);  	}  	return new_listener; @@ -1250,10 +1278,10 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  		if (can_list)  		{ -			LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id); +			LLFolderViewFolder * object_folderp =   mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL;  			if (object_folderp)  			{ -				can_list = !object_folderp->isLoading(); +				can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading();  			}  		} @@ -1261,7 +1289,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  		{  			// Get outbox id  			const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); -			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); +			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL;  			if (outbox_itemp)  			{ @@ -1271,7 +1299,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  				void * cargo_data = (void *) obj;  				std::string tooltip_msg; -				can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +				can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);  			}  		}  	} @@ -1283,6 +1311,21 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  #endif  } +LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const +{ +	if (gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID())) +	{ +		return LLToolDragAndDrop::SOURCE_AGENT; +	} +	else if (gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID())) +	{ +		return LLToolDragAndDrop::SOURCE_LIBRARY; +	} + +	return LLToolDragAndDrop::SOURCE_VIEWER; +} + +  // +=================================================+  // |        InventoryFVBridgeBuilder                 | @@ -1291,6 +1334,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset  														LLAssetType::EType actual_asset_type,  														LLInventoryType::EType inv_type,  														LLInventoryPanel* inventory, +														LLFolderViewModelInventory* view_model,  														LLFolderView* root,  														const LLUUID& uuid,  														U32 flags /* = 0x00 */) const @@ -1299,6 +1343,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset  									   actual_asset_type,  									   inv_type,  									   inventory, +									   view_model,  									   root,  									   uuid,  									   flags); @@ -1368,10 +1413,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); +		LLFolderViewItem* folder_view_itemp =   mInventoryPanel.get()->getItemByID(itemp->getParentUUID());  		if (!folder_view_itemp) return; -		folder_view_itemp->getListener()->pasteFromClipboard(); +		folder_view_itemp->getViewModelItem()->pasteFromClipboard();  		return;  	}  	else if ("paste_link" == action) @@ -1380,10 +1425,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); +		LLFolderViewItem* folder_view_itemp =   mInventoryPanel.get()->getItemByID(itemp->getParentUUID());  		if (!folder_view_itemp) return; -		folder_view_itemp->getListener()->pasteLinkFromClipboard(); +		folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();  		return;  	}  	else if (isMarketplaceCopyAction(action)) @@ -1494,25 +1539,20 @@ PermissionMask LLItemBridge::getPermissionMask() const  	return perm_mask;  } -const std::string& LLItemBridge::getDisplayName() const -{ -	if(mDisplayName.empty()) -	{ -		buildDisplayName(getItem(), mDisplayName); -	} -	return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +void LLItemBridge::buildDisplayName() const  { -	if(item) +	if(getItem())  	{ -		name.assign(item->getName()); +		mDisplayName.assign(getItem()->getName());  	}  	else  	{ -		name.assign(LLStringUtil::null); +		mDisplayName.assign(LLStringUtil::null);  	} + +	mSearchableName.assign(mDisplayName); +	mSearchableName.append(getLabelSuffix()); +	LLStringUtil::toUpper(mSearchableName);  }  LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const @@ -1629,11 +1669,11 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)  	{  		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);  		new_item->rename(new_name); -		buildDisplayName(new_item, mDisplayName);  		new_item->updateServer(FALSE);  		model->updateItem(new_item);  		model->notifyObservers(); +		buildDisplayName();  	}  	// return FALSE because we either notified observers (& therefore  	// rebuilt) or we didn't update. @@ -1786,6 +1826,93 @@ void LLFolderBridge::selectItem()  	LLInventoryModelBackgroundFetch::instance().start(getUUID(), true);  } +void LLFolderBridge::buildDisplayName() const +{ +	LLFolderType::EType preferred_type = getPreferredType(); + +	// *TODO: to be removed when database supports multi language. This is a +	// temporary attempt to display the inventory folder in the user locale. +	// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID +	//		it uses the same way to find localized string + +	// HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) +	// Translation of Accessories folder in Library inventory folder +	bool accessories = false; +	if(getName() == "Accessories") +	{ +		//To ensure that Accessories folder is in Library we have to check its parent folder. +		//Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model +		LLInventoryCategory* cat = gInventory.getCategory(getUUID()); +		if(cat) +		{ +			const LLUUID& parent_folder_id = cat->getParentUUID(); +			accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); +		} +	} + +	//"Accessories" inventory category has folder type FT_NONE. So, this folder +	//can not be detected as protected with LLFolderType::lookupIsProtectedType +	mDisplayName.assign(getName()); +	if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) +	{ +		LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); +	} + +	mSearchableName.assign(mDisplayName); +	mSearchableName.append(getLabelSuffix()); +	LLStringUtil::toUpper(mSearchableName); +} + + +void LLFolderBridge::update() +{ +	bool possibly_has_children = false; +	bool up_to_date = isUpToDate(); +	if(!up_to_date && hasChildren()) // we know we have children but  haven't  fetched them (doesn't obey filter) +	{ +		possibly_has_children = true; +	} + +	bool loading = (possibly_has_children +		&& !up_to_date ); + +	if (loading != mIsLoading) +	{ +		if ( loading && !mIsLoading ) +		{ +			// Measure how long we've been in the loading state +			mTimeSinceRequestStart.reset(); +		} + +		const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID()); +		const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID()); + +		bool root_is_loading = false; +		if (in_inventory) +		{ +			root_is_loading =   LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); +		} +		if (in_library) +		{ +			root_is_loading =   LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); +		} +		if ((mIsLoading +				&&	mTimeSinceRequestStart.getElapsedTimeF32() >=   gSavedSettings.getF32("FolderLoadingMessageWaitTime")) +			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive() +				&&	root_is_loading)) +		{ +			mDisplayName = LLInvFVBridge::getDisplayName() + " ( " +   LLTrans::getString("LoadingData") + " ) "; +			mIsLoading = true; +		} +		else +		{ +			mDisplayName = LLInvFVBridge::getDisplayName(); +			mIsLoading = false; +		} +	} +} + +  // Iterate through a folder's children to determine if  // all the children are removable.  class LLIsItemRemovable : public LLFolderViewFunctor @@ -1794,11 +1921,11 @@ public:  	LLIsItemRemovable() : mPassed(TRUE) {}  	virtual void doFolder(LLFolderViewFolder* folder)  	{ -		mPassed &= folder->getListener()->isItemRemovable(); +		mPassed &= folder->getViewModelItem()->isItemRemovable();  	}  	virtual void doItem(LLFolderViewItem* item)  	{ -		mPassed &= item->getListener()->isItemRemovable(); +		mPassed &= item->getViewModelItem()->isItemRemovable();  	}  	BOOL mPassed;  }; @@ -1812,7 +1939,7 @@ BOOL LLFolderBridge::isItemRemovable() const  	}  	LLInventoryPanel* panel = mInventoryPanel.get(); -	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); +	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ?   panel->getItemByID(mUUID) : NULL);  	if (folderp)  	{  		LLIsItemRemovable folder_test; @@ -2051,7 +2178,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  	LLInventoryPanel* destination_panel = mInventoryPanel.get();  	if (!destination_panel) return false; -	LLInventoryFilter* filter = destination_panel->getFilter(); +	LLInventoryFilter* filter = getInventoryFilter();  	if (!filter) return false;  	const LLUUID &cat_id = inv_cat->getUUID(); @@ -2270,7 +2397,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  				{  					// Check whether the folder being dragged from active inventory panel  					// passes the filter of the destination panel. -					is_movable = check_category(model, cat_id, active_folder_view, filter); +					is_movable = check_category(model, cat_id, active_panel, filter);  				}  			}  		} @@ -2696,7 +2823,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  {  	if ("open" == action)  	{ -		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mRoot->getItemByID(mUUID)); +		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder   *>(mInventoryPanel.get()->getItemByID(mUUID));  		if (f)  		{  			f->setOpen(TRUE); @@ -2880,17 +3007,24 @@ LLUIImagePtr LLFolderBridge::getIcon() const  LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)  {  	return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); -		/*case LLAssetType::AT_MESH: -			control = "inv_folder_mesh.tga"; -			break;*/  } -LLUIImagePtr LLFolderBridge::getOpenIcon() const +LLUIImagePtr LLFolderBridge::getIconOpen() const  {  	return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));  } +LLUIImagePtr LLFolderBridge::getIconOverlay() const +{ +	if (getInventoryObject() && getInventoryObject()->getIsLinkType()) +	{ +		return LLUI::getUIImage("Inv_Link"); +	} +	return NULL; +} + +  BOOL LLFolderBridge::renameItem(const std::string& new_name)  {  	rename_category(getInventoryModel(), mUUID, new_name); @@ -2971,7 +3105,7 @@ void LLFolderBridge::pasteFromClipboard()  		if (move_is_into_outbox)  		{ -			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); +			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get()->getItemByID(mUUID);  			if (outbox_itemp)  			{ @@ -2994,7 +3128,7 @@ void LLFolderBridge::pasteFromClipboard()  						void * cargo_data = (void *) item;  						std::string tooltip_msg; -						can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +						can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);  					}  				} @@ -3166,7 +3300,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv  	return ((item_array.count() > 0) ? TRUE : FALSE );  } -void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) +void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items, menuentry_vec_t& disabled_items)  {  	LLInventoryModel* model = getInventoryModel();  	llassert(model != NULL); @@ -3177,30 +3311,30 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  	if (lost_and_found_id == mUUID)  	{  		// This is the lost+found folder. -		mItems.push_back(std::string("Empty Lost And Found")); +		items.push_back(std::string("Empty Lost And Found")); -		mDisabledItems.push_back(std::string("New Folder")); -		mDisabledItems.push_back(std::string("New Script")); -		mDisabledItems.push_back(std::string("New Note")); -		mDisabledItems.push_back(std::string("New Gesture")); -		mDisabledItems.push_back(std::string("New Clothes")); -		mDisabledItems.push_back(std::string("New Body Parts")); +		disabled_items.push_back(std::string("New Folder")); +		disabled_items.push_back(std::string("New Script")); +		disabled_items.push_back(std::string("New Note")); +		disabled_items.push_back(std::string("New Gesture")); +		disabled_items.push_back(std::string("New Clothes")); +		disabled_items.push_back(std::string("New Body Parts"));  	}  	if(trash_id == mUUID)  	{  		// This is the trash. -		mItems.push_back(std::string("Empty Trash")); +		items.push_back(std::string("Empty Trash"));  	}  	else if(isItemInTrash())  	{  		// This is a folder in the trash. -		mItems.clear(); // clear any items that used to exist -		addTrashContextMenuOptions(mItems, mDisabledItems); +		items.clear(); // clear any items that used to exist +		addTrashContextMenuOptions(items, disabled_items);  	}  	else if(isOutboxFolder())  	{ -		addOutboxContextMenuOptions(flags, mItems, mDisabledItems); +		addOutboxContextMenuOptions(flags, items, disabled_items);  	}  	else if(isAgentInventory()) // do not allow creating in library  	{ @@ -3214,40 +3348,40 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.  				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))  				{ -					mItems.push_back(std::string("New Folder")); +					items.push_back(std::string("New Folder"));  				} -				mItems.push_back(std::string("New Script")); -				mItems.push_back(std::string("New Note")); -				mItems.push_back(std::string("New Gesture")); -				mItems.push_back(std::string("New Clothes")); -				mItems.push_back(std::string("New Body Parts")); +				items.push_back(std::string("New Script")); +				items.push_back(std::string("New Note")); +				items.push_back(std::string("New Gesture")); +				items.push_back(std::string("New Clothes")); +				items.push_back(std::string("New Body Parts"));  			}  #if SUPPORT_ENSEMBLES  			// Changing folder types is an unfinished unsupported feature  			// and can lead to unexpected behavior if enabled. -			mItems.push_back(std::string("Change Type")); +			items.push_back(std::string("Change Type"));  			const LLViewerInventoryCategory *cat = getCategory();  			if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))  			{ -				mDisabledItems.push_back(std::string("Change Type")); +				disabled_items.push_back(std::string("Change Type"));  			}  #endif -			getClipboardEntries(false, mItems, mDisabledItems, flags); +			getClipboardEntries(false, items, disabled_items, flags);  		}  		else  		{  			// Want some but not all of the items from getClipboardEntries for outfits.  			if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))  			{ -				mItems.push_back(std::string("Rename")); +				items.push_back(std::string("Rename")); -				addDeleteContextMenuOptions(mItems, mDisabledItems); +				addDeleteContextMenuOptions(items, disabled_items);  				// EXT-4030: disallow deletion of currently worn outfit  				const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();  				if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))  				{ -					mDisabledItems.push_back(std::string("Delete")); +					disabled_items.push_back(std::string("Delete"));  				}  			}  		} @@ -3276,20 +3410,44 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  	// Preemptively disable system folder removal if more than one item selected.  	if ((flags & FIRST_SELECTED_ITEM) == 0)  	{ -		mDisabledItems.push_back(std::string("Delete System Folder")); +		disabled_items.push_back(std::string("Delete System Folder"));  	}  	if (!isOutboxFolder())  	{ -		mItems.push_back(std::string("Share")); +		items.push_back(std::string("Share"));  		if (!canShare())  		{ -			mDisabledItems.push_back(std::string("Share")); +			disabled_items.push_back(std::string("Share")); +		} +	} +	// Add menu items that are dependent on the contents of the folder. +	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); +	if (category) +	{ +		uuid_vec_t folders; +		folders.push_back(category->getUUID()); + +		sSelf = getHandle(); +		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); +		fetch->startFetch(); +		if (fetch->isFinished()) +		{ +			// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down  +			// This saves lots of time as buildContextMenu() is called a lot +			delete fetch; +			buildContextMenuFolderOptions(flags, items, disabled_items); +		} +		else +		{ +			// it's all on its way - add an observer, and the inventory will call done for us when everything is here. +			inc_busy_count(); +			gInventory.addObserver(fetch);  		}  	}  } -void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) +void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t& items, menuentry_vec_t& disabled_items)  {  	// Build folder specific options back up  	LLInventoryModel* model = getInventoryModel(); @@ -3316,21 +3474,21 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  		LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);  		if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))  		{ -			mItems.push_back(std::string("Calling Card Separator")); -			mItems.push_back(std::string("Conference Chat Folder")); -			mItems.push_back(std::string("IM All Contacts In Folder")); +			items.push_back(std::string("Calling Card Separator")); +			items.push_back(std::string("Conference Chat Folder")); +			items.push_back(std::string("IM All Contacts In Folder"));  		}  	}  	if (!isItemRemovable())  	{ -		mDisabledItems.push_back(std::string("Delete")); +		disabled_items.push_back(std::string("Delete"));  	}  #ifndef LL_RELEASE_FOR_DOWNLOAD  	if (LLFolderType::lookupIsProtectedType(type))  	{ -		mItems.push_back(std::string("Delete System Folder")); +		items.push_back(std::string("Delete System Folder"));  	}  #endif @@ -3345,7 +3503,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  		checkFolderForContentsOfType(model, is_object) ||  		checkFolderForContentsOfType(model, is_gesture) )  	{ -		mItems.push_back(std::string("Folder Wearables Separator")); +		items.push_back(std::string("Folder Wearables Separator"));  		// Only enable add/replace outfit for non-system folders.  		if (!is_system_folder) @@ -3353,25 +3511,25 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  			// Adding an outfit onto another (versus replacing) doesn't make sense.  			if (type != LLFolderType::FT_OUTFIT)  			{ -				mItems.push_back(std::string("Add To Outfit")); +				items.push_back(std::string("Add To Outfit"));  			} -			mItems.push_back(std::string("Replace Outfit")); +			items.push_back(std::string("Replace Outfit"));  		}  		if (is_ensemble)  		{ -			mItems.push_back(std::string("Wear As Ensemble")); +			items.push_back(std::string("Wear As Ensemble"));  		} -		mItems.push_back(std::string("Remove From Outfit")); +		items.push_back(std::string("Remove From Outfit"));  		if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))  		{ -			mDisabledItems.push_back(std::string("Remove From Outfit")); +			disabled_items.push_back(std::string("Remove From Outfit"));  		}  		if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))  		{ -			mDisabledItems.push_back(std::string("Replace Outfit")); +			disabled_items.push_back(std::string("Replace Outfit"));  		} -		mItems.push_back(std::string("Outfit Separator")); +		items.push_back(std::string("Outfit Separator"));  	}  } @@ -3380,49 +3538,28 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  {  	sSelf.markDead(); -	mItems.clear(); -	mDisabledItems.clear(); +	// fetch contents of this folder, as context menu can depend on contents +	// still, user would have to open context menu again to see the changes +	gInventory.fetchDescendentsOf(getUUID()); + + +	menuentry_vec_t items; +	menuentry_vec_t disabled_items;  	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;  	LLInventoryModel* model = getInventoryModel();  	if(!model) return; -	buildContextMenuBaseOptions(flags); - -	// Add menu items that are dependent on the contents of the folder. -	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); -	if (category) -	{ -		uuid_vec_t folders; -		folders.push_back(category->getUUID()); - -		sSelf = getHandle(); -		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); -		fetch->startFetch(); -		if (fetch->isFinished()) -		{ -			// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down  -			// This saves lots of time as buildContextMenu() is called a lot -			delete fetch; -			buildContextMenuFolderOptions(flags); -		} -		else -		{ -			// it's all on its way - add an observer, and the inventory will call done for us when everything is here. -			inc_busy_count(); -			gInventory.addObserver(fetch); -		} -	} - -	hide_context_entries(menu, mItems, mDisabledItems); +	buildContextMenuOptions(flags, items, disabled_items); +        hide_context_entries(menu, items, disabled_items);  	// Reposition the menu, in case we're adding items to an existing menu.  	menu.needsArrange();  	menu.arrangeAndClear();  } -BOOL LLFolderBridge::hasChildren() const +bool LLFolderBridge::hasChildren() const  {  	LLInventoryModel* model = getInventoryModel();  	if(!model) return FALSE; @@ -3512,25 +3649,6 @@ void LLFolderBridge::pasteClipboard(void* user_data)  	if(self) self->pasteFromClipboard();  } -void LLFolderBridge::createNewCategory(void* user_data) -{ -	LLFolderBridge* bridge = (LLFolderBridge*)user_data; -	if(!bridge) return; -	LLInventoryPanel* panel = bridge->mInventoryPanel.get(); -	if (!panel) return; -	LLInventoryModel* model = panel->getModel(); -	if(!model) return; -	LLUUID id; -	id = model->createNewCategory(bridge->getUUID(), -								  LLFolderType::FT_NONE, -								  LLStringUtil::null); -	model->notifyObservers(); - -	// At this point, the bridge has probably been deleted, but the -	// view is still there. -	panel->setSelection(id, TAKE_FOCUS_YES); -} -  void LLFolderBridge::createNewShirt(void* user_data)  {  	LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT); @@ -3596,6 +3714,24 @@ void LLFolderBridge::createNewEyes(void* user_data)  	LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES);  } +EInventorySortGroup LLFolderBridge::getSortGroup() const +{ +	LLFolderType::EType preferred_type = getPreferredType(); + +	if (preferred_type == LLFolderType::FT_TRASH) +	{ +		return SG_TRASH_FOLDER; +	} + +	if(LLFolderType::lookupIsProtectedType(preferred_type)) +	{ +		return SG_SYSTEM_FOLDER; +	} + +	return SG_NORMAL_FOLDER; +} + +  // static  void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type)  { @@ -3698,9 +3834,10 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)  	LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();  	LLInventoryPanel* panel = mInventoryPanel.get();  	LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; -	if (drag_over_item && drag_over_item->getListener()) +	LLFolderViewModelItemInventory* view_model = drag_over_item ? static_cast<LLFolderViewModelItemInventory*>(drag_over_item->getViewModelItem()) : NULL; +	if (view_model)  	{ -		cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); +		cb.get()->setTargetLandmarkId(view_model->getUUID());  	}  	copy_inventory_item( @@ -3749,7 +3886,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  	LLInventoryPanel* destination_panel = mInventoryPanel.get();  	if (!destination_panel) return false; -	LLInventoryFilter* filter = destination_panel->getFilter(); +	LLInventoryFilter* filter = getInventoryFilter();  	if (!filter) return false;  	const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3866,13 +4003,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  		// passes the filter of the destination panel.  		if (accept && active_panel)  		{ -			LLFolderView* active_folder_view = active_panel->getRootFolder(); -			if (!active_folder_view) return false; - -			LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +			LLFolderViewItem* fv_item =   active_panel->getItemByID(inv_item->getUUID());  			if (!fv_item) return false; -			accept = filter->check(fv_item); +			accept = filter->check(fv_item->getViewModelItem());  		}  		if (accept && drop) @@ -3884,6 +4018,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			}  			// If an item is being dragged between windows, unselect everything in the active window   			// so that we don't follow the selection to its new location (which is very annoying). +                        // RN: a better solution would be to deselect automatically when an   item is moved +			// and then select any item that is dropped only in the panel that it   is dropped in  			if (active_panel && (destination_panel != active_panel))  				{  					active_panel->unSelectAll(); @@ -3901,8 +4037,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  				if (itemp)  				{  					LLUUID srcItemId = inv_item->getUUID(); -					LLUUID destItemId = itemp->getListener()->getUUID(); -					gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); +					LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID(); +					LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId);  				}  			} @@ -4089,13 +4225,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			// passes the filter of the destination panel.  			if (accept && active_panel)  			{ -				LLFolderView* active_folder_view = active_panel->getRootFolder(); -				if (!active_folder_view) return false; - -				LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +				LLFolderViewItem* fv_item =   active_panel->getItemByID(inv_item->getUUID());  				if (!fv_item) return false; -				accept = filter->check(fv_item); +				accept = filter->check(fv_item->getViewModelItem());  			}  			if (accept && drop) @@ -4135,10 +4268,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  // static  bool check_category(LLInventoryModel* model,  					const LLUUID& cat_id, -					LLFolderView* active_folder_view, +					LLInventoryPanel* active_panel,  					LLInventoryFilter* filter)  { -	if (!model || !active_folder_view || !filter) +	if (!model || !active_panel || !filter)  		return false;  	if (!filter->checkFolder(cat_id)) @@ -4158,13 +4291,13 @@ bool check_category(LLInventoryModel* model,  		// Empty folder should be checked as any other folder view item.  		// If we are filtering by date the folder should not pass because  		// it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). -		return check_item(cat_id, active_folder_view, filter); +		return check_item(cat_id, active_panel, filter);  	}  	for (S32 i = 0; i < num_descendent_categories; ++i)  	{  		LLInventoryCategory* category = descendent_categories[i]; -		if(!check_category(model, category->getUUID(), active_folder_view, filter)) +		if(!check_category(model, category->getUUID(), active_panel, filter))  		{  			return false;  		} @@ -4173,7 +4306,7 @@ bool check_category(LLInventoryModel* model,  	for (S32 i = 0; i < num_descendent_items; ++i)  	{  		LLViewerInventoryItem* item = descendent_items[i]; -		if(!check_item(item->getUUID(), active_folder_view, filter)) +		if(!check_item(item->getUUID(), active_panel, filter))  		{  			return false;  		} @@ -4184,15 +4317,15 @@ bool check_category(LLInventoryModel* model,  // static  bool check_item(const LLUUID& item_id, -				LLFolderView* active_folder_view, +				LLInventoryPanel* active_panel,  				LLInventoryFilter* filter)  { -	if (!active_folder_view || !filter) return false; +	if (!active_panel || !filter) return false; -	LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); +	LLFolderViewItem* fv_item = active_panel->getItemByID(item_id);  	if (!fv_item) return false; -	return filter->check(fv_item); +	return filter->check(fv_item->getViewModelItem());  }  // +=================================================+ @@ -4294,15 +4427,6 @@ void LLSoundBridge::openItem()  	}  } -void LLSoundBridge::previewItem() -{ -	LLViewerInventoryItem* item = getItem(); -	if(item) -	{ -		send_sound_trigger(item->getAssetUUID(), 1.0); -	} -} -  void LLSoundBridge::openSoundPreview(void* which)  {  	LLSoundBridge *me = (LLSoundBridge *)which; @@ -4518,7 +4642,7 @@ LLCallingCardBridge::~LLCallingCardBridge()  void LLCallingCardBridge::refreshFolderViewItem()  {  	LLInventoryPanel* panel = mInventoryPanel.get(); -	LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; +	LLFolderViewItem* itemp = panel ? panel->getItemByID(mUUID) : NULL;  	if (itemp)  	{  		itemp->refresh(); @@ -5309,11 +5433,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)  	{  		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);  		new_item->rename(new_name); -		buildDisplayName(new_item, mDisplayName);  		new_item->updateServer(FALSE);  		model->updateItem(new_item); -  		model->notifyObservers(); +		buildDisplayName();  		if (isAgentAvatarValid())  		{ @@ -5913,16 +6036,6 @@ void LLMeshBridge::openItem()  	}  } -void LLMeshBridge::previewItem() -{ -	LLViewerInventoryItem* item = getItem(); -	if(item) -	{ -		// preview mesh -	} -} - -  void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  {  	lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; @@ -6011,14 +6124,15 @@ void LLLinkFolderBridge::gotoItem()  	const LLUUID &cat_uuid = getFolderID();  	if (!cat_uuid.isNull())  	{ -		if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) +		LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid); +		if (base_folder)  		{  			if (LLInventoryModel* model = getInventoryModel())  			{  				model->fetchDescendentsOf(cat_uuid);  			}  			base_folder->setOpen(TRUE); -			mRoot->setSelectionFromRoot(base_folder,TRUE); +			mRoot->setSelection(base_folder,TRUE);  			mRoot->scrollToShowSelection();  		}  	} @@ -6349,9 +6463,8 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_  /************************************************************************/  void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  { -	LLFolderBridge::buildContextMenu(menu, flags); - -	menuentry_vec_t disabled_items, items = getMenuItems(); +	menuentry_vec_t disabled_items, items; +        buildContextMenuOptions(flags, items, disabled_items);  	items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); @@ -6363,42 +6476,30 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(  	LLAssetType::EType actual_asset_type,  	LLInventoryType::EType inv_type,  	LLInventoryPanel* inventory, +	LLFolderViewModelInventory* view_model,  	LLFolderView* root,  	const LLUUID& uuid,  	U32 flags /*= 0x00*/ ) const  {  	LLInvFVBridge* new_listener = NULL; -	switch(asset_type) +	if (asset_type == LLAssetType::AT_CATEGORY  +		&& actual_asset_type != LLAssetType::AT_LINK_FOLDER)  	{ -	case LLAssetType::AT_CATEGORY: -		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) -		{ -			// *TODO: Create a link folder handler instead if it is necessary -			new_listener = LLInventoryFVBridgeBuilder::createBridge( -				asset_type, -				actual_asset_type, -				inv_type, -				inventory, -				root, -				uuid, -				flags); -			break; -		}  		new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); -		break; -	default: -		new_listener = LLInventoryFVBridgeBuilder::createBridge( -			asset_type, -			actual_asset_type, -			inv_type, -			inventory, -			root, -			uuid, -			flags); +		new_listener->setRootViewModel(view_model); +	} +	else +	{ +		new_listener = LLInventoryFVBridgeBuilder::createBridge(asset_type, +																actual_asset_type, +																inv_type, +																inventory, +																view_model, +																root, +																uuid, +																flags);  	}  	return new_listener; -  } -  // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index dc9e88d54d..e235d9cf5f 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -29,9 +29,10 @@  #include "llcallingcard.h"  #include "llfloaterproperties.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llinventorymodel.h"  #include "llinventoryobserver.h" +#include "llinventorypanel.h"  #include "llviewercontrol.h"  #include "llwearable.h" @@ -41,7 +42,7 @@ class LLInventoryModel;  class LLMenuGL;  class LLCallingCardObserver;  class LLViewerJointAttachment; - +class LLFolderView;  typedef std::vector<std::string> menuentry_vec_t; @@ -56,7 +57,7 @@ typedef std::vector<std::string> menuentry_vec_t;  // functionality a bit. (except for folders, you can create those  // manually...)  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInvFVBridge : public LLFolderViewEventListener +class LLInvFVBridge : public LLFolderViewModelItemInventory  {  public:  	// This method is a convenience function which creates the correct @@ -65,6 +66,7 @@ public:  									   LLAssetType::EType actual_asset_type,  									   LLInventoryType::EType inv_type,  									   LLInventoryPanel* inventory, +									   LLFolderViewModelInventory* view_model,  									   LLFolderView* root,  									   const LLUUID& uuid,  									   U32 flags = 0x00); @@ -83,18 +85,20 @@ public:  	virtual void restoreToWorld() {}  	//-------------------------------------------------------------------- -	// Inherited LLFolderViewEventListener functions +	// Inherited LLFolderViewModelItemInventory functions  	//--------------------------------------------------------------------  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const; +	const std::string& getSearchableName() const { return mSearchableName; } +  	virtual PermissionMask getPermissionMask() const;  	virtual LLFolderType::EType getPreferredType() const;  	virtual time_t getCreationDate() const; +        virtual void setCreationDate(time_t creation_date_utc);  	virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }  	virtual std::string getLabelSuffix() const { return LLStringUtil::null; }  	virtual void openItem() {}  	virtual void closeItem() {} -	virtual void previewItem() {openItem();}  	virtual void showProperties();  	virtual BOOL isItemRenameable() const { return TRUE; }  	//virtual BOOL renameItem(const std::string& new_name) {} @@ -103,8 +107,8 @@ public:  	virtual BOOL isItemInTrash() const;  	virtual BOOL isLink() const;  	//virtual BOOL removeItem() = 0; -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); -	virtual void move(LLFolderViewEventListener* new_parent_bridge) {} +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); +	virtual void move(LLFolderViewModelItem* new_parent_bridge) {}  	virtual BOOL isItemCopyable() const { return FALSE; }  	virtual BOOL copyToClipboard() const;  	virtual BOOL cutToClipboard() const; @@ -115,6 +119,7 @@ public:  	void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items,   							 menuentry_vec_t &disabled_items, U32 flags);  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); +        virtual LLToolDragAndDrop::ESource getDragSource() const;  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -122,6 +127,9 @@ public:  							std::string& tooltip_msg) { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return mInvType; }  	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +        EInventorySortGroup getSortGroup()  const { return SG_ITEM; } +	virtual LLInventoryObject* getInventoryObject() const; +  	//--------------------------------------------------------------------  	// Convenience functions for adding various common menu options. @@ -138,16 +146,16 @@ protected:  protected:  	LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); -	LLInventoryObject* getInventoryObject() const;  	LLInventoryModel* getInventoryModel() const; +	LLInventoryFilter* getInventoryFilter() const;  	BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?  	BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?  	BOOL isAgentInventory() const; // false if lost or in the inventory library -	BOOL isCOFFolder() const; // true if COF or descendent of -	BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox -	BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox +	BOOL isCOFFolder() const;       // true if COF or descendant of +	BOOL isInboxFolder() const;     // true if COF or descendant of   marketplace inbox +	BOOL isOutboxFolder() const;    // true if COF or descendant of   marketplace outbox  	BOOL isOutboxFolderDirectParent() const;  	const LLUUID getOutboxFolder() const; @@ -160,14 +168,19 @@ protected:  									 LLViewerInventoryCategory* item,  									 const LLUUID& new_parent,  									 BOOL restamp); -	void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch); +	void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch);  protected: -	LLHandle<LLInventoryPanel> mInventoryPanel; -	LLFolderView* mRoot; -	const LLUUID mUUID;	// item id -	LLInventoryType::EType mInvType; -	BOOL mIsLink; +	LLHandle<LLInventoryPanel>	mInventoryPanel; +	LLFolderView*				mRoot; +	const LLUUID				mUUID;	// item id +	LLInventoryType::EType		mInvType; +	bool						mIsLink; +	LLTimer						mTimeSinceRequestStart; +	mutable std::string			mDisplayName; +	mutable std::string			mSearchableName; +  	void purgeItem(LLInventoryModel *model, const LLUUID &uuid); +	virtual void buildDisplayName() const {}  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -184,6 +197,7 @@ public:  										LLAssetType::EType actual_asset_type,  										LLInventoryType::EType inv_type,  										LLInventoryPanel* inventory, +										LLFolderViewModelInventory* view_model,  										LLFolderView* root,  										const LLUUID& uuid,  										U32 flags = 0x00) const; @@ -203,7 +217,6 @@ public:  	virtual void restoreToWorld();  	virtual void gotoItem();  	virtual LLUIImagePtr getIcon() const; -	virtual const std::string& getDisplayName() const;  	virtual std::string getLabelSuffix() const;  	virtual LLFontGL::StyleFlags getLabelStyle() const;  	virtual PermissionMask getPermissionMask() const; @@ -212,7 +225,7 @@ public:  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL removeItem();  	virtual BOOL isItemCopyable() const; -	virtual BOOL hasChildren() const { return FALSE; } +	virtual bool hasChildren() const { return FALSE; }  	virtual BOOL isUpToDate() const { return TRUE; }  	/*virtual*/ void clearDisplayName() { mDisplayName.clear(); } @@ -222,9 +235,8 @@ public:  protected:  	BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response);  	virtual BOOL isItemPermissive() const; -	static void buildDisplayName(LLInventoryItem* item, std::string& name); +	virtual void buildDisplayName() const; -	mutable std::string mDisplayName;  };  class LLFolderBridge : public LLInvFVBridge @@ -232,15 +244,18 @@ class LLFolderBridge : public LLInvFVBridge  public:  	LLFolderBridge(LLInventoryPanel* inventory,   				   LLFolderView* root, -				   const LLUUID& uuid) : -		LLInvFVBridge(inventory, root, uuid), +				   const LLUUID& uuid)  +        :       LLInvFVBridge(inventory, root, uuid),  		mCallingCards(FALSE), -		mWearables(FALSE) +		mWearables(FALSE), +		mIsLoading(false)  	{}  	BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg);  	BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); +    virtual void buildDisplayName() const; +  	virtual void performAction(LLInventoryModel* model, std::string action);  	virtual void openItem();  	virtual void closeItem(); @@ -250,7 +265,9 @@ public:  	virtual LLFolderType::EType getPreferredType() const;  	virtual LLUIImagePtr getIcon() const; -	virtual LLUIImagePtr getOpenIcon() const; +	virtual LLUIImagePtr getIconOpen() const; +	virtual LLUIImagePtr getIconOverlay() const; +  	static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);  	virtual BOOL renameItem(const std::string& new_name); @@ -262,7 +279,7 @@ public:  	virtual void pasteFromClipboard();  	virtual void pasteLinkFromClipboard();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); -	virtual BOOL hasChildren() const; +	virtual bool hasChildren() const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type,  							void* cargo_data, @@ -275,20 +292,24 @@ public:  	virtual BOOL isClipboardPasteable() const;  	virtual BOOL isClipboardPasteableAsLink() const; +	EInventorySortGroup getSortGroup()  const; +	virtual void update(); +  	static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);  	LLViewerInventoryCategory* getCategory() const;  	LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } +	bool isLoading() { return mIsLoading; } +  protected: -	void buildContextMenuBaseOptions(U32 flags); -	void buildContextMenuFolderOptions(U32 flags); +	void buildContextMenuOptions(U32 flags, menuentry_vec_t& items,   menuentry_vec_t& disabled_items); +	void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items,   menuentry_vec_t& disabled_items);  	//--------------------------------------------------------------------  	// Menu callbacks  	//--------------------------------------------------------------------  	static void pasteClipboard(void* user_data); -	static void createNewCategory(void* user_data);  	static void createNewShirt(void* user_data);  	static void createNewPants(void* user_data);  	static void createNewShoes(void* user_data); @@ -308,8 +329,6 @@ protected:  	void modifyOutfit(BOOL append);  	void determineFolderType(); -	menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items -  	void dropToFavorites(LLInventoryItem* inv_item);  	void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); @@ -321,11 +340,12 @@ public:  	static void staticFolderOptionsMenu();  private: -	BOOL				mCallingCards; -	BOOL				mWearables; -	menuentry_vec_t		mItems; -	menuentry_vec_t		mDisabledItems; -	LLRootHandle<LLFolderBridge> mHandle; + +	bool							mCallingCards; +	bool							mWearables; +	bool							mIsLoading; +	LLTimer							mTimeSinceRequestStart; +	LLRootHandle<LLFolderBridge>	mHandle;  };  class LLTextureBridge : public LLItemBridge @@ -354,7 +374,6 @@ public:  				  const LLUUID& uuid) :  		LLItemBridge(inventory, root, uuid) {}  	virtual void openItem(); -	virtual void previewItem();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	static void openSoundPreview(void*);  }; @@ -544,7 +563,6 @@ class LLMeshBridge : public LLItemBridge  public:  	virtual LLUIImagePtr getIcon() const;  	virtual void openItem(); -	virtual void previewItem();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  protected: @@ -629,6 +647,7 @@ public:  		LLAssetType::EType actual_asset_type,  		LLInventoryType::EType inv_type,  		LLInventoryPanel* inventory, +		LLFolderViewModelInventory* view_model,  		LLFolderView* root,  		const LLUUID& uuid,  		U32 flags = 0x00) const; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 4d0af94f9f..3f38d80a39 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -29,7 +29,7 @@  #include "llinventoryfilter.h"  // viewer includes -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llfolderviewitem.h"  #include "llinventorymodel.h"  #include "llinventorymodelbackgroundfetch.h" @@ -42,109 +42,91 @@  #include "llclipboard.h"  #include "lltrans.h" +//TODO RN: fix use of static cast as much as possible +  LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); -LLInventoryFilter::FilterOps::FilterOps() : -	mFilterObjectTypes(0xffffffffffffffffULL), -	mFilterCategoryTypes(0xffffffffffffffffULL), -	mFilterWearableTypes(0xffffffffffffffffULL), -	mMinDate(time_min()), -	mMaxDate(time_max()), -	mHoursAgo(0), -	mShowFolderState(SHOW_NON_EMPTY_FOLDERS), -	mPermissions(PERM_NONE), -	mFilterTypes(FILTERTYPE_OBJECT), -	mFilterUUID(LLUUID::null), -	mFilterLinks(FILTERLINK_INCLUDE_LINKS) +LLInventoryFilter::FilterOps::FilterOps(const Params& p) +:	mFilterObjectTypes(p.object_types), +	mFilterCategoryTypes(p.category_types), +	mFilterWearableTypes(p.wearable_types), +	mMinDate(p.date_range.min_date), +	mMaxDate(p.date_range.max_date), +	mHoursAgo(p.hours_ago), +	mShowFolderState(p.show_folder_state), +	mPermissions(p.permissions), +	mFilterTypes(p.types), +	mFilterUUID(p.uuid), +	mFilterLinks(p.links)  {  }  ///----------------------------------------------------------------------------  /// Class LLInventoryFilter  ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) -:	mName(name), -	mModified(FALSE), -	mNeedTextRebuild(TRUE), -	mEmptyLookupMessage("InventoryNoMatchingItems") +LLInventoryFilter::LLInventoryFilter(const Params& p) +:	mName(p.name), +	mFilterModified(FILTER_NONE), +	mEmptyLookupMessage("InventoryNoMatchingItems"), +    mFilterOps(p.filter_ops), +	mOrder(p.sort_order), +	mFilterSubString(p.substring), +	mCurrentGeneration(0), +	mFirstRequiredGeneration(0), +	mFirstSuccessGeneration(0), +	mFilterCount(0)  { -	mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately - -	mSubStringMatchOffset = 0; -	mFilterSubString.clear(); -	mFilterGeneration = 0; -	mMustPassGeneration = S32_MAX; -	mMinRequiredGeneration = 0; -	mFilterCount = 0; -	mNextFilterGeneration = mFilterGeneration + 1; - -	mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); -	mFilterBehavior = FILTER_NONE; +	mNextFilterGeneration = mCurrentGeneration + 1;  	// copy mFilterOps into mDefaultFilterOps  	markDefault();  } -LLInventoryFilter::~LLInventoryFilter() -{ -} - -BOOL LLInventoryFilter::check(const LLFolderViewItem* item)  +bool LLInventoryFilter::check(const LLFolderViewModelItem* item)   { +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item);  	// Clipboard cut items are *always* filtered so we need this value upfront -	const LLFolderViewEventListener* listener = item->getListener();  	const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE);  	// If it's a folder and we're showing all folders, return automatically. -	const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL); +	const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;;  	if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))  	{  		return passed_clipboard;  	} -	mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; +	std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : 0; -	const BOOL passed_filtertype = checkAgainstFilterType(item); -	const BOOL passed_permissions = checkAgainstPermissions(item); -	const BOOL passed_filterlink = checkAgainstFilterLinks(item); -	const BOOL passed = (passed_filtertype && -						 passed_permissions && -						 passed_filterlink && -						 passed_clipboard && -						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); +	BOOL passed = string_offset !=  std::string::npos; +	passed = passed && checkAgainstFilterType(listener); +	passed = passed && checkAgainstPermissions(listener); +	passed = passed && checkAgainstFilterLinks(listener); +	passed = passed && passed_clipboard;  	return passed;  }  bool LLInventoryFilter::check(const LLInventoryItem* item)  { -	mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; +	std::string::size_type string_offset = mFilterSubString.size() ?   item->getName().find(mFilterSubString) : std::string::npos;  	const bool passed_filtertype = checkAgainstFilterType(item);  	const bool passed_permissions = checkAgainstPermissions(item);  	const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); -	const bool passed = (passed_filtertype && -						 passed_permissions && -						 passed_clipboard && -						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); +	const bool passed = (passed_filtertype  +		&& passed_permissions +		&& passed_clipboard  +		&&	(mFilterSubString.size() == 0 || string_offset !=  std::string::npos));  	return passed;  } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const  { -	if (!folder) -	{ -		llwarns << "The filter can not be checked on an invalid folder." << llendl; -		llassert(false); // crash in development builds -		return false; -	} - -	const LLFolderViewEventListener* listener = folder->getListener(); +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item);  	if (!listener)  	{ -		llwarns << "Folder view event listener not found." << llendl; -		llassert(false); // crash in development builds +		llerrs << "Folder view event listener not found." << llendl;  		return false;  	} @@ -155,6 +137,13 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const  bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  { +	// when applying a filter, matching folders get their contents downloaded first +	if (isNotDefault() +		&& !gInventory.isCategoryComplete(folder_id)) +	{ +		LLInventoryModelBackgroundFetch::instance().start(folder_id); +	} +  	// Always check against the clipboard  	const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -163,14 +152,14 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  	{  		return passed_clipboard;  	} - +	  	if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)  	{  		// Can only filter categories for items in your inventory  		// (e.g. versus in-world object contents).  		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);  		if (!cat) -			return false; +			return folder_id.isNull();  		LLFolderType::EType cat_type = cat->getPreferredType();  		if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))  			return false; @@ -179,9 +168,8 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  	return passed_clipboard;  } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return FALSE;  	LLInventoryType::EType object_type = listener->getInventoryType(); @@ -268,7 +256,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  			}  		}  	} - +	  	return TRUE;  } @@ -347,13 +335,12 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const  	return true;  } -BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return FALSE;  	PermissionMask perm = listener->getPermissionMask(); -	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener()); +	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(listener);  	if (bridge && bridge->isLink())  	{  		const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -375,9 +362,8 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con  	return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;  } -BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return TRUE;  	const LLUUID object_id = listener->getUUID(); @@ -397,20 +383,20 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const  	return mFilterSubString;  } -std::string::size_type LLInventoryFilter::getStringMatchOffset() const +std::string::size_type   LLInventoryFilter::getStringMatchOffset(LLFolderViewItem* item) const  { -	return mSubStringMatchOffset; +	return mFilterSubString.size() ? item->getName().find(mFilterSubString)   : std::string::npos;  } -BOOL LLInventoryFilter::isDefault() const +bool LLInventoryFilter::isDefault() const  {  	return !isNotDefault();  }  // has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() const +bool LLInventoryFilter::isNotDefault() const  { -	BOOL not_default = FALSE; +	S32 not_default = 0;  	not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes);  	not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); @@ -422,11 +408,11 @@ BOOL LLInventoryFilter::isNotDefault() const  	not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate);  	not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate);  	not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); -	 -	return not_default; + +	return not_default != 0;  } -BOOL LLInventoryFilter::isActive() const +bool LLInventoryFilter::isActive() const  {  	return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL  		|| mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL @@ -440,16 +426,9 @@ BOOL LLInventoryFilter::isActive() const  		|| mFilterOps.mHoursAgo != 0;  } -BOOL LLInventoryFilter::isModified() const +bool LLInventoryFilter::isModified() const  { -	return mModified; -} - -BOOL LLInventoryFilter::isModifiedAndClear() -{ -	BOOL ret = mModified; -	mModified = FALSE; -	return ret; +	return mFilterModified != FILTER_NONE;  }  void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) @@ -613,9 +592,10 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)  void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  { +	static LLCachedControl<U32> s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0);  	if (sl && !isSinceLogoff())  	{ -		setDateRange(mLastLogoff, time_max()); +		setDateRange(s_last_logoff(), time_max());  		setModified();  	}  	if (!sl && isSinceLogoff()) @@ -634,17 +614,18 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  	}  } -BOOL LLInventoryFilter::isSinceLogoff() const +bool LLInventoryFilter::isSinceLogoff() const  { -	return (mFilterOps.mMinDate == (time_t)mLastLogoff) && +	static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); + +	return (mFilterOps.mMinDate == (time_t)s_last_logoff()) &&  		(mFilterOps.mMaxDate == time_max()) &&  		(mFilterOps.mFilterTypes & FILTERTYPE_DATE);  }  void LLInventoryFilter::clearModified()  { -	mModified = FALSE;  -	mFilterBehavior = FILTER_NONE; +	mFilterModified = FILTER_NONE;  }  void LLInventoryFilter::setHoursAgo(U32 hours) @@ -742,83 +723,68 @@ void LLInventoryFilter::resetDefault()  	setModified();  } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +void LLInventoryFilter::setModified(EFilterModified behavior)  { -	mModified = TRUE; -	mNeedTextRebuild = TRUE; -	mFilterGeneration = mNextFilterGeneration++; +	mFilterText.clear(); +	mCurrentGeneration = mNextFilterGeneration++; -	if (mFilterBehavior == FILTER_NONE) +	if (mFilterModified == FILTER_NONE)  	{ -		mFilterBehavior = behavior; +		mFilterModified = behavior;  	} -	else if (mFilterBehavior != behavior) +	else if (mFilterModified != behavior)  	{  		// trying to do both less restrictive and more restrictive filter  		// basically means restart from scratch -		mFilterBehavior = FILTER_RESTART; +		mFilterModified = FILTER_RESTART;  	} -	if (isNotDefault()) -	{ -		// if not keeping current filter results, update last valid as well -		switch(mFilterBehavior) -		{ -			case FILTER_RESTART: -				mMustPassGeneration = mFilterGeneration; -				mMinRequiredGeneration = mFilterGeneration; -				break; -			case FILTER_LESS_RESTRICTIVE: -				mMustPassGeneration = mFilterGeneration; -				break; -			case FILTER_MORE_RESTRICTIVE: -				mMinRequiredGeneration = mFilterGeneration; -				// must have passed either current filter generation (meaningless, as it hasn't been run yet) -				// or some older generation, so keep the value -				mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); -				break; -			default: -				llerrs << "Bad filter behavior specified" << llendl; -		} -	} -	else +	// if not keeping current filter results, update last valid as well +	switch(mFilterModified)  	{ -		// shortcut disabled filters to show everything immediately -		mMinRequiredGeneration = 0; -		mMustPassGeneration = S32_MAX; +		case FILTER_RESTART: +			mFirstRequiredGeneration = mCurrentGeneration; +			mFirstSuccessGeneration = mCurrentGeneration; +			break; +		case FILTER_LESS_RESTRICTIVE: +			mFirstRequiredGeneration = mCurrentGeneration; +			break; +		case FILTER_MORE_RESTRICTIVE: +			mFirstSuccessGeneration = mCurrentGeneration; +			break; +		default: +			llerrs << "Bad filter behavior specified" << llendl;  	}  } -BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const +bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const  {  	return mFilterOps.mFilterObjectTypes & (1LL << t);  }  const std::string& LLInventoryFilter::getFilterText()  { -	if (!mNeedTextRebuild) +	if (!mFilterText.empty())  	{  		return mFilterText;  	} -	mNeedTextRebuild = FALSE;  	std::string filtered_types;  	std::string not_filtered_types;  	BOOL filtered_by_type = FALSE;  	BOOL filtered_by_all_types = TRUE;  	S32 num_filter_types = 0; +  	mFilterText.clear();  	if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION))  	{ -		//filtered_types += " Animations,";  		filtered_types += LLTrans::getString("Animations");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Animations,";  		not_filtered_types += LLTrans::getString("Animations");  		filtered_by_all_types = FALSE; @@ -826,140 +792,120 @@ const std::string& LLInventoryFilter::getFilterText()  	if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD))  	{ -		//filtered_types += " Calling Cards,";  		filtered_types += LLTrans::getString("Calling Cards");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Calling Cards,";  		not_filtered_types += LLTrans::getString("Calling Cards");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE))  	{ -		//filtered_types += " Clothing,";  		filtered_types +=  LLTrans::getString("Clothing");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Clothing,";  		not_filtered_types +=  LLTrans::getString("Clothing");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE))  	{ -		//filtered_types += " Gestures,";  		filtered_types +=  LLTrans::getString("Gestures");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Gestures,";  		not_filtered_types +=  LLTrans::getString("Gestures");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK))  	{ -		//filtered_types += " Landmarks,";  		filtered_types +=  LLTrans::getString("Landmarks");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Landmarks,";  		not_filtered_types +=  LLTrans::getString("Landmarks");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))  	{ -		//filtered_types += " Notecards,";  		filtered_types +=  LLTrans::getString("Notecards");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Notecards,";  		not_filtered_types +=  LLTrans::getString("Notecards");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT))  	{ -		//filtered_types += " Objects,";  		filtered_types +=  LLTrans::getString("Objects");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Objects,";  		not_filtered_types +=  LLTrans::getString("Objects");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_LSL))  	{ -		//filtered_types += " Scripts,";  		filtered_types +=  LLTrans::getString("Scripts");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Scripts,";  		not_filtered_types +=  LLTrans::getString("Scripts");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND))  	{ -		//filtered_types += " Sounds,";  		filtered_types +=  LLTrans::getString("Sounds");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Sounds,";  		not_filtered_types +=  LLTrans::getString("Sounds");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE))  	{ -		//filtered_types += " Textures,";  		filtered_types +=  LLTrans::getString("Textures");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Textures,";  		not_filtered_types +=  LLTrans::getString("Textures");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT))  	{ -		//filtered_types += " Snapshots,";  		filtered_types +=  LLTrans::getString("Snapshots");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Snapshots,";  		not_filtered_types +=  LLTrans::getString("Snapshots");  		filtered_by_all_types = FALSE;  	} @@ -975,7 +921,6 @@ const std::string& LLInventoryFilter::getFilterText()  		}  		else  		{ -			//mFilterText += "No ";  			mFilterText += LLTrans::getString("No Filters");  			mFilterText += not_filtered_types;  		} @@ -985,66 +930,58 @@ const std::string& LLInventoryFilter::getFilterText()  	if (isSinceLogoff())  	{ -		//mFilterText += " - Since Logoff";  		mFilterText += LLTrans::getString("Since Logoff");  	}  	return mFilterText;  } -void LLInventoryFilter::toLLSD(LLSD& data) const -{ -	data["filter_types"] = (LLSD::Integer)getFilterObjectTypes(); -	data["min_date"] = (LLSD::Integer)getMinDate(); -	data["max_date"] = (LLSD::Integer)getMaxDate(); -	data["hours_ago"] = (LLSD::Integer)getHoursAgo(); -	data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); -	data["permissions"] = (LLSD::Integer)getFilterPermissions(); -	data["substring"] = (LLSD::String)getFilterSubString(); -	data["sort_order"] = (LLSD::Integer)getSortOrder(); -	data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); -} - -void LLInventoryFilter::fromLLSD(LLSD& data) -{ -	if(data.has("filter_types")) -	{ -		setFilterObjectTypes((U64)data["filter_types"].asInteger()); -	} - -	if(data.has("min_date") && data.has("max_date")) -	{ -		setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); -	} - -	if(data.has("hours_ago")) -	{ -		setHoursAgo((U32)data["hours_ago"].asInteger()); -	} -	if(data.has("show_folder_state")) -	{ -		setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); -	} +LLInventoryFilter& LLInventoryFilter::operator=( const  LLInventoryFilter&  other ) +{ +	setFilterObjectTypes(other.getFilterObjectTypes()); +	setDateRange(other.getMinDate(), other.getMaxDate()); +	setHoursAgo(other.getHoursAgo()); +	setShowFolderState(other.getShowFolderState()); +	setFilterPermissions(other.getFilterPermissions()); +	setFilterSubString(other.getFilterSubString()); +	setSortOrder(other.getSortOrder()); +	setDateRangeLastLogoff(other.isSinceLogoff()); +	return *this; +} -	if(data.has("permissions")) -	{ -		setFilterPermissions((PermissionMask)data["permissions"].asInteger()); -	} -	if(data.has("substring")) -	{ -		setFilterSubString(std::string(data["substring"].asString())); -	} +void LLInventoryFilter::toParams(Params& params) const +{ +	params.filter_ops.types = getFilterObjectTypes(); +	params.filter_ops.category_types = getFilterCategoryTypes(); +	params.filter_ops.wearable_types = getFilterWearableTypes(); +	params.filter_ops.date_range.min_date = getMinDate(); +	params.filter_ops.date_range.max_date = getMaxDate(); +	params.filter_ops.hours_ago = getHoursAgo(); +	params.filter_ops.show_folder_state = getShowFolderState(); +	params.filter_ops.permissions = getFilterPermissions(); +	params.substring = getFilterSubString(); +	params.sort_order = getSortOrder(); +	params.since_logoff = isSinceLogoff(); +} -	if(data.has("sort_order")) +void LLInventoryFilter::fromParams(const Params& params) +{ +	if (!params.validateBlock())  	{ -		setSortOrder((U32)data["sort_order"].asInteger()); +		return;  	} -	if(data.has("since_logoff")) -	{ -		setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); -	} +	setFilterObjectTypes(params.filter_ops.types); +	setFilterCategoryTypes(params.filter_ops.category_types); +	setFilterWearableTypes(params.filter_ops.wearable_types); +	setDateRange(params.filter_ops.date_range.min_date,   params.filter_ops.date_range.max_date); +	setHoursAgo(params.filter_ops.hours_ago); +	setShowFolderState(params.filter_ops.show_folder_state); +	setFilterPermissions(params.filter_ops.permissions); +	setFilterSubString(params.substring); +	setSortOrder(params.sort_order); +	setDateRangeLastLogoff(params.since_logoff);  }  U64 LLInventoryFilter::getFilterObjectTypes() const @@ -1057,7 +994,12 @@ U64 LLInventoryFilter::getFilterCategoryTypes() const  	return mFilterOps.mFilterCategoryTypes;  } -BOOL LLInventoryFilter::hasFilterString() const +U64 LLInventoryFilter::getFilterWearableTypes() const +{ +	return mFilterOps.mFilterWearableTypes; +} + +bool LLInventoryFilter::hasFilterString() const  {  	return mFilterSubString.size() > 0;  } @@ -1092,10 +1034,6 @@ U32 LLInventoryFilter::getSortOrder() const  {   	return mOrder;   } -const std::string& LLInventoryFilter::getName() const  -{  -	return mName;  -}  void LLInventoryFilter::setFilterCount(S32 count)   {  @@ -1113,15 +1051,15 @@ void LLInventoryFilter::decrementFilterCount()  S32 LLInventoryFilter::getCurrentGeneration() const   {  -	return mFilterGeneration;  +	return mCurrentGeneration;  } -S32 LLInventoryFilter::getMinRequiredGeneration() const  +S32 LLInventoryFilter::getFirstSuccessGeneration() const  {  -	return mMinRequiredGeneration;  +	return mFirstSuccessGeneration;   } -S32 LLInventoryFilter::getMustPassGeneration() const  +S32 LLInventoryFilter::getFirstRequiredGeneration() const  {  -	return mMustPassGeneration;  +	return mFirstRequiredGeneration;   }  void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) @@ -1129,9 +1067,12 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)  	mEmptyLookupMessage = message;  } -const std::string& LLInventoryFilter::getEmptyLookupMessage() const +std::string LLInventoryFilter::getEmptyLookupMessage() const  { -	return mEmptyLookupMessage; +	LLStringUtil::format_map_t args; +	args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); + +	return LLTrans::getString(mEmptyLookupMessage, args);  } @@ -1141,3 +1082,27 @@ bool LLInventoryFilter::areDateLimitsSet()  			|| mFilterOps.mMaxDate != time_max()  			|| mFilterOps.mHoursAgo != 0;  } + +bool LLInventoryFilter::showAllResults() const +{ +	return hasFilterString(); +} + + + +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool   emit_errors /*= true*/ ) const +{ +	bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); +	if (valid) +	{ +		if (max_date() < min_date()) +		{ +			if (emit_errors) +			{ +				llwarns << "max_date should be greater or equal to min_date" <<   llendl; +			} +			valid = false; +		} +	} +	return valid; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 9e600c036f..af245a9c3b 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -29,12 +29,13 @@  #include "llinventorytype.h"  #include "llpermissionsflags.h" +#include "llfolderviewmodel.h"  class LLFolderViewItem;  class LLFolderViewFolder;  class LLInventoryItem; -class LLInventoryFilter +class LLInventoryFilter : public LLFolderViewFilter  {  public:  	enum EFolderShow @@ -44,14 +45,6 @@ public:  		SHOW_NO_FOLDERS  	}; -	enum EFilterBehavior -	{ -		FILTER_NONE,				// nothing to do, already filtered -		FILTER_RESTART,				// restart filtering from scratch -		FILTER_LESS_RESTRICTIVE,	// existing filtered items will certainly pass this filter -		FILTER_MORE_RESTRICTIVE		// if you didn't pass the previous filter, you definitely won't pass this one -	}; -  	enum EFilterType	{  		FILTERTYPE_NONE = 0,  		FILTERTYPE_OBJECT = 0x1 << 0,	// normal default search-by-object-type @@ -59,7 +52,7 @@ public:  		FILTERTYPE_UUID	= 0x1 << 2,		// find the object with UUID and any links to it  		FILTERTYPE_DATE = 0x1 << 3,		// search by date range  		FILTERTYPE_WEARABLE = 0x1 << 4,	// search by wearable type -		FILTERTYPE_EMPTYFOLDERS = 0x1 << 5	// pass if folder is not a system folder to be hidden if empty +		FILTERTYPE_EMPTYFOLDERS = 0x1 << 5		// pass if folder is not a system   folder to be hidden if  	};  	enum EFilterLink @@ -77,16 +70,94 @@ public:  		SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2	// Force system folders to be on top  	}; -	LLInventoryFilter(const std::string& name); -	virtual ~LLInventoryFilter(); +	struct FilterOps +	{ +		struct DateRange : public LLInitParam::Block<DateRange> +		{ +			Optional<time_t> min_date; +			Optional<time_t> max_date; + +			DateRange() +			:	min_date("min_date", time_min()), +				max_date("max_date", time_max()) +			{} + +			bool validateBlock(bool emit_errors = true) const; +		}; + +		struct Params : public LLInitParam::Block<Params> +		{ +			Optional<U32>				types; +			Optional<U64>				object_types, +										wearable_types, +										category_types; +			Optional<EFilterLink>		links; +			Optional<LLUUID>			uuid; +			Optional<DateRange>			date_range; +			Optional<S32>				hours_ago; +			Optional<EFolderShow>		show_folder_state; +			Optional<PermissionMask>	permissions; + +			Params() +			:	types("filter_types", FILTERTYPE_OBJECT), +				object_types("object_types", 0xffffFFFFffffFFFFULL), +				wearable_types("wearable_types", 0xffffFFFFffffFFFFULL), +				category_types("category_types", 0xffffFFFFffffFFFFULL), +				links("links", FILTERLINK_INCLUDE_LINKS), +				uuid("uuid"), +				date_range("date_range"), +				hours_ago("hours_ago", 0), +				show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS), +				permissions("permissions", PERM_NONE) +			{} +		}; + +		FilterOps(const Params& = Params()); + +		U32 			mFilterTypes; + +		U64				mFilterObjectTypes;   // For _OBJECT +		U64				mFilterWearableTypes; +		U64				mFilterCategoryTypes; // For _CATEGORY +		LLUUID      	mFilterUUID; 		  // for UUID + +		time_t			mMinDate; +		time_t			mMaxDate; +		U32				mHoursAgo; +		EFolderShow		mShowFolderState; +		PermissionMask	mPermissions; +		U64				mFilterLinks; +	}; +							 +	struct Params : public LLInitParam::Block<Params> +	{ +		Optional<std::string>		name; +		Optional<FilterOps::Params>	filter_ops; +		Optional<std::string>		substring; +		Optional<U32>				sort_order; +		Optional<bool>				since_logoff; + +		Params() +		:	name("name"), +			filter_ops(""), +			substring("substring"), +			sort_order("sort_order"), +			since_logoff("since_logoff") +		{} +	}; +									 +	LLInventoryFilter(const Params& p = Params()); +	LLInventoryFilter(const LLInventoryFilter& other) { *this = other; } +	virtual ~LLInventoryFilter() {}  	// +-------------------------------------------------------------------+  	// + Parameters  	// +-------------------------------------------------------------------+ -	void 				setFilterObjectTypes(U64 types);  	U64 				getFilterObjectTypes() const;  	U64					getFilterCategoryTypes() const; -	BOOL 				isFilterObjectTypesWith(LLInventoryType::EType t) const; +	U64					getFilterWearableTypes() const; +	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const; +	void 				setFilterObjectTypes(U64 types);  	void 				setFilterCategoryTypes(U64 types);  	void 				setFilterUUID(const LLUUID &object_id);  	void				setFilterWearableTypes(U64 types); @@ -96,7 +167,7 @@ public:  	void 				setFilterSubString(const std::string& string);  	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;  	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; }  -	BOOL 				hasFilterString() const; +	bool 				hasFilterString() const;  	void 				setFilterPermissions(PermissionMask perms);  	PermissionMask 		getFilterPermissions() const; @@ -115,19 +186,17 @@ public:  	// +-------------------------------------------------------------------+  	// + Execution And Results  	// +-------------------------------------------------------------------+ -	BOOL 				check(const LLFolderViewItem* item); +	bool				check(const LLFolderViewModelItem* listener);  	bool				check(const LLInventoryItem* item); -	bool				checkFolder(const LLFolderViewFolder* folder) const; +	bool				checkFolder(const LLFolderViewModelItem* listener) const;  	bool				checkFolder(const LLUUID& folder_id) const; -	BOOL 				checkAgainstFilterType(const LLFolderViewItem* item) const; -	bool 				checkAgainstFilterType(const LLInventoryItem* item) const; -	BOOL 				checkAgainstPermissions(const LLFolderViewItem* item) const; -	bool 				checkAgainstPermissions(const LLInventoryItem* item) const; -	BOOL 				checkAgainstFilterLinks(const LLFolderViewItem* item) const; -	bool				checkAgainstClipboard(const LLUUID& object_id) const; + +	bool				showAllResults() const; +  	std::string::size_type getStringMatchOffset() const; +	std::string::size_type getStringMatchOffset(LLFolderViewItem* item)   const;  	// +-------------------------------------------------------------------+  	// + Presentation  	// +-------------------------------------------------------------------+ @@ -138,20 +207,19 @@ public:  	U32 				getSortOrder() const;  	void 				setEmptyLookupMessage(const std::string& message); -	const std::string&	getEmptyLookupMessage() const; +	std::string			getEmptyLookupMessage() const;  	// +-------------------------------------------------------------------+  	// + Status  	// +-------------------------------------------------------------------+ -	BOOL 				isActive() const; -	BOOL 				isModified() const; -	BOOL 				isModifiedAndClear(); -	BOOL 				isSinceLogoff() const; +	bool 				isActive() const; +	bool 				isModified() const; +	bool 				isSinceLogoff() const;  	void 				clearModified(); -	const std::string& 	getName() const; +	const std::string& 	getName() const { return mName; }  	const std::string& 	getFilterText();  	//RN: this is public to allow system to externally force a global refilter -	void 				setModified(EFilterBehavior behavior = FILTER_RESTART); +	void 				setModified(EFilterModified behavior = FILTER_RESTART);  	// +-------------------------------------------------------------------+  	// + Count @@ -163,8 +231,8 @@ public:  	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ -	BOOL 				isDefault() const; -	BOOL 				isNotDefault() const; +	bool 				isDefault() const; +	bool 				isNotDefault() const;  	void 				markDefault();  	void 				resetDefault(); @@ -172,57 +240,44 @@ public:  	// + Generation  	// +-------------------------------------------------------------------+  	S32 				getCurrentGeneration() const; -	S32 				getMinRequiredGeneration() const; -	S32 				getMustPassGeneration() const; +	S32 				getFirstSuccessGeneration() const; +	S32 				getFirstRequiredGeneration() const; +  	// +-------------------------------------------------------------------+  	// + Conversion  	// +-------------------------------------------------------------------+ -	void 				toLLSD(LLSD& data) const; -	void 				fromLLSD(LLSD& data); +	void 				toParams(Params& params) const; +	void 				fromParams(const Params& p); + +	LLInventoryFilter& operator =(const LLInventoryFilter& other);  private:  	bool				areDateLimitsSet(); - -	struct FilterOps -	{ -		FilterOps(); -		U32 			mFilterTypes; - -		U64				mFilterObjectTypes; // For _OBJECT -		U64				mFilterWearableTypes; -		U64				mFilterCategoryTypes; // For _CATEGORY -		LLUUID      	mFilterUUID; // for UUID - -		time_t			mMinDate; -		time_t			mMaxDate; -		U32				mHoursAgo; -		EFolderShow		mShowFolderState; -		PermissionMask	mPermissions; -		U64				mFilterLinks; -	}; +	bool 				checkAgainstFilterType(const class LLFolderViewModelItemInventory* listener) const; +	bool 				checkAgainstFilterType(const LLInventoryItem* item) const; +	bool 				checkAgainstPermissions(const class LLFolderViewModelItemInventory* listener) const; +	bool 				checkAgainstPermissions(const LLInventoryItem* item) const; +	bool 				checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; +	bool				checkAgainstClipboard(const LLUUID& object_id) const;  	U32						mOrder; -	U32 					mLastLogoff;  	FilterOps				mFilterOps;  	FilterOps				mDefaultFilterOps; -	std::string::size_type	mSubStringMatchOffset;  	std::string				mFilterSubString;  	std::string				mFilterSubStringOrig;  	const std::string		mName; -	S32						mFilterGeneration; -	S32						mMustPassGeneration; -	S32						mMinRequiredGeneration; +	S32						mCurrentGeneration; +	S32						mFirstRequiredGeneration; +	S32						mFirstSuccessGeneration;  	S32						mNextFilterGeneration;  	S32						mFilterCount; -	EFilterBehavior 		mFilterBehavior; +	EFilterModified 		mFilterModified; -	BOOL 					mModified; -	BOOL 					mNeedTextRebuild;  	std::string 			mFilterText;  	std::string 			mEmptyLookupMessage;  }; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ab5b082915..ff461236a2 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -948,7 +948,7 @@ void LLSaveFolderState::setApply(BOOL apply)  void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)  {  	LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); -	LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); +	LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem();  	if(!bridge) return;  	if(mApply) @@ -983,7 +983,7 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)  void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)  { -	if (item->getFiltered()) +	if (item->passedFilter())  	{  		item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);  	} @@ -991,12 +991,12 @@ void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)  void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getFiltered() && folder->getParentFolder()) +	if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())  	{  		folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);  	}  	// if this folder didn't pass the filter, and none of its descendants did -	else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) +	else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter())  	{  		folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);  	} @@ -1004,7 +1004,7 @@ void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)  void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)  { -	if (item->getFiltered() && !mItemSelected) +	if (item->passedFilter() && !mItemSelected)  	{  		item->getRoot()->setSelection(item, FALSE, FALSE);  		if (item->getParentFolder()) @@ -1017,7 +1017,7 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)  void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getFiltered() && !mItemSelected) +	if (folder->LLFolderViewItem::passedFilter() && !mItemSelected)  	{  		folder->getRoot()->setSelection(folder, FALSE, FALSE);  		if (folder->getParentFolder()) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 5cf9c528b0..c6b1da0417 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -418,21 +418,6 @@ public:  class LLFolderViewItem;  class LLFolderViewFolder; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: -	virtual ~LLFolderViewFunctor() {} -	virtual void doFolder(LLFolderViewFolder* folder) = 0; -	virtual void doItem(LLFolderViewItem* item) = 0; -};  class LLInventoryState  { @@ -442,49 +427,6 @@ public:  	static LLUUID sWearNewClothingTransactionID;	// wear all clothing in this transaction	  }; -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: -	LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} -	virtual ~LLSelectFirstFilteredItem() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -	BOOL wasItemSelected() { return mItemSelected; } -protected: -	BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: -	LLOpenFilteredFolders()  {} -	virtual ~LLOpenFilteredFolders() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: -	LLSaveFolderState() : mApply(FALSE) {} -	virtual ~LLSaveFolderState() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item) {} -	void setApply(BOOL apply); -	void clearOpenFolders() { mOpenFolders.clear(); } -protected: -	std::set<LLUUID> mOpenFolders; -	BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: -	LLOpenFoldersWithSelection() {} -	virtual ~LLOpenFoldersWithSelection() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -};  #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 85ecb133d0..9b0d12b353 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3201,68 +3201,7 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c  	}  } -//* @param[in] items vector of items in order to be saved. -void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) -{ -	int sortField = 0; - -	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field -	for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) -	{ -		LLViewerInventoryItem* item = *i; - -		item->setSortField(++sortField); -		item->setComplete(TRUE); -		item->updateServer(FALSE); - -		updateItem(item); - -		// Tell the parent folder to refresh its sort order. -		addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); -	} - -	notifyObservers(); -} - -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: -	bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) -	{ -		return a->getSortField() < b->getSortField(); -	} -}; -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ -	static LLViewerInventoryItemSort sort_functor; -	std::sort(items.begin(), items.end(), sort_functor); -} - -// * @param source_item_id - LLUUID of the source item to be moved into new position -// * @param target_item_id - LLUUID of the target item before which source item should be placed. -void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) -{ -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	LLIsType is_type(LLAssetType::AT_LANDMARK); -	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - -	// ensure items are sorted properly before changing order. EXT-3498 -	rearrange_item_order_by_sort_field(items); - -	// update order -	updateItemsOrder(items, source_item_id, target_item_id); - -	saveItemsOrder(items); -}  //---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 8382e875b4..3613bc4917 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -362,15 +362,6 @@ public:  	// Returns end() of the vector if not found.  	static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); -	// Saves current order of the passed items using inventory item sort field. -	// Resets 'items' sort fields and saves them on server. -	// Is used to save order for Favorites folder. -	void saveItemsOrder(const LLInventoryModel::item_array_t& items); - -	// Rearranges Landmarks inside Favorites folder. -	// Moves source landmark before target one. -	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); -  	//--------------------------------------------------------------------  	// Creation  	//-------------------------------------------------------------------- diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 71dd963f28..b5fcf364dd 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -38,6 +38,7 @@  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h"  #include "llfolderview.h" +#include "llfolderviewitem.h"  #include "llimfloater.h"  #include "llimview.h"  #include "llinventorybridge.h" @@ -55,7 +56,6 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent  const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");  static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; -  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLInventoryPanelObserver  // @@ -134,7 +134,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :  	mAllowMultiSelect(p.allow_multi_select),  	mShowItemLinkOverlays(p.show_item_link_overlays),  	mShowEmptyMessage(p.show_empty_message), -	mShowLoadStatus(p.show_load_status),  	mViewsInitialized(false),  	mInvFVBridgeBuilder(NULL)  { @@ -183,10 +182,12 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)  																	LLAssetType::AT_CATEGORY,  																	LLInventoryType::IT_CATEGORY,  																	this, +																	&mInventoryViewModel,  																	NULL,  																	root_id);  	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); +	addItemID(root_id, mFolderRoot);  }  void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) @@ -202,18 +203,16 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);  	// Scroller -	{ -		LLRect scroller_view_rect = getRect(); -		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); -		LLScrollContainer::Params scroller_params(params.scroll()); -		scroller_params.rect(scroller_view_rect); -		mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); -		addChild(mScroller); -		mScroller->addChild(mFolderRoot); -		mFolderRoot->setScrollContainer(mScroller); -		mFolderRoot->setFollowsAll(); -		mFolderRoot->addChild(mFolderRoot->mStatusTextBox); -	} +	LLRect scroller_view_rect = getRect(); +	scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +	LLScrollContainer::Params scroller_params(params.scroll()); +	scroller_params.rect(scroller_view_rect); +	mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); +	addChild(mScroller); +	mScroller->addChild(mFolderRoot); +	mFolderRoot->setScrollContainer(mScroller); +	mFolderRoot->setFollowsAll(); +	mFolderRoot->addChild(mFolderRoot->mStatusTextBox);  	// Set up the callbacks from the inventory we're viewing, and then build everything.  	mInventoryObserver = new LLInventoryPanelObserver(this); @@ -258,13 +257,10 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  LLInventoryPanel::~LLInventoryPanel()  { -	if (mFolderRoot) +	U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); +	if (mSortOrderSetting != INHERIT_SORT_ORDER)  	{ -		U32 sort_order = mFolderRoot->getSortOrder(); -		if (mSortOrderSetting != INHERIT_SORT_ORDER) -		{ -			gSavedSettings.setU32(mSortOrderSetting, sort_order); -		} +		gSavedSettings.setU32(mSortOrderSetting, sort_order);  	}  	gIdleCallbacks.deleteFunction(onIdle, this); @@ -281,7 +277,7 @@ LLInventoryPanel::~LLInventoryPanel()  void LLInventoryPanel::draw()  {  	// Select the desired item (in case it wasn't loaded when the selection was requested) -	mFolderRoot->updateSelection(); +	updateSelection();  	// Nudge the filter if the clipboard state changed  	if (mClipboardState != LLClipboard::instance().getGeneration()) @@ -293,22 +289,14 @@ void LLInventoryPanel::draw()  	LLPanel::draw();  } -LLInventoryFilter* LLInventoryPanel::getFilter() +const LLInventoryFilter* LLInventoryPanel::getFilter() const  { -	if (mFolderRoot)  -	{ -		return mFolderRoot->getFilter(); -	} -	return NULL; +	return getFolderViewModel()->getFilter();  } -const LLInventoryFilter* LLInventoryPanel::getFilter() const +LLInventoryFilter* LLInventoryPanel::getFilter()  { -	if (mFolderRoot) -	{ -		return mFolderRoot->getFilter(); -	} -	return NULL; +	return getFolderViewModel()->getFilter();  }  void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) @@ -321,12 +309,12 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType  U32 LLInventoryPanel::getFilterObjectTypes() const   {  -	return mFolderRoot->getFilterObjectTypes();  +	return getFilter()->getFilterObjectTypes();  }  U32 LLInventoryPanel::getFilterPermMask() const   {  -	return mFolderRoot->getFilterPermissions();  +	return getFilter()->getFilterPermissions();  } @@ -347,16 +335,17 @@ void LLInventoryPanel::setFilterSubString(const std::string& string)  const std::string LLInventoryPanel::getFilterSubString()   {  -	return mFolderRoot->getFilterSubString();  +	return getFilter()->getFilterSubString();  }  void LLInventoryPanel::setSortOrder(U32 order)  { +        LLInventorySort sorter(order);  	getFilter()->setSortOrder(order); -	if (getFilter()->isModified()) +	if (order != getFolderViewModel()->getSorter().getSortOrder())  	{ -		mFolderRoot->setSortOrder(order); +		getFolderViewModel()->setSorter(LLInventorySort(order));  		// try to keep selection onscreen, even if it wasn't to start with  		mFolderRoot->scrollToShowSelection();  	} @@ -364,12 +353,7 @@ void LLInventoryPanel::setSortOrder(U32 order)  U32 LLInventoryPanel::getSortOrder() const   {  -	return mFolderRoot->getSortOrder();  -} - -void LLInventoryPanel::requestSort() -{ -	mFolderRoot->requestSort(); +	return getFolderViewModel()->getSorter().getSortOrder();  }  void LLInventoryPanel::setSinceLogoff(BOOL sl) @@ -418,7 +402,9 @@ void LLInventoryPanel::modelChanged(U32 mask)  	{  		const LLUUID& item_id = (*items_iter);  		const LLInventoryObject* model_item = model->getObject(item_id); -		LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id); +		LLFolderViewItem* view_item = getItemByID(item_id); +		LLFolderViewModelItemInventory* viewmodel_item =  +			static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);  		// LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item  		// to folder is the fast way to get a folder without searching through folders tree. @@ -433,7 +419,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  			if (view_item)  			{  				// Request refresh on this item (also flags for filtering) -				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener(); +				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem();  				if(bridge)  				{	// Clear the display name first, so it gets properly re-built during refresh()  					bridge->clearDisplayName(); @@ -452,8 +438,11 @@ void LLInventoryPanel::modelChanged(U32 mask)  			if (model_item && view_item)  			{  				view_item->destroyView(); +				removeItemID(viewmodel_item->getUUID());  			}  			view_item = buildNewViews(item_id); +			viewmodel_item =  +				static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);  			view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);  		} @@ -510,23 +499,24 @@ void LLInventoryPanel::modelChanged(U32 mask)  			else if (model_item && view_item)  			{  				// Don't process the item if it is the root -				if (view_item->getRoot() != view_item) +				if (view_item->getParentFolder())  				{ -					LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID()); +					LLFolderViewFolder* new_parent =   (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());  					// Item has been moved.  					if (view_item->getParentFolder() != new_parent)  					{  						if (new_parent != NULL)  						{  							// Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. -							view_item->getParentFolder()->extractItem(view_item); -							view_item->addToFolder(new_parent, mFolderRoot); +							view_item->addToFolder(new_parent); +							addItemID(viewmodel_item->getUUID(), view_item);  						}  						else   						{  							// Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that   							// doesn't include trash).  Just remove the item's UI.  							view_item->destroyView(); +                            removeItemID(viewmodel_item->getUUID());  						}  					}  				} @@ -538,6 +528,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  			else if (!model_item && view_item)  			{  				// Remove the item's UI. +                removeItemID(viewmodel_item->getUUID());  				view_item->destroyView();  			}  		} @@ -549,6 +540,11 @@ LLFolderView* LLInventoryPanel::getRootFolder()  	return mFolderRoot;   } +LLUUID LLInventoryPanel::getRootFolderID() +{ +	return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); +} +  // static  void LLInventoryPanel::onIdle(void *userdata) @@ -568,16 +564,11 @@ void LLInventoryPanel::onIdle(void *userdata)  	}  } -const LLUUID& LLInventoryPanel::getRootFolderID() const -{ -	return mFolderRoot->getListener()->getUUID(); -} -  void LLInventoryPanel::initializeViews()  {  	if (!gInventory.isInventoryUsable()) return; -	rebuildViewsFor(getRootFolderID()); +	rebuildViewsFor(gInventory.getRootFolderID());  	mViewsInitialized = true; @@ -587,14 +578,14 @@ void LLInventoryPanel::initializeViews()  	if (gAgent.isFirstLogin())  	{  		// Auto open the user's library -		LLFolderViewFolder* lib_folder = mFolderRoot->getFolderByID(gInventory.getLibraryRootFolderID()); +		LLFolderViewFolder* lib_folder =   getFolderByID(gInventory.getLibraryRootFolderID());  		if (lib_folder)  		{  			lib_folder->setOpen(TRUE);  		}  		// Auto close the user's my inventory folder -		LLFolderViewFolder* my_inv_folder = mFolderRoot->getFolderByID(gInventory.getRootFolderID()); +		LLFolderViewFolder* my_inv_folder =   getFolderByID(gInventory.getRootFolderID());  		if (my_inv_folder)  		{  			my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); @@ -605,10 +596,11 @@ void LLInventoryPanel::initializeViews()  LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id)  {  	// Destroy the old view for this ID so we can rebuild it. -	LLFolderViewItem* old_view = mFolderRoot->getItemByID(id); +	LLFolderViewItem* old_view = getItemByID(id);  	if (old_view)  	{  		old_view->destroyView(); +		removeItemID(static_cast<LLFolderViewModelItemInventory*>(old_view->getViewModelItem())->getUUID());  	}  	return buildNewViews(id); @@ -628,11 +620,12 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u  	p.rect = folder_rect;  	p.parent_panel = this;  	p.tool_tip = p.name; -	p.listener =  bridge; +	p.listener = bridge; +	p.view_model = &mInventoryViewModel;  	p.use_label_suffix = useLabelSuffix;  	p.allow_multiselect = mAllowMultiSelect;  	p.show_empty_message = mShowEmptyMessage; -	p.show_load_status = mShowLoadStatus; +	p.show_item_link_overlays = mShowItemLinkOverlays;  	return LLUICtrlFactory::create<LLFolderView>(p);  } @@ -642,14 +635,6 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br  	LLFolderViewFolder::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -662,14 +647,6 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge  	LLFolderViewItem::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; @@ -682,79 +659,69 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge  LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  {   	LLInventoryObject const* objectp = gInventory.getObject(id); - 	LLUUID root_id = mFolderRoot->getListener()->getUUID(); - 	LLFolderViewFolder* parent_folder = NULL; -	LLFolderViewItem* itemp = NULL; - 	if (id == root_id) - 	{ - 		parent_folder = mFolderRoot; - 	} - 	else if (objectp) - 	{ - 		const LLUUID &parent_id = objectp->getParentUUID(); - 		parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id); -  		 -  		if (parent_folder) +	if (!objectp) return NULL; + +	LLFolderViewItem* folder_view_item = getItemByID(id); + +	const LLUUID &parent_id = objectp->getParentUUID(); +	LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); +	  + 	if (!folder_view_item && parent_folder) +  	{ +  		if (objectp->getType() <= LLAssetType::AT_NONE || +  			objectp->getType() >= LLAssetType::AT_COUNT)    		{ -  			if (objectp->getType() <= LLAssetType::AT_NONE || -  				objectp->getType() >= LLAssetType::AT_COUNT) -  			{ -  				llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " -  						<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() -  						<< llendl; -  				return NULL; -  			} +  			llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " +  					<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() +  					<< llendl; +  			return NULL; +  		} -  			if ((objectp->getType() == LLAssetType::AT_CATEGORY) && -  				(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) +  		if ((objectp->getType() == LLAssetType::AT_CATEGORY) && +  			(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) +  		{ +  			LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), +  																			objectp->getType(), +  																			LLInventoryType::IT_CATEGORY, +  																			this, +																			&mInventoryViewModel, +  																			mFolderRoot, +  																			objectp->getUUID()); +  			if (new_listener)    			{ -  				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), -  																				objectp->getType(), -  																				LLInventoryType::IT_CATEGORY, -  																				this, -  																				mFolderRoot, -  																				objectp->getUUID()); -  				if (new_listener) -  				{ -					LLFolderViewFolder* folderp = createFolderViewFolder(new_listener); -					if (folderp) -					{ -						folderp->setItemSortOrder(mFolderRoot->getSortOrder()); -					} -  					itemp = folderp; -  				} +				folder_view_item = createFolderViewFolder(new_listener);    			} -  			else -  			{ -  				// Build new view for item. -  				LLInventoryItem* item = (LLInventoryItem*)objectp; -  				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), -  																				item->getActualType(), -  																				item->getInventoryType(), -  																				this, -  																				mFolderRoot, -  																				item->getUUID(), -  																				item->getFlags()); +  		} +  		else +  		{ +  			// Build new view for item. +  			LLInventoryItem* item = (LLInventoryItem*)objectp; +  			LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), +  																			item->getActualType(), +  																			item->getInventoryType(), +  																			this, +																			&mInventoryViewModel, +  																			mFolderRoot, +  																			item->getUUID(), +  																			item->getFlags()); -  				if (new_listener) -  				{ -					itemp = createFolderViewItem(new_listener); -  				} +  			if (new_listener) +  			{ +				folder_view_item = createFolderViewItem(new_listener);    			} +  		} -  			if (itemp) -  			{ -  				itemp->addToFolder(parent_folder, mFolderRoot); -   			} -		} +  		if (folder_view_item) +  		{ +  			folder_view_item->addToFolder(parent_folder); +			addItemID(id, folder_view_item); +   		}  	}  	// If this is a folder, add the children of the folder and recursively add any   	// child folders. -	if (id.isNull() -		||	(objectp -			&& objectp->getType() == LLAssetType::AT_CATEGORY)) +	if (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY)  	{  		LLViewerInventoryCategory::cat_array_t* categories;  		LLViewerInventoryItem::item_array_t* items; @@ -771,7 +738,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  			}  		} -		if(items && parent_folder) +		if(items)  		{  			for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();  				 item_iter != items->end(); @@ -784,7 +751,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  		mInventory->unlockDirectDescendentArrays(id);  	} -	return itemp; +	return folder_view_item;  }  // bit of a hack to make sure the inventory is open. @@ -795,8 +762,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory()  	{  		LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);  		if (fchild -			&& fchild->getListener() -				&& fchild->getListener()->getUUID() == gInventory.getRootFolderID()) +			&& fchild->getViewModelItem() +			&& fchild->getViewModelItem()->getName() == "My Inventory")  		{  			fchild->setOpen(TRUE);  			break; @@ -813,7 +780,7 @@ void LLInventoryPanel::openSelected()  {  	LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem();  	if(!folder_item) return; -	LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); +	LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();  	if(!bridge) return;  	bridge->openItem();  } @@ -917,7 +884,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc  	{  		return;  	} -	mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus); +	setSelectionByID(obj_id, take_keyboard_focus);  }  void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)  @@ -930,7 +897,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::  void LLInventoryPanel::clearSelection()  { -	mFolderRoot->clearSelection(); +	mSelectThisID.setNull();  }  void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) @@ -939,7 +906,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it  	mCompletionObserver->reset();  	for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it)  	{ -		LLUUID id = (*it)->getListener()->getUUID(); +		LLUUID id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();  		LLViewerInventoryItem* inv_item = mInventory->getItem(id);  		if (inv_item && !inv_item->isFinished()) @@ -966,12 +933,12 @@ void LLInventoryPanel::doToSelected(const LLSD& userdata)  void LLInventoryPanel::doCreate(const LLSD& userdata)  { -	menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf.get(), userdata); +	menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata);  }  bool LLInventoryPanel::beginIMSession()  { -	std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); +	std::set<LLFolderViewItem*> selected_items =   mFolderRoot->getSelectionList();  	std::string name;  	static int session_num = 1; @@ -979,20 +946,19 @@ bool LLInventoryPanel::beginIMSession()  	LLDynamicArray<LLUUID> members;  	EInstantMessage type = IM_SESSION_CONFERENCE_START; -	std::set<LLUUID>::const_iterator iter; +	std::set<LLFolderViewItem*>::const_iterator iter;  	for (iter = selected_items.begin(); iter != selected_items.end(); iter++)  	{ -		LLUUID item = *iter; -		LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); +		LLFolderViewItem* folder_item = (*iter);  		if(folder_item)   		{ -			LLFolderViewEventListener* fve_listener = folder_item->getListener(); +			LLFolderViewModelItemInventory* fve_listener = static_cast<LLFolderViewModelItemInventory*>(folder_item->getViewModelItem());  			if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))  			{ -				LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); +				LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem();  				if(!bridge) return true;  				LLViewerInventoryCategory* cat = bridge->getCategory();  				if(!cat) return true; @@ -1026,9 +992,7 @@ bool LLInventoryPanel::beginIMSession()  			}  			else  			{ -				LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); -				if(!folder_item) return true; -				LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); +				LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getViewModelItem();  				if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)  				{ @@ -1069,13 +1033,13 @@ bool LLInventoryPanel::beginIMSession()  bool LLInventoryPanel::attachObject(const LLSD& userdata)  {  	// Copy selected item UUIDs to a vector. -	std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); +	std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList();  	uuid_vec_t items; -	for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();  +	for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin();  		 set_iter != selected_items.end();   		 ++set_iter)  	{ -		items.push_back(*set_iter); +		items.push_back(static_cast<LLFolderViewModelItemInventory*>((*set_iter)->getViewModelItem())->getUUID());  	}  	// Attach selected items. @@ -1222,6 +1186,80 @@ BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) co  	return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type));  } +void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem*   itemp ) +{ +	mItemMap[id] = itemp; +} + +void LLInventoryPanel::removeItemID(const LLUUID& id) +{ +	LLInventoryModel::cat_array_t categories; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(id, categories, items, TRUE); + +	mItemMap.erase(id); + +	for (LLInventoryModel::cat_array_t::iterator it = categories.begin(),    end_it = categories.end(); +		it != end_it; +		++it) +	{ +		mItemMap.erase((*it)->getUUID()); +	} + +	for (LLInventoryModel::item_array_t::iterator it = items.begin(),   end_it  = items.end(); +		it != end_it; +		++it) +	{ +		mItemMap.erase((*it)->getUUID()); +	} +} + +LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) +{ +	LLFastTimer _(FTM_GET_ITEM_BY_ID); + +	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; +	map_it = mItemMap.find(id); +	if (map_it != mItemMap.end()) +	{ +		return map_it->second; +	} + +	return NULL; +} + +LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) +{ +	LLFolderViewItem* item = getItemByID(id); +	return dynamic_cast<LLFolderViewFolder*>(item); +} + + +void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL    take_keyboard_focus ) +{ +	LLFolderViewItem* itemp = getItemByID(obj_id); +	if(itemp && itemp->getViewModelItem()) +	{ +		itemp->arrangeAndSet(TRUE, take_keyboard_focus); +		mSelectThisID.setNull(); +		return; +	} +	else +	{ +		// save the desired item to be selected later (if/when ready) +		mSelectThisID = obj_id; +	} +} + +void LLInventoryPanel::updateSelection() +{ +	if (mSelectThisID.notNull()) +	{ +		setSelectionByID(mSelectThisID, false); +	} +} +  /************************************************************************/  /* Recent Inventory Panel related class                                 */ @@ -1254,4 +1292,3 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)  	// replace bridge builder to have necessary View bridges.  	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;  } - diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 6db59afb9b..a62b97aa7d 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -30,6 +30,8 @@  #include "llassetstorage.h"  #include "lldarray.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodelinventory.h"  #include "llfloater.h"  #include "llinventory.h"  #include "llinventoryfilter.h" @@ -38,21 +40,8 @@  #include "lluictrlfactory.h"  #include <set> -class LLFolderView; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel;  class LLInvFVBridge;  class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer;  class LLInvPanelComplObserver;  class LLInventoryPanel : public LLPanel @@ -85,7 +74,6 @@ public:  		Optional<std::string>               start_folder;  		Optional<bool>						use_label_suffix;  		Optional<bool>						show_empty_message; -		Optional<bool>						show_load_status;  		Optional<LLScrollContainer::Params>	scroll;  		Optional<bool>						accepts_drag_and_drop; @@ -98,7 +86,6 @@ public:  			start_folder("start_folder"),  			use_label_suffix("use_label_suffix", true),  			show_empty_message("show_empty_message", true), -			show_load_status("show_load_status"),  			scroll("scroll"),  			accepts_drag_and_drop("accepts_drag_and_drop")  		{} @@ -156,6 +143,7 @@ public:  	// This method is called when something has changed about the inventory.  	void modelChanged(U32 mask);  	LLFolderView* getRootFolder(); +	LLUUID getRootFolderID();  	LLScrollContainer* getScrollableContainer() { return mScroller; }  	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); @@ -182,10 +170,21 @@ public:  	static void openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id); +	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); +	void removeItemID(const LLUUID& id); +	LLFolderViewItem* getItemByID(const LLUUID& id); +	LLFolderViewFolder* getFolderByID(const LLUUID& id); +	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); +	void updateSelection(); +	 	 +	LLFolderViewModelInventory* getFolderViewModel(); +	const LLFolderViewModelInventory* getFolderViewModel() const; +  protected:  	void openStartFolderOrMyInventory(); // open the first level of inventory  	void onItemsCompletion();			// called when selected items are complete +        LLUUID						mSelectThisID;	  	LLInventoryModel*			mInventory;  	LLInventoryObserver*		mInventoryObserver;  	LLInvPanelComplObserver*	mCompletionObserver; @@ -193,11 +192,13 @@ protected:  	BOOL 						mAllowMultiSelect;  	BOOL 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons  	BOOL						mShowEmptyMessage; -	BOOL						mShowLoadStatus;  	LLFolderView*				mFolderRoot;  	LLScrollContainer*			mScroller; +	LLFolderViewModelInventory	mInventoryViewModel; + +	std::map<LLUUID, LLFolderViewItem*> mItemMap;  	/**  	 * Pointer to LLInventoryFVBridgeBuilder.  	 * @@ -218,7 +219,6 @@ public:  	void setSortOrder(U32 order);  	U32 getSortOrder() const; -	void requestSort();  private:  	std::string					mSortOrderSetting; @@ -231,8 +231,7 @@ public:  	void addHideFolderType(LLFolderType::EType folder_type);  public: -	BOOL 				getIsViewsInitialized() const { return mViewsInitialized; } -	const LLUUID&		getRootFolderID() const; +	BOOL getIsViewsInitialized() const { return mViewsInitialized; }  protected:  	// Builds the UI.  Call this once the inventory is usable.  	void 				initializeViews(); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 68a3b6d1cd..0b899d34f4 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -102,7 +102,7 @@ void LLCheckFolderState::doFolder(LLFolderViewFolder* folder)  	// Counting only folders that pass the filter.  	// The listener check allow us to avoid counting the folder view  	// object itself because it has no listener assigned. -	if (folder->hasFilteredDescendants() && folder->getListener()) +	if (folder->getViewModelItem()->descendantsPassedFilter())  	{  		if (folder->isOpen())  		{ @@ -138,7 +138,7 @@ private:  // virtual  void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getListener() && folder->getListener()->getUUID() == mFolderID) +	if (folder->getViewModelItem() && static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem())->getUUID() == mFolderID)  	{  		if (!folder->isOpen())  		{ @@ -281,28 +281,21 @@ void LLLandmarksPanel::onShowOnMap()  //virtual  void LLLandmarksPanel::onShowProfile()  { -	LLFolderViewItem* cur_item = getCurSelectedItem(); +	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  	if(!cur_item)  		return; -	cur_item->getListener()->performAction(mCurrentSelectedList->getModel(),"about"); +	cur_item->performAction(mCurrentSelectedList->getModel(),"about");  }  // virtual  void LLLandmarksPanel::onTeleport()  { -	LLFolderViewItem* current_item = getCurSelectedItem(); -	if (!current_item) -	{ -		llwarns << "There are no selected list. No actions are performed." << llendl; -		return; -	} - -	LLFolderViewEventListener* listenerp = current_item->getListener(); -	if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* view_model_item = getCurSelectedViewModelItem(); +	if (view_model_item && view_model_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{ -		listenerp->openItem(); +		view_model_item->openItem();  	}  } @@ -360,7 +353,7 @@ void LLLandmarksPanel::onSelectorButtonClicked()  	LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();  	if (!cur_item) return; -	LLFolderViewEventListener* listenerp = cur_item->getListener(); +	LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem());  	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		LLSD key; @@ -376,7 +369,7 @@ void LLLandmarksPanel::updateShowFolderState()  	if (!mLandmarksInventoryPanel->getFilter())  		return; -	bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); +	bool show_all_folders =   mLandmarksInventoryPanel->getFilterSubString().empty();  	if (show_all_folders)  	{  		show_all_folders = category_has_descendents(mLandmarksInventoryPanel); @@ -417,8 +410,9 @@ void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_  bool LLLandmarksPanel::isLandmarkSelected() const   { -	LLFolderViewItem* current_item = getCurSelectedItem(); -	if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* current_item = getCurSelectedViewModelItem(); + +	if(current_item && current_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		return true;  	} @@ -440,10 +434,10 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const  void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)  { -	LLFolderViewItem* cur_item = getCurSelectedItem(); -	if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); +	if(cur_item && cur_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  -		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb); +		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getUUID(), cb);  		if (landmark)  		{  			cb(landmark); @@ -456,6 +450,17 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const  	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;  } +LLFolderViewModelItemInventory* LLLandmarksPanel::getCurSelectedViewModelItem() const +{ +	LLFolderViewItem* cur_item = getCurSelectedItem(); +	if (cur_item) +	{ +		return 	static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem()); +	} +	return NULL; +} + +  LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,  															 const std::string& tab_name,  															 const LLUUID& obj_id, @@ -466,7 +471,7 @@ LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPa  	LLFolderView* root = inventory_list->getRootFolder(); -	LLFolderViewItem* item = root->getItemByID(obj_id); +	LLFolderViewItem* item = inventory_list->getItemByID(obj_id);  	if (!item)  		return NULL; @@ -508,12 +513,12 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)  	// We have to make request to sever to get parcel_id and snaption_id.   	if(isLandmarkSelected())  	{ -		LLFolderViewItem* cur_item = getCurSelectedItem(); +		LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  		if (!cur_item) return; -		LLUUID id = cur_item->getListener()->getUUID(); +		LLUUID id = cur_item->getUUID();  		LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);  		doActionOnCurSelectedLandmark(boost::bind( -				&LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data)); +				&LLLandmarksPanel::doProcessParcelInfo, this, _1, getCurSelectedItem(), inv_item, parcel_data));  	}  } @@ -646,7 +651,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI  	// Start background fetch, mostly for My Inventory and Library  	if (expanded)  	{ -		const LLUUID &cat_id = inventory_list->getRootFolderID(); +		const LLUUID &cat_id = mCurrentSelectedList->getRootFolderID();  		// Just because the category itself has been fetched, doesn't mean its child folders have.  		/*  		  if (!gInventory.isCategoryComplete(cat_id)) @@ -665,20 +670,20 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory  {  	if (inventory_list != mFavoritesInventoryPanel)  	{ -		mFavoritesInventoryPanel->getRootFolder()->clearSelection(); +		mFavoritesInventoryPanel->clearSelection();  	}  	if (inventory_list != mLandmarksInventoryPanel)  	{ -		mLandmarksInventoryPanel->getRootFolder()->clearSelection(); +		mLandmarksInventoryPanel->clearSelection();  	}  	if (inventory_list != mMyInventoryPanel)  	{ -		mMyInventoryPanel->getRootFolder()->clearSelection(); +		mMyInventoryPanel->clearSelection();  	}  	if (inventory_list != mLibraryInventoryPanel)  	{ -		mLibraryInventoryPanel->getRootFolder()->clearSelection(); +		mLibraryInventoryPanel->clearSelection();  	}  } @@ -731,14 +736,9 @@ void LLLandmarksPanel::onActionsButtonClick()  {  	LLToggleableMenu* menu = mGearFolderMenu; -	LLFolderViewItem* cur_item = NULL;  	if(mCurrentSelectedList)  	{ -		cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem(); -		if(!cur_item) -			return; - -		LLFolderViewEventListener* listenerp = cur_item->getListener(); +		LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();  		if(!listenerp)  			return; @@ -776,6 +776,9 @@ void LLLandmarksPanel::onTrashButtonClick() const  void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  { +	LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem(); +	LLFolderViewItem* item = getCurSelectedItem(); +  	std::string command_name = userdata.asString();  	if("add_landmark" == command_name)  	{ @@ -791,24 +794,24 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  	}   	else if ("category" == command_name)  	{ -		LLFolderViewItem* item = getCurSelectedItem();  		if (item && mCurrentSelectedList == mLandmarksInventoryPanel)  		{ -			LLFolderViewEventListener* folder_bridge = NULL; -			if (item-> getListener()->getInventoryType() +			LLFolderViewModelItem* folder_bridge = NULL; + +			if (view_model->getInventoryType()  					== LLInventoryType::IT_LANDMARK)  			{  				// for a landmark get parent folder bridge -				folder_bridge = item->getParentFolder()->getListener(); +				folder_bridge = item->getParentFolder()->getViewModelItem();  			} -			else if (item-> getListener()->getInventoryType() +			else if (view_model->getInventoryType()  					== LLInventoryType::IT_CATEGORY)  			{  				// for a folder get its own bridge -				folder_bridge = item->getListener(); +				folder_bridge = view_model;  			} -			menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), +			menu_create_inventory_item(mCurrentSelectedList,  					dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(  							"category"), gInventory.findCategoryUUIDForType(  							LLFolderType::FT_LANDMARK)); @@ -816,7 +819,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  		else  		{  			//in case My Landmarks tab is completely empty (thus cannot be determined as being selected) -			menu_create_inventory_item(mLandmarksInventoryPanel->getRootFolder(), NULL, LLSD("category"),  +			menu_create_inventory_item(mLandmarksInventoryPanel, NULL,  LLSD("category"),   				gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));  			if (mMyLandmarksAccordionTab) @@ -834,9 +837,9 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const  	std::string command_name = userdata.asString();      if("copy_slurl" == command_name)  	{ -    	LLFolderViewItem* cur_item = getCurSelectedItem(); +    	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  		if(cur_item) -			LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); +			LLLandmarkActions::copySLURLtoClipboard(cur_item->getUUID());  	}  	else if ( "paste" == command_name)  	{ @@ -977,18 +980,13 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  	{  		if (!root_folder_view) return false; -		std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); +		std::set<LLFolderViewItem*> selected_uuids =    root_folder_view->getSelectionList();  		// Allow to execute the command only if it can be applied to all selected items. -		for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) +		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_uuids.begin(); iter != selected_uuids.end(); ++iter)  		{ -			LLFolderViewItem* item = root_folder_view->getItemByID(*iter); +			LLFolderViewItem* item = *iter; -			// If no item is found it might be a folder id. -			if (!item) -			{ -				item = root_folder_view->getFolderByID(*iter); -			}  			if (!item) return false;  			if (!canItemBeModified(command_name, item)) return false; @@ -1012,10 +1010,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  		if ("show_on_map" == command_name)  		{ -			LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem(); +			LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  			if (!cur_item) return false; -			LLViewerInventoryItem* inv_item = cur_item->getInventoryItem(); +			LLViewerInventoryItem* inv_item = dynamic_cast<LLViewerInventoryItem*>(cur_item->getInventoryObject());  			if (!inv_item) return false;  			LLUUID asset_uuid = inv_item->getAssetUUID(); @@ -1049,7 +1047,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  	{  		if (mCurrentSelectedList)  		{ -			std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selection =    mCurrentSelectedList->getRootFolder()->getSelectionList();  			if (!selection.empty())  			{  				return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); @@ -1105,27 +1103,23 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param)  	{  		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); -		std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); +		std::set<LLFolderViewItem*> selected_items =    root_folder_view->getSelectionList();  		// Iterate through selected items to find out if any of these items are in Trash  		// or all the items are in Trash category. -		for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) +		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_items.begin(); iter != selected_items.end(); ++iter)  		{ -			LLFolderViewItem* item = root_folder_view->getItemByID(*iter); +			LLFolderViewItem* item = *iter;  			// If no item is found it might be a folder id. -			if (!item) -			{ -				item = root_folder_view->getFolderByID(*iter); -			}  			if (!item) continue; -			LLFolderViewEventListener* listenerp = item->getListener(); +			LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());  			if(!listenerp) continue;  			// Trash category itself should not be included because it can't be  			// actually restored from trash. -			are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id; +			are_all_items_in_trash &= listenerp->isItemInTrash() &&    listenerp->getUUID() != trash_id;  			// If there are any selected items in Trash including the Trash category itself  			// we show "Restore Item" in context menu and hide other irrelevant items. @@ -1164,7 +1158,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	bool can_be_modified = false;  	// landmarks can be modified in any other accordion... -	if (item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	if (static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem())->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		can_be_modified = true; @@ -1202,7 +1196,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	if (can_be_modified)  	{ -		LLFolderViewEventListener* listenerp = item->getListener(); +		LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());  		if ("cut" == command_name)  		{ @@ -1262,8 +1256,9 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg  				LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data);  				if (item)  				{ -					LLFolderViewItem* fv_item = (mCurrentSelectedList && mCurrentSelectedList->getRootFolder()) ? -						mCurrentSelectedList->getRootFolder()->getItemByID(item->getUUID()) : NULL; +					LLFolderViewItem* fv_item = mCurrentSelectedList +						? mCurrentSelectedList->getItemByID(item->getUUID()) +						: NULL;  					if (fv_item)  					{ @@ -1391,7 +1386,7 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)  static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)  {  	// When search is cleared, restore the old folder state. -	if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "") +	if (!inventory_list->getFilterSubString().empty() && string == "")  	{  		inventory_list->setFilterSubString(LLStringUtil::null);  		// Re-open folders that were open before @@ -1405,7 +1400,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin  	}  	// save current folder open state if no filter currently applied -	if (inventory_list->getRootFolder()->getFilterSubString().empty()) +	if (inventory_list->getFilterSubString().empty())  	{  		inventory_list->saveFolderState();  	} diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b2f4e92473..aa5f69739d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -44,6 +44,7 @@ class LLMenuGL;  class LLToggleableMenu;  class LLInventoryPanel;  class LLPlacesInventoryPanel; +class LLFolderViewModelItemInventory;  class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver  { @@ -87,6 +88,7 @@ protected:  	bool isReceivedFolderSelected() const;  	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);  	LLFolderViewItem* getCurSelectedItem() const; +	LLFolderViewModelItemInventory* getCurSelectedViewModelItem() const;  	/**  	 * Selects item with "obj_id" in "inventory_list" and scrolls accordion diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c11597f532..6cef1f877b 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -47,12 +47,14 @@  #include "llresmgr.h"  #include "llscrollcontainer.h"  #include "llsdserialize.h" +#include "llsdparam.h"  #include "llspinctrl.h"  #include "lltoggleablemenu.h"  #include "lltooldraganddrop.h"  #include "llviewermenu.h"  #include "llviewertexturelist.h"  #include "llsidepanelinventory.h" +#include "llfolderview.h"  const std::string FILTERS_FILENAME("filters.xml"); @@ -171,7 +173,10 @@ BOOL LLPanelMainInventory::postBuild()  			{  				LLSD recent_items = savedFilterState.get(  					recent_items_panel->getFilter()->getName()); -				recent_items_panel->getFilter()->fromLLSD(recent_items); +				LLInventoryFilter::Params p; +				LLParamSDParser parser; +				parser.readSD(recent_items, p); +				recent_items_panel->getFilter()->fromParams(p);  			}  		} @@ -212,21 +217,25 @@ LLPanelMainInventory::~LLPanelMainInventory( void )  		if (filter)  		{  			LLSD filterState; -			filter->toLLSD(filterState); -			filterRoot[filter->getName()] = filterState; +			LLInventoryFilter::Params p; +			filter->toParams(p); +			if (p.validateBlock(false)) +			{ +				LLParamSDParser().writeSD(filterState, p); +				filterRoot[filter->getName()] = filterState; +			}  		}  	} -	LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); -	if (recent_items_panel) +	LLInventoryFilter* filter = findChild<LLInventoryPanel>("Recent Items")->getFilter(); +	if (filter)  	{ -		LLInventoryFilter* filter = recent_items_panel->getFilter(); -		if (filter) -		{ -			LLSD filterState; -			filter->toLLSD(filterState); -			filterRoot[filter->getName()] = filterState; -		} +		LLSD filterState; +		LLInventoryFilter::Params p; +		filter->toParams(p); +		LLParamSDParser parser; +		parser.writeSD(filterState, p); +		filterRoot[filter->getName()] = filterState;  	}  	std::ostringstream filterSaveName; @@ -306,7 +315,7 @@ void LLPanelMainInventory::newWindow()  void LLPanelMainInventory::doCreate(const LLSD& userdata)  { -	menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); +	menu_create_inventory_item(getPanel(), NULL, userdata);  }  void LLPanelMainInventory::resetFilters() @@ -417,7 +426,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string )  	}  	// save current folder open state if no filter currently applied -	if (!mActivePanel->getRootFolder()->isFilterModified()) +	if (!mActivePanel->getFilter()->isNotDefault())  	{  		mSavedFolderState->setApply(FALSE);  		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -972,7 +981,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata)  		return;  	} -	const LLUUID& item_id = current_item->getListener()->getUUID(); +	const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  	LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);  	if (preview_texture)  	{ @@ -1045,7 +1054,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		const LLUUID item_id = current_item->getListener()->getUUID(); +		const LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item)  		{ @@ -1060,7 +1069,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		current_item->getListener()->performAction(getActivePanel()->getModel(), "goto"); +		static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto");  	}  	if (command_name == "find_links") @@ -1070,8 +1079,8 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		const LLUUID& item_id = current_item->getListener()->getUUID(); -		const std::string &item_name = current_item->getListener()->getName(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); +		const std::string &item_name = current_item->getViewModelItem()->getName();  		mFilterSubString = item_name;  		LLInventoryFilter *filter = mActivePanel->getFilter();  		filter->setFilterSubString(item_name); @@ -1089,11 +1098,11 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)  	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  	if (current_item)   	{ -		LLViewerInventoryItem *inv_item = current_item->getInventoryItem(); +		LLViewerInventoryItem *inv_item = dynamic_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryObject());  		if(inv_item)  		{  			bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); -			LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType(); +			LLInventoryType::EType curr_type = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryType();  			return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT);  		}  	} @@ -1110,15 +1119,14 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  		if (root)  		{  			can_delete = TRUE; -			std::set<LLUUID> selection_set = root->getSelectionList(); +			std::set<LLFolderViewItem*> selection_set = root->getSelectionList();  			if (selection_set.empty()) return FALSE; -			for (std::set<LLUUID>::iterator iter = selection_set.begin(); +			for (std::set<LLFolderViewItem*>::iterator iter =    selection_set.begin();  				 iter != selection_set.end();  				 ++iter)  			{ -				const LLUUID &item_id = (*iter); -				LLFolderViewItem *item = root->getItemByID(item_id); -				const LLFolderViewEventListener *listener = item->getListener(); +				LLFolderViewItem *item = *iter; +				const LLFolderViewModelItemInventory *listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem());  				llassert(listener);  				if (!listener) return FALSE;  				can_delete &= listener->isItemRemovable(); @@ -1136,7 +1144,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	{  		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item && item->getIsLinkType() && !item->getIsBrokenLink())  		{ @@ -1148,11 +1156,11 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	if (command_name == "find_links")  	{  		LLFolderView* root = getActivePanel()->getRootFolder(); -		std::set<LLUUID> selection_set = root->getSelectionList(); +		std::set<LLFolderViewItem*> selection_set = root->getSelectionList();  		if (selection_set.size() != 1) return FALSE;  		LLFolderViewItem* current_item = root->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLInventoryObject *obj = gInventory.getObject(item_id);  		if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType()))  		{ @@ -1165,7 +1173,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	{  		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item && item->getIsBrokenLink())  		{ diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 66c9c323cb..3547156197 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -94,7 +94,7 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel()  	mInventoryPanel->setShape(inventory_placeholder_rect);  	// Set the sort order newest to oldest -	mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	 +	mInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_DATE);  	mInventoryPanel->getFilter()->markDefault();  	// Set selection callback for proper update of inventory status buttons @@ -139,7 +139,7 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const  	if (mInventoryPanel)  	{ -		const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); +		LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();  		if (inbox_folder)  		{ diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 678e4f2843..6e5a522297 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -29,7 +29,8 @@  #include "llpanelmarketplaceinboxinventory.h"  #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -110,6 +111,7 @@ void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& para  																	LLAssetType::AT_CATEGORY,  																	LLInventoryType::IT_CATEGORY,  																	this, +																	&mInventoryViewModel,  																	NULL,  																	root_id); @@ -121,14 +123,6 @@ LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge  	LLInboxFolderViewFolder::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); -	 -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -141,14 +135,6 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b  	LLInboxFolderViewItem::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; @@ -207,7 +193,7 @@ void LLInboxFolderViewFolder::computeFreshness()  	if (last_expansion_utc > 0)  	{ -		mFresh = (mCreationDate > last_expansion_utc); +		mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);  #if DEBUGGING_FRESHNESS  		if (mFresh) @@ -229,15 +215,16 @@ void LLInboxFolderViewFolder::deFreshify()  	gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());  } -void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) -{  -	mCreationDate = creation_date_utc;  - -	if (mParentFolder == mRoot) -	{ -		computeFreshness(); -	} -} +// TODO RN: move this behavior to modelview? +//void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) +//{  +//	mCreationDate = creation_date_utc;  +// +//	if (LLFolderViewItem::mParentFolder == mRoot) +//	{ +//		computeFreshness(); +//	} +//}  //  // LLInboxFolderViewItem Implementation @@ -253,9 +240,9 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p)  #endif  } -BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder)  { -	BOOL retval = LLFolderViewItem::addToFolder(folder, root); +	BOOL retval = LLFolderViewItem::addToFolder(folder);  #if SUPPORTING_FRESH_ITEM_COUNT  	// Compute freshness if our parent is the root folder for the inbox @@ -303,7 +290,7 @@ void LLInboxFolderViewItem::computeFreshness()  	if (last_expansion_utc > 0)  	{ -		mFresh = (mCreationDate > last_expansion_utc); +		mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);  #if DEBUGGING_FRESHNESS  		if (mFresh) diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d6b827ee3e..209f3a4098 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -81,8 +81,6 @@ public:  	bool isFresh() const { return mFresh; }  protected: -	void setCreationDate(time_t creation_date_utc); -  	bool mFresh;  }; @@ -102,7 +100,7 @@ public:  	LLInboxFolderViewItem(const Params& p); -	BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); +	BOOL addToFolder(LLFolderViewFolder* folder);  	BOOL handleDoubleClick(S32 x, S32 y, MASK mask);  	void draw(); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index ff62cb23db..2885dd6266 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -28,8 +28,8 @@  #include "llpanelmarketplaceoutboxinventory.h" -#include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -77,6 +77,7 @@ void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par  																	LLAssetType::AT_CATEGORY,  																	LLInventoryType::IT_CATEGORY,  																	this, +																	&mInventoryViewModel,  																	NULL,  																	root_id); @@ -88,14 +89,6 @@ LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridg  	LLOutboxFolderViewFolder::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); -	 -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -108,14 +101,6 @@ LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge *  	LLFolderViewItem::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index f84d6e5cc1..450e1f7ed0 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -71,12 +71,13 @@  /// Class LLTaskInvFVBridge  ///---------------------------------------------------------------------------- -class LLTaskInvFVBridge : public LLFolderViewEventListener +class LLTaskInvFVBridge : public LLFolderViewModelItemInventory  {  protected:  	LLUUID mUUID;  	std::string mName;  	mutable std::string mDisplayName; +	mutable std::string mSearchableName;  	LLPanelObjectInventory* mPanel;  	U32 mFlags;  	LLAssetType::EType mAssetType;	 @@ -102,26 +103,29 @@ public:  	S32 getPrice();  	static bool commitBuyItem(const LLSD& notification, const LLSD& response); -	// LLFolderViewEventListener functionality +	// LLFolderViewModelItemInventory functionality  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const; +	virtual const std::string& getSearchableName() const; +  	virtual PermissionMask getPermissionMask() const { return PERM_NONE; }  	/*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; }  	virtual const LLUUID& getUUID() const { return mUUID; }  	virtual time_t getCreationDate() const; +	virtual void setCreationDate(time_t creation_date_utc); +  	virtual LLUIImagePtr getIcon() const;  	virtual void openItem();  	virtual BOOL canOpenItem() const { return FALSE; }  	virtual void closeItem() {} -	virtual void previewItem();  	virtual void selectItem() {}  	virtual BOOL isItemRenameable() const;  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL isItemMovable() const;  	virtual BOOL isItemRemovable() const;  	virtual BOOL removeItem(); -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); -	virtual void move(LLFolderViewEventListener* parent_listener); +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); +	virtual void move(LLFolderViewModelItem* parent_listener);	  	virtual BOOL isItemCopyable() const;  	virtual BOOL copyToClipboard() const;  	virtual BOOL cutToClipboard() const; @@ -131,11 +135,15 @@ public:  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	virtual void performAction(LLInventoryModel* model, std::string action);  	virtual BOOL isUpToDate() const { return TRUE; } -	virtual BOOL hasChildren() const { return FALSE; } +	virtual bool hasChildren() const { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }  	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +	virtual EInventorySortGroup getSortGroup() const { return SG_ITEM; } +	virtual LLInventoryObject* getInventoryObject() const { return findInvObject(); } +  	// LLDragAndDropBridge functionality +	virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_WORLD; }  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -330,15 +338,27 @@ const std::string& LLTaskInvFVBridge::getDisplayName() const  		}  	} +	mSearchableName.assign(mDisplayName + getLabelSuffix()); +  	return mDisplayName;  } +const std::string& LLTaskInvFVBridge::getSearchableName() const +{ +	return mSearchableName; +} + +  // BUG: No creation dates for task inventory  time_t LLTaskInvFVBridge::getCreationDate() const  {  	return 0;  } +void LLTaskInvFVBridge::setCreationDate(time_t creation_date_utc) +{} + +  LLUIImagePtr LLTaskInvFVBridge::getIcon() const  {  	const BOOL item_is_multi = (mFlags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS); @@ -352,11 +372,6 @@ void LLTaskInvFVBridge::openItem()  	lldebugs << "LLTaskInvFVBridge::openItem()" << llendl;  } -void LLTaskInvFVBridge::previewItem() -{ -	openItem(); -} -  BOOL LLTaskInvFVBridge::isItemRenameable() const  {  	if(gAgent.isGodlike()) return TRUE; @@ -467,7 +482,7 @@ BOOL LLTaskInvFVBridge::removeItem()  	return FALSE;  } -void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void   LLTaskInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)  {  	if (!mPanel)  	{ @@ -507,7 +522,7 @@ void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>&  	}  } -void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener) +void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener)  {  } @@ -709,7 +724,7 @@ public:  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL isItemRemovable() const;  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); -	virtual BOOL hasChildren() const; +	virtual bool hasChildren() const;  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -717,6 +732,7 @@ public:  							std::string& tooltip_msg);  	virtual BOOL canOpenItem() const { return TRUE; }  	virtual void openItem(); +	virtual EInventorySortGroup getSortGroup() const { return SG_NORMAL_FOLDER; }  };  LLTaskCategoryBridge::LLTaskCategoryBridge( @@ -767,7 +783,7 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	hide_context_entries(menu, items, disabled_items);  } -BOOL LLTaskCategoryBridge::hasChildren() const +bool LLTaskCategoryBridge::hasChildren() const  {  	// return TRUE if we have or do know know if we have children.  	// *FIX: For now, return FALSE - we will know for sure soon enough. @@ -1546,9 +1562,11 @@ void LLPanelObjectInventory::reset()  	p.tool_tip= LLTrans::getString("PanelContentsTooltip");  	p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL);  	p.folder_indentation = -14; // subtract space normally reserved for folder expanders +	p.view_model = &mInventoryViewModel;  	mFolders = LLUICtrlFactory::create<LLFolderView>(p);  	// this ensures that we never say "searching..." or "no items found" -	mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); +	//TODO RN: make this happen by manipulating filter object directly +	static_cast<LLInventoryFilter*>(mFolders->getFolderViewModel()->getFilter())->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);  	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);  	if (hasFocus()) @@ -1608,7 +1626,7 @@ void LLPanelObjectInventory::updateInventory()  	//		<< " panel UUID: " << panel->mTaskUUID << "\n"  	//		<< " task  UUID: " << object->mID << llendl;  	// We're still interested in this task's inventory. -	std::set<LLUUID> selected_items; +	std::set<LLFolderViewItem*> selected_items;  	BOOL inventory_has_focus = FALSE;  	if (mHaveInventory)  	{ @@ -1646,11 +1664,11 @@ void LLPanelObjectInventory::updateInventory()  	}  	// restore previous selection -	std::set<LLUUID>::iterator selection_it; +	std::set<LLFolderViewItem*>::iterator selection_it;  	BOOL first_item = TRUE;  	for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it)  	{ -		LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); +		LLFolderViewItem* selected_item = (*selection_it);  		if (selected_item)  		{  			//HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1687,18 +1705,6 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root  	bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);  	if(bridge)  	{ -		//LLFolderViewFolder* new_folder = NULL; -		//LLFolderViewFolder::Params p; -		//p.name = inventory_root->getName(); -		//p.icon = LLUI::getUIImage("Inv_FolderClosed"); -		//p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); -		//p.root = mFolders; -		//p.listener = bridge; -		//p.tool_tip = p.name; -		//new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); -		//new_folder->addToFolder(mFolders, mFolders); -		//new_folder->toggleOpen(); -  		createViewsForCategory(&contents, inventory_root, mFolders);  	}  } @@ -1731,8 +1737,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  			{  				LLFolderViewFolder::Params p;  				p.name = obj->getName(); -				p.icon = LLUI::getUIImage("Inv_FolderClosed"); -				p.icon_open = LLUI::getUIImage("Inv_FolderOpen");  				p.root = mFolders;  				p.listener = bridge;  				p.tool_tip = p.name; @@ -1744,7 +1748,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  			{  				LLFolderViewItem::Params params;  				params.name(obj->getName()); -				params.icon(bridge->getIcon());  				params.creation_date(bridge->getCreationDate());  				params.root(mFolders);  				params.listener(bridge); @@ -1752,7 +1755,7 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  				params.tool_tip = params.name;  				view = LLUICtrlFactory::create<LLFolderViewItem> (params);  			} -			view->addToFolder(folder, mFolders); +			view->addToFolder(folder);  		}  	} diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 607b705f7f..7e857f8b31 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -29,6 +29,7 @@  #include "llvoinventorylistener.h"  #include "llpanel.h" +#include "llinventorypanel.h" // for LLFolderViewModelInventory  #include "llinventory.h" @@ -94,6 +95,7 @@ private:  	BOOL mHaveInventory;  	BOOL mIsInventoryEmpty;  	BOOL mInventoryNeedsUpdate; +	LLFolderViewModelInventory	mInventoryViewModel;	  };  #endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..d690a18477 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -270,7 +270,7 @@ private:  		if (inventory_panel->getVisible())  		{ -			inventory_panel->setSortOrder(sort_order); +			inventory_panel->getFolderViewModel()->setSorter(sort_order);  		}  		else  		{ @@ -738,7 +738,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string)  	}  	// save current folder open state if no filter currently applied -	if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty()) +	if (mInventoryItemsPanel->getFilterSubString().empty())  	{  		mSavedFolderState->setApply(FALSE);  		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -885,13 +885,13 @@ LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionT  	{  		if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible())  		{ -			std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selected_items =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); -			result.second = selected_uuids.size(); +			result.second = selected_items.size();  			if (result.second == 1)  			{ -				result.first = getWearableTypeByItemUUID(*(selected_uuids.begin())); +				result.first = getWearableTypeByItemUUID(static_cast<LLFolderViewModelItemInventory*>((*selected_items.begin())->getViewModelItem())->getUUID());  			}  		}  		else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id)  		LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem();  		if (!curr_item) return; -		LLFolderViewEventListener* listenerp  = curr_item->getListener(); +		LLFolderViewModelItemInventory* listenerp  = static_cast<LLFolderViewModelItemInventory*>(curr_item->getViewModelItem());  		if (!listenerp) return;  		selected_id = listenerp->getUUID(); @@ -1327,9 +1327,13 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)  	void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back;  	if (mInventoryItemsPanel->getVisible())  	{ -		std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - -		std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1)); +		std::set<LLFolderViewItem*> item_set =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); +		for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(),    end_it = item_set.end(); +			it != end_it; +			++it) +		{ +			uuid_list.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +		}  	}  	else if (mWearablesListViewPanel->getVisible())  	{ @@ -1374,13 +1378,13 @@ void LLPanelOutfitEdit::saveListSelection()  {  	if(mWearablesListViewPanel->getVisible())  	{ -		std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); +		std::set<LLFolderViewItem*> selected_ids =    mInventoryItemsPanel->getRootFolder()->getSelectionList();  		if(!selected_ids.size()) return; -		for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		for (std::set<LLFolderViewItem*>::const_iterator item_id =    selected_ids.begin(); item_id != selected_ids.end(); ++item_id)  		{ -			mWearableItemsList->selectItemByUUID(*item_id, true); +			mWearableItemsList->selectItemByUUID(static_cast<LLFolderViewModelItemInventory*>((*item_id)->getViewModelItem())->getUUID(),    true);  		}  		mWearableItemsList->scrollToShowFirstSelectedItem();  	} @@ -1398,7 +1402,7 @@ void LLPanelOutfitEdit::saveListSelection()  		for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id)  		{ -			LLFolderViewItem* item = root->getItemByID(*item_id); +			LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id);  			if (!item) continue;  			LLFolderViewFolder* parent = item->getParentFolder(); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index fe4cc0f55f..af29ab7ea9 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -85,34 +85,33 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  { +	std::vector<std::string> items; +	std::vector<std::string> disabled_items; + +	LLInventoryPanel* inv_panel = mInventoryPanel.get(); +	bool is_open = false; +	if (inv_panel)  	{ -		std::vector<std::string> items; -		std::vector<std::string> disabled_items; +		LLFolderViewFolder* folder =  dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); +		is_open = (NULL != folder) && folder->isOpen(); +	} -		LLInventoryPanel* inv_panel = mInventoryPanel.get(); -		bool is_open = false; -		if (inv_panel) -		{ -			LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); -			is_open = (NULL != folder) && folder->isOpen(); -		} +	// collect all items' names +	fill_items_with_menu_items(items, menu); -		// collect all items' names -		fill_items_with_menu_items(items, menu); +	// remove expand or collapse menu item depend on folder state +	std::string collapse_expand_item_to_hide(is_open ? "expand" :  "collapse"); +	std::vector<std::string>::iterator it = std::find(items.begin(),  items.end(), collapse_expand_item_to_hide); +	if (it != items.end())	items.erase(it); -		// remove expand or collapse menu item depend on folder state -		std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); -		std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); -		if (it != items.end())	items.erase(it); -		// Disabled items are processed via LLLandmarksPanel::isActionEnabled() -		// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601  +	// Disabled items are processed via LLLandmarksPanel::isActionEnabled() +	// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601  -		// repeat parent functionality - 		sSelf = getHandle(); // necessary for "New Folder" functionality +	// repeat parent functionality + 	sSelf = getHandle(); // necessary for "New Folder" functionality -		hide_context_entries(menu, items, disabled_items); -	} +	hide_context_entries(menu, items, disabled_items);  }  //virtual @@ -140,7 +139,7 @@ LLFolderViewFolder* LLPlacesFolderBridge::getFolder()  	LLInventoryPanel* inv_panel = mInventoryPanel.get();  	if (inv_panel)  	{ -		folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); +		folder =    dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID));  	}  	return folder; @@ -152,6 +151,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  	LLAssetType::EType actual_asset_type,  	LLInventoryType::EType inv_type,  	LLInventoryPanel* inventory, +	LLFolderViewModelInventory* view_model,  	LLFolderView* root,  	const LLUUID& uuid,  	U32 flags/* = 0x00*/) const @@ -165,6 +165,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl;  		}  		new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, root, uuid, flags); +		new_listener->setRootViewModel(view_model);  		break;  	case LLAssetType::AT_CATEGORY:  		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) @@ -175,12 +176,14 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  				actual_asset_type,  				inv_type,  				inventory, +				view_model,  				root,  				uuid,  				flags);  			break;  		}  		new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid); +		new_listener->setRootViewModel(view_model);  		break;  	default:  		new_listener = LLInventoryFVBridgeBuilder::createBridge( @@ -188,6 +191,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  			actual_asset_type,  			inv_type,  			inventory, +			view_model,  			root,  			uuid,  			flags); diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h index 52beacef9c..791502990b 100644 --- a/indra/newview/llplacesinventorybridge.h +++ b/indra/newview/llplacesinventorybridge.h @@ -89,6 +89,7 @@ public:  											LLAssetType::EType actual_asset_type,  											LLInventoryType::EType inv_type,  											LLInventoryPanel* inventory, +											LLFolderViewModelInventory* view_model,  											LLFolderView* root,  											const LLUUID& uuid,  											U32 flags = 0x00) const; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index f7823f4fe8..d95d5eac19 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -30,7 +30,8 @@  #include "llplacesinventorypanel.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" +#include "llfolderview.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -86,12 +87,13 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par  													LLAssetType::AT_CATEGORY,  													LLInventoryType::IT_CATEGORY,  													this, +													&mInventoryViewModel,  													NULL,  													root_id);  	p.parent_panel = this;  	p.allow_multiselect = mAllowMultiSelect;  	p.use_ellipses = true;	// truncate inventory item text so remove horizontal scroller -	mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); +	mFolderRoot = LLUICtrlFactory::create<LLPlacesFolderView>(p);  } @@ -161,7 +163,7 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask)  	// then determine its type and set necessary menu handle  	if (getCurSelectedItem())  	{ -		LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); +		LLInventoryType::EType inventory_type = static_cast<LLFolderViewModelItemInventory*>(getCurSelectedItem()->getViewModelItem())->getInventoryType();  		inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type);  		if (it_handle != mMenuHandlesByInventoryType.end()) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 853656905c..b143240187 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -38,7 +38,7 @@  #include "llfiltereditor.h"  #include "llfloaterreg.h"  #include "llfloaterworldmap.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "lloutfitobserver.h"  #include "llpaneleditwearable.h"  #include "llpaneloutfitsinventory.h" @@ -267,11 +267,11 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked()  		if (inventory_panel)  		{  			LLFolderView* root = inventory_panel->getRootFolder(); -			LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); +			LLFolderViewItem *outfit_folder =    inventory_panel->getItemByID(outfit_link->getLinkedUUID());  			if (outfit_folder)  			{  				outfit_folder->setOpen(!outfit_folder->isOpen()); -				root->setSelectionFromRoot(outfit_folder,TRUE); +				root->setSelection(outfit_folder,TRUE);  				root->scrollToShowSelection();  			}  		} diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 4f9ab318a5..47bd620fc6 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -36,6 +36,7 @@  #include "llfirstuse.h"  #include "llfloatersidepanelcontainer.h"  #include "llfoldertype.h" +#include "llfolderview.h"  #include "llhttpclient.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h" @@ -383,10 +384,10 @@ void LLSidepanelInventory::onToggleInboxBtn()  	{  		inboxPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));  		if (inboxPanel->isInVisibleChain()) -		{ -			gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); -		} +	{ +		gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());  	} +}  	else  	{  		gSavedPerAccountSettings.setS32("InventoryInboxHeight", inboxPanel->getTargetDim()); @@ -472,7 +473,7 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action)  		}  	} -	current_item->getListener()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); +	static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(mPanelMainInventory->getActivePanel()->getModel(), action);  }  void LLSidepanelInventory::onWearButtonClicked() @@ -662,7 +663,7 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()  			return NULL;  		}  	} -	const LLUUID &item_id = current_item->getListener()->getUUID(); +	const LLUUID &item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  	LLInventoryItem *item = gInventory.getItem(item_id);  	return item;  } @@ -671,7 +672,7 @@ U32 LLSidepanelInventory::getSelectedCount()  {  	int count = 0; -	std::set<LLUUID> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); +	std::set<LLFolderViewItem*> selection_list =    mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList();  	count += selection_list.size();  	if ((count == 0) && mInboxEnabled && (mInventoryPanelInbox != NULL)) @@ -722,9 +723,9 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox)  	updateVerbs();  } -std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() +std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList()  { -	std::set<LLUUID> inventory_selected_uuids; +	std::set<LLFolderViewItem*> inventory_selected_uuids;  	if (mInboxEnabled && (mInventoryPanelInbox != NULL))  	{ diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index a33607f50d..e8b2808d4f 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -63,7 +63,7 @@ public:  	BOOL isMainInventoryPanelActive() const;  	void clearSelections(bool clearMain, bool clearInbox); -	std::set<LLUUID> getInboxSelectionList(); +    std::set<LLFolderViewItem*> getInboxSelectionList();  	void showItemInfoPanel();  	void showTaskInfoPanel(); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ed9faa0706..4a9e106687 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -39,7 +39,7 @@  #include "llfocusmgr.h"  #include "llviewertexture.h"  #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llinventory.h"  #include "llinventoryfunctions.h"  #include "llinventorymodelbackgroundfetch.h" @@ -181,7 +181,7 @@ protected:  	F32					mContextConeOpacity;  	LLSaveFolderState	mSavedFolderState;  	BOOL				mSelectedItemPinned; -	 +  	LLRadioGroup*		mModeSelector;  	LLScrollListCtrl*	mLocalScrollCtrl;  }; @@ -358,7 +358,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)  		{  			if (!root_folder->getCurSelectedItem())  			{ -				LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); +				LLFolderViewItem* itemp =    mInventoryPanel->getItemByID(gInventory.getRootFolderID());  				if (itemp)  				{  					root_folder->setSelection(itemp, FALSE, FALSE); @@ -623,10 +623,9 @@ void LLFloaterTexturePicker::draw()  		LLFolderView* folder_view = mInventoryPanel->getRootFolder();  		if (!folder_view) return; -		LLInventoryFilter* filter = folder_view->getFilter(); -		if (!filter) return; +		LLFolderViewFilter* filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); -		bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && +		bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter->getCurrentGeneration() &&  				filter->isNotDefault();  		// After inventory panel filter is applied we have to update @@ -637,8 +636,9 @@ void LLFloaterTexturePicker::draw()  		if (!is_filter_active && !mSelectedItemPinned)  		{  			folder_view->setPinningSelectedItem(mSelectedItemPinned); -			folder_view->dirtyFilter(); -			folder_view->arrangeFromRoot(); +			folder_view->getViewModelItem()->dirtyFilter(); +			//TODO RN: test..still works without this? +			//folder_view->arrangeFromRoot();  			mSelectedItemPinned = TRUE;  		} @@ -800,7 +800,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem  	if (items.size())  	{  		LLFolderViewItem* first_item = items.front(); -		LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); +		LLInventoryItem* itemp = gInventory.getItem(static_cast<LLFolderViewModelItemInventory*>(first_item->getViewModelItem())->getUUID());  		mNoCopyTextureSelected = FALSE;  		if (itemp)  		{ @@ -982,7 +982,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  	else if (mInventoryPanel->getFilterSubString().empty())  	{  		// first letter in search term, save existing folder open state -		if (!mInventoryPanel->getRootFolder()->isFilterModified()) +		if (!mInventoryPanel->getFilter()->isNotDefault())  		{  			mSavedFolderState.setApply(FALSE);  			mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); @@ -1280,7 +1280,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  		// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.  		else if (mCommitOnSelection || op == TEXTURE_SELECT)  			mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - +			  		if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work.  		{  			setTentative( FALSE ); @@ -1292,10 +1292,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  			}  			else  			{ -				mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); -				lldebugs << "mImageItemID: " << mImageItemID << llendl; -				mImageAssetID = floaterp->getAssetID(); -				lldebugs << "mImageAssetID: " << mImageAssetID << llendl; +			mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); +			lldebugs << "mImageItemID: " << mImageItemID << llendl; +			mImageAssetID = floaterp->getAssetID(); +			lldebugs << "mImageAssetID: " << mImageAssetID << llendl;  			}  			if (op == TEXTURE_SELECT && mOnSelectCallback) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 45ca23cdfe..d81b016fc1 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1030,12 +1030,7 @@ void CreateGestureCallback::fire(const LLUUID& inv_item)  	gFloaterView->adjustToFitScreen(preview, FALSE);  } -void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) -{ -	if (mTargetLandmarkId.isNull()) return; -	gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); -}  LLInventoryCallbackManager gInventoryCallbacks; @@ -1308,7 +1303,7 @@ const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably  const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)  // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... -void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) +void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)  {  	std::string type_name = userdata.asString(); @@ -1332,7 +1327,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons  		LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);  		gInventory.notifyObservers(); -		root->setSelectionByID(category, TRUE); +		panel->setSelectionByID(category, TRUE);  	}  	else if ("lsl" == type_name)  	{ @@ -1375,7 +1370,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons  			llwarns << "Can't create unrecognized type " << type_name << llendl;  		}  	} -	root->setNeedsAutoRename(TRUE);	 +	panel->getRootFolder()->setNeedsAutoRename(TRUE);	  }  LLAssetType::EType LLViewerInventoryItem::getType() const @@ -1449,348 +1444,6 @@ const std::string& LLViewerInventoryItem::getName() const  	return  LLInventoryItem::getName();  } -/** - * Class to store sorting order of favorites landmarks in a local file. EXT-3985. - * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. - * Data are stored in user home directory. - */ -class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> -	, public LLDestroyClass<LLFavoritesOrderStorage> -{ -	LOG_CLASS(LLFavoritesOrderStorage); -public: -	/** -	 * Sets sort index for specified with LLUUID favorite landmark -	 */ -	void setSortIndex(const LLUUID& inv_item_id, S32 sort_index); - -	/** -	 * Gets sort index for specified with LLUUID favorite landmark -	 */ -	S32 getSortIndex(const LLUUID& inv_item_id); -	void removeSortIndex(const LLUUID& inv_item_id); - -	void getSLURL(const LLUUID& asset_id); - -	/** -	 * Implementation of LLDestroyClass. Calls cleanup() instance method. -	 * -	 * It is important this callback is called before gInventory is cleaned. -	 * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), -	 * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. -	 * @see cleanup() -	 */ -	static void destroyClass(); - -	const static S32 NO_INDEX; -private: -	friend class LLSingleton<LLFavoritesOrderStorage>; -	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } -	~LLFavoritesOrderStorage() { save(); } - -	/** -	 * Removes sort indexes for items which are not in Favorites bar for now. -	 */ -	void cleanup(); - -	const static std::string SORTING_DATA_FILE_NAME; - -	void load(); -	void save(); - -	void saveFavoritesSLURLs(); - -	// Remove record of current user's favorites from file on disk. -	void removeFavoritesRecordOfUser(); - -	void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark); -	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); - -	typedef std::map<LLUUID, S32> sort_index_map_t; -	sort_index_map_t mSortIndexes; - -	typedef std::map<LLUUID, std::string> slurls_map_t; -	slurls_map_t mSLURLs; - -	bool mIsDirty; - -	struct IsNotInFavorites -	{ -		IsNotInFavorites(const LLInventoryModel::item_array_t& items) -			: mFavoriteItems(items) -		{ - -		} - -		/** -		 * Returns true if specified item is not found among inventory items -		 */ -		bool operator()(const sort_index_map_t::value_type& id_index_pair) const -		{ -			LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); -			if (item.isNull()) return true; - -			LLInventoryModel::item_array_t::const_iterator found_it = -				std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); - -			return found_it == mFavoriteItems.end(); -		} -	private: -		LLInventoryModel::item_array_t mFavoriteItems; -	}; - -}; - -const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; -const S32 LLFavoritesOrderStorage::NO_INDEX = -1; - -void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index) -{ -	mSortIndexes[inv_item_id] = sort_index; -	mIsDirty = true; -} - -S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) -{ -	sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); -	if (it != mSortIndexes.end()) -	{ -		return it->second; -	} -	return NO_INDEX; -} - -void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) -{ -	mSortIndexes.erase(inv_item_id); -	mIsDirty = true; -} - -void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) -{ -	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); -	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached - -	LLLandmark* lm = gLandmarkList.getAsset(asset_id, -			boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); -	if (lm) -	{ -		onLandmarkLoaded(asset_id, lm); -	} -} - -// static -void LLFavoritesOrderStorage::destroyClass() -{ -	LLFavoritesOrderStorage::instance().cleanup(); -	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) -	{ -		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); -	} -	else -	{ -		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); -	} -} - -void LLFavoritesOrderStorage::load() -{ -	// load per-resident sorting information -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); - -	LLSD settings_llsd; -	llifstream file; -	file.open(filename); -	if (file.is_open()) -	{ -		LLSDSerialize::fromXML(settings_llsd, file); -	} - -	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); -		iter != settings_llsd.endMap(); ++iter) -	{ -		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); -	} -} - -void LLFavoritesOrderStorage::saveFavoritesSLURLs() -{ -	// Do not change the file if we are not logged in yet. -	if (!LLLoginInstance::getInstance()->authSuccess()) -	{ -		llwarns << "Cannot save favorites: not logged in" << llendl; -		return; -	} -	 -	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); -	if (user_dir.empty()) -	{ -		llwarns << "Cannot save favorites: empty user dir name" << llendl; -		return; -	} - -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); -	llifstream in_file; -	in_file.open(filename); -	LLSD fav_llsd; -	if (in_file.is_open()) -	{ -		LLSDSerialize::fromXML(fav_llsd, in_file); -	} - -	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -	LLSD user_llsd; -	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) -	{ -		LLSD value; -		value["name"] = (*it)->getName(); -		value["asset_id"] = (*it)->getAssetUUID(); - -		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); -		if (slurl_iter != mSLURLs.end()) -		{ -			lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl; -			value["slurl"] = slurl_iter->second; -			user_llsd[(*it)->getSortField()] = value; -		} -		else -		{ -			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; -		} -	} - -	LLAvatarName av_name; -	LLAvatarNameCache::get( gAgentID, &av_name ); -	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; -	fav_llsd[av_name.getLegacyName()] = user_llsd; - -	llofstream file; -	file.open(filename); -	LLSDSerialize::toPrettyXML(fav_llsd, file); -} - -void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() -{ -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); -	LLSD fav_llsd; -	llifstream file; -	file.open(filename); -	if (!file.is_open()) return; -	LLSDSerialize::fromXML(fav_llsd, file); - -	LLAvatarName av_name; -	LLAvatarNameCache::get( gAgentID, &av_name ); -	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; -	if (fav_llsd.has(av_name.getLegacyName())) -	{ -		fav_llsd.erase(av_name.getLegacyName()); -	} - -	llofstream out_file; -	out_file.open(filename); -	LLSDSerialize::toPrettyXML(fav_llsd, out_file); - -} - -void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) -{ -	if (!landmark) return; - -	LLVector3d pos_global; -	if (!landmark->getGlobalPos(pos_global)) -	{ -		// If global position was unknown on first getGlobalPos() call -		// it should be set for the subsequent calls. -		landmark->getGlobalPos(pos_global); -	} - -	if (!pos_global.isExactlyZero()) -	{ -		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, -				boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); -	} -} - -void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) -{ -	lldebugs << "Saving landmark SLURL: " << slurl << llendl; -	mSLURLs[asset_id] = slurl; -} - -void LLFavoritesOrderStorage::save() -{ -	// nothing to save if clean -	if (!mIsDirty) return; - -	// If we quit from the login screen we will not have an SL account -	// name.  Don't try to save, otherwise we'll dump a file in -	// C:\Program Files\SecondLife\ or similar. JC -	std::string user_dir = gDirUtilp->getLindenUserDir(); -	if (!user_dir.empty()) -	{ -		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); -		LLSD settings_llsd; - -		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) -		{ -			settings_llsd[iter->first.asString()] = iter->second; -		} - -		llofstream file; -		file.open(filename); -		LLSDSerialize::toPrettyXML(settings_llsd, file); -	} -} - -void LLFavoritesOrderStorage::cleanup() -{ -	// nothing to clean -	if (!mIsDirty) return; - -	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -	IsNotInFavorites is_not_in_fav(items); - -	sort_index_map_t  aTempMap; -	//copy unremoved values from mSortIndexes to aTempMap -	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  -		inserter(aTempMap, aTempMap.begin()), -		is_not_in_fav); - -	//Swap the contents of mSortIndexes and aTempMap -	mSortIndexes.swap(aTempMap); -} - - -S32 LLViewerInventoryItem::getSortField() const -{ -	return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); -} - -void LLViewerInventoryItem::setSortField(S32 sortField) -{ -	LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); -	getSLURL(); -} - -void LLViewerInventoryItem::getSLURL() -{ -	LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); -} - -const LLPermissions& LLViewerInventoryItem::getPermissions() const -{ -	// Use the actual permissions of the symlink, not its parent. -	return LLInventoryItem::getPermissions();	 -} -  const LLUUID& LLViewerInventoryItem::getCreatorUUID() const  {  	if (const LLViewerInventoryItem *linked_item = getLinkedItem()) @@ -1861,17 +1514,6 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const  	return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);  } - -time_t LLViewerInventoryItem::getCreationDate() const -{ -	return LLInventoryItem::getCreationDate(); -} - -U32 LLViewerInventoryItem::getCRC32() const -{ -	return LLInventoryItem::getCRC32();	 -} -  // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985  static char getSeparator() { return '@'; }  BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7822ef4da6..3cf03c3bc5 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -34,7 +34,7 @@  #include <boost/signals2.hpp>	// boost::signals2::trackable -class LLFolderView; +class LLInventoryPanel;  class LLFolderBridge;  class LLViewerInventoryCategory; @@ -60,10 +60,6 @@ public:  	virtual const LLUUID& getAssetUUID() const;  	virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user  	virtual const std::string& getName() const; -	virtual S32 getSortField() const; -	virtual void setSortField(S32 sortField); -	virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. -	virtual const LLPermissions& getPermissions() const;  	virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied  	virtual const LLUUID& getCreatorUUID() const;  	virtual const std::string& getDescription() const; @@ -72,8 +68,11 @@ public:  	virtual bool isWearableType() const;  	virtual LLWearableType::EType getWearableType() const;  	virtual U32 getFlags() const; -	virtual time_t getCreationDate() const; -	virtual U32 getCRC32() const; // really more of a checksum. + +    using LLInventoryItem::getPermissions; +	using LLInventoryItem::getCreationDate; +	using LLInventoryItem::setCreationDate; +	using LLInventoryItem::getCRC32;  	static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); @@ -285,18 +284,6 @@ public:  	void fire(const LLUUID& inv_item);  }; -class AddFavoriteLandmarkCallback : public LLInventoryCallback -{ -public: -	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} -	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } - -private: -	void fire(const LLUUID& inv_item); - -	LLUUID mTargetLandmarkId; -}; -  // misc functions  //void inventory_reliable_callback(void**, S32 status); @@ -372,7 +359,7 @@ void copy_inventory_from_notecard(const LLUUID& destination_id,  								  U32 callback_id = 0); -void menu_create_inventory_item(LLFolderView* root, +void menu_create_inventory_item(LLInventoryPanel* root,  								LLFolderBridge* bridge,  								const LLSD& userdata,  								const LLUUID& default_parent_uuid = LLUUID::null); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dd78bbd491..b0e36d756d 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -728,7 +728,7 @@ static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& item  		LLFolderView* fv = inventory_panel->getRootFolder();  		if (fv)  		{ -			LLFolderViewItem* fv_item = fv->getItemByID(item_id); +			LLFolderViewItem* fv_item = inventory_panel->getItemByID(item_id);  			if (fv_item)  			{  				LLFolderViewItem* fv_folder = fv_item->getParentFolder(); @@ -816,7 +816,13 @@ private:  		mSelectedItems.clear();  		if (LLInventoryPanel::getActiveInventoryPanel())  		{ -			mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selection =    LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +			for (std::set<LLFolderViewItem*>::iterator it = selection.begin(),    end_it = selection.end(); +				it != end_it; +				++it) +			{ +				mSelectedItems.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +			}  		}  		mSelectedItems.erase(mMoveIntoFolderID);  	} @@ -851,7 +857,15 @@ private:  		}  		// get selected items (without destination folder) -		selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList(); +		selected_items_t selected_items; + 		 + 		std::set<LLFolderViewItem*> selection =    LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +		for (std::set<LLFolderViewItem*>::iterator it = selection.begin(),    end_it = selection.end(); +			it != end_it; +			++it) +		{ +			selected_items.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +		}  		selected_items.erase(mMoveIntoFolderID);  		// compare stored & current sets of selected items  | 
