diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index fbf23bc3f09a760eee88c85f29cf41df9a1a5352..6e54f9d78a722a999032ebefc1df4cea6fe241ed 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 a5cfe59bda347b615f674c351b6050cc362bf2af..dc9a09e9d64dbcd302101f6e4b1969cf2036a044 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -75,6 +75,7 @@ class LLInventoryObject : public LLRefCount
 	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 @@ class LLInventoryObject : public LLRefCount
 	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 @@ class LLInventoryObject : public LLRefCount
 	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 @@ class LLInventoryItem : public LLInventoryObject
 	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 @@ class LLInventoryItem : public LLInventoryObject
 	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 487a2e5fe7c6df5ae1d48ba8c8f3b5e189972e6f..48128e0b409729b6f26da24e8bff79c3ce697f42 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 25e7a31e9073de346c6a1bc43f2d37d1925d1b47..f64f33bc5e71fdbf042d508cf41bf6586ea1e4f1 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 d612ad5005d19afebbbdbbc15d92e008396e92ad..b441cb0c9d7be2b33614d1c04a5f00460c7d7f4a 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -105,7 +105,7 @@ class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
 		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 @@ class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
 	}
 
 
-	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 ce59401e871983e6770e58ca098d623fd597edc6..d44ccac6e4dfbae18f33d6128944a89f5b1fa949 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 36ce6a97b720c75d347d972948f16fee80ce8a2f..3e8d9267cca9d91e9fd487632841ef22ece0facf 100644
--- a/indra/llxuixml/llregistry.h
+++ b/indra/llxuixml/llregistry.h
@@ -302,6 +302,10 @@ class LLRegistrySingleton
 		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 e67089c4de8d79420bbfed7d51bc59864ad8d7c0..1ea474a48517fc74f31227e6c95ee46dbac490c6 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -812,7 +812,7 @@ set(viewer_HEADER_FILES
     llfloaterwindowsize.h
     llfloaterworldmap.h
     llfolderview.h
-    llfoldervieweventlistener.h
+    llfolderviewmodel.h
     llfolderviewitem.h
     llfollowcam.h
     llfriendcard.h
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 21367c224d34b5efec67de1fa4d1631b9fe5e220..fb32bcbd6007cd42a3db38f2c5d7827fcb2fcaee 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 575b613ccfcce44e41e09484073f2a19f2ffce0f..4a96de942d9c4f4fcbfd72e7a09ce43adb46144b 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 @@ class LLItemCopiedCallback : public LLInventoryCallback
 
 		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 2f75b3bb0eec119a4b66a660c6dd4a2abd5ea656..60e02b661e23d0d3b320ea1ea2a1821aa640a958 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 @@ class LLFavoritesBarCtrl : public LLUICtrl, public LLInventoryObserver
 	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 c55970ad695290f965f04415c7ab753f7841633c..04a55b261ccdaa1e6e67980b3c402c6895edf0e2 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 57fc3f7efd45d07ed09d8c309868e28683e2b960..5844c58e094a4a0e9b217c4449a1f87869a697ab 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -26,17 +26,14 @@
 
 #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 @@ class LLCloseAllFoldersFunctor : public LLFolderViewFunctor
 };
 
 
-// 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();
@@ -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,144 +331,42 @@ 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();
-
-	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() );
-		}
-	}
+	LLFolderViewFolder::arrange(&mMinWidth, &target_height);
 
-	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())
+	if (getLastFilterGeneration() < filter.getCurrentGeneration())
 	{
-		mPassedFilter = FALSE;
 		mMinWidth = 0;
-		LLFolderViewFolder::filter(filter);
-	}
-	else
-	{
-		mPassedFilter = TRUE;
+		getViewModelItem()->filter(filter);
 	}
 }
 
@@ -552,7 +379,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 +478,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 +528,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 +535,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 +593,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 +632,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 +653,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 +671,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,26 +704,20 @@ 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())
+		if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration())
 		{
 			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);
-			}
+			mStatusText = getFolderViewModel()->getFilter()->getEmptyLookupMessage();
 		}
 		mStatusTextBox->setValue(mStatusText);
 		mStatusTextBox->setVisible( TRUE );
@@ -967,7 +736,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 +767,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 +879,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 +896,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 +914,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 +960,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 +980,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 +1101,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 +1117,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 +1141,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 +1158,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 +1187,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 +1209,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 +1248,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 +1362,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 +1426,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 +1558,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 +1625,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 +1669,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 +1742,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 +1844,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 +1859,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 +1874,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 +1895,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 +1935,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 +1950,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 +1960,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 +1971,8 @@ void LLFolderView::doIdle()
 		scrollToShowSelection();
 	}
 
-	BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration() 
-						&& !LLInventoryModelBackgroundFetch::instance().folderFetchActive();
+	BOOL filter_finished = getLastFilterGeneration() >= getFolderViewModel()->getFilter()->getCurrentGeneration() 
+						&& mViewModel->contentsReady();
 	if (filter_finished 
 		|| gFocusMgr.childHasKeyboardFocus(inventory_panel) 
 		|| gFocusMgr.childHasMouseCapture(inventory_panel))
@@ -2330,7 +2042,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 +2250,23 @@ 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)
+S32 LLFolderView::getItemHeight()
 {
-	if(user_data)
+	if(!hasVisibleChildren())
 	{
-		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)
-{
-	if(user_data)
-	{
-		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
-		fv->openSelectedItems();
+		//We need to display status textbox, let's reserve some place for it
+		return llmax(0, mStatusTextBox->getTextPixelHeight());
 	}
+	return 0;
 }
 
-void properties_selected_items(void* user_data)
+//TODO RN: move to llfolderviewmodel.cpp file
+bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item)
 {
-	if(user_data)
-	{
-		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
-		fv->propertiesSelectedItems();
-	}
+	return item->getSortVersion() < mTargetSortVersion;
 }
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index dc3d02eac68594d791c96292283d9c5acdd80dc5..8a0317f8400a5dd5a32bef379c5e65a4910dd00d 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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 		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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 
 	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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	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 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 
 };
 
-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 06682dcbf1f9d8058e9449e146027f4ae80f38a0..0000000000000000000000000000000000000000
--- 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 8ae779326c2377610d926b20bd58200d5eb1069a..08ddb76f3b9025c9efa81fb8e24f4f344ed2a23e 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),
 	mIsMouseOverTitle(false)
 {
+	if (mListener)
+	{
+		mListener->setFolderViewItem(this);
+	}
 }
 
 BOOL LLFolderViewItem::postBuild()
@@ -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()
+BOOL LLFolderViewItem::passedFilter(S32 filter_generation) 
 {
-	// we haven't been checked against min required filter
-	// or we have and we passed
-	return potentiallyFiltered();
+	return getViewModelItem()->passedFilter(filter_generation);
 }
 
-BOOL LLFolderViewItem::potentiallyFiltered()
+void LLFolderViewItem::refresh()
 {
-	return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered();
-}
+	LLFolderViewModelItem& vmi = *getViewModelItem();
 
-BOOL LLFolderViewItem::getFiltered() 
-{ 
-	return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); 
-}
-
-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();
+	//TODO RN: make sure this logic still fires
+	//std::string searchable_label(mLabel);
+	//searchable_label.append(mLabelSuffix);
+	//LLStringUtil::toUpper(searchable_label);
 
-	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)
+std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const
 {
-	getRoot()->changeSelection(selection, selected);
-}
-
-std::set<LLUUID> 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,72 +402,36 @@ 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)
-			{
-				mParentFolder->requestSort();
-			}
+		if(mParentFolder)
+		{
+			mParentFolder->requestSort();
 		}
 	}
 }
 
-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);
@@ -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);
 		}
 	}
 
@@ -833,21 +605,17 @@ 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)
+	BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg);
+	handled = accepted;
+	if (accepted)
 	{
-		accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg);
-		handled = accepted;
-		if (accepted)
-		{
-			mDragAndDropTarget = TRUE;
-			*accept = ACCEPT_YES_MULTI;
-		}
-		else
-		{
-			*accept = ACCEPT_NO;
-		}
+		mDragAndDropTarget = TRUE;
+		*accept = ACCEPT_YES_MULTI;
+	}
+	else
+	{
+		*accept = ACCEPT_NO;
 	}
 	if(mParentFolder && !handled)
 	{
@@ -866,34 +634,29 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 
 void LLFolderViewItem::draw()
 {
-	static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
-	static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
-	static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
+	static LLUIColor sFgColor 			= LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
+	static LLUIColor sHighlightBgColor 	= LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
+	static LLUIColor sHighlightFgColor 	= LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
 	static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
-	static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
-	static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
-	static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE);
-	static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE);
-	static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
+	static LLUIColor sFilterBGColor 	= LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
+	static LLUIColor sFilterTextColor 	= LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
+	static LLUIColor sSuffixColor 		= LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE);
+	static LLUIColor sLibraryColor 		= LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE);
+	static LLUIColor sLinkColor 		= LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
 	static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
-	static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
+	static LLUIColor sMouseOverColor 	= LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
 
 	const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
 	const S32 TOP_PAD = default_params.item_top_pad;
 	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,30 +780,14 @@ 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
 	//
@@ -1050,30 +795,6 @@ void LLFolderViewItem::draw()
 					 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
 					 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
 	//
@@ -1087,50 +808,61 @@ void LLFolderViewItem::draw()
 	//--------------------------------------------------------------------------------//
 	// Highlight string match
 	//
-	if (mStringMatchOffset != std::string::npos)
-	{
-		// don't draw backgrounds for zero-length strings
-		S32 filter_string_length = (getRoot() ? getRoot()->getFilterSubString().size() : 0);
-		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 );
-		}
-	}
+	//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
+{
+	return getRoot()->getFolderViewModel();
+}
+
+LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void )
+{
+	return getRoot()->getFolderViewModel();
+}
+
+S32 LLFolderViewItem::getLastFilterGeneration() const
+{
+	return getViewModelItem()->getLastFilterGeneration();
 }
 
 
+
 ///----------------------------------------------------------------------------
 /// Class LLFolderViewFolder
 ///----------------------------------------------------------------------------
 
 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 +874,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)
+BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
 {
-	if (!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 +901,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 +911,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 +921,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 +936,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 +944,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 +952,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 +963,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 +971,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 +995,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 +1046,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 +1417,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 +1426,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,162 +1452,67 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
 		mItems.erase(it);
 	}
 	//item has been removed, need to update filter
-	dirtyFilter();
+	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
+BOOL LLFolderViewFolder::isMovable()
 {
-	if (mAmTrash == LLFolderViewFolder::UNKNOWN)
+	if( !(getViewModelItem()->isItemMovable()) )
 	{
-		mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH;
+		return FALSE;
 	}
-	return mAmTrash == LLFolderViewFolder::TRASH;
-}
 
-void LLFolderViewFolder::sortBy(U32 order)
-{
-	if (!mSortFunction.updateSort(order))
+	for (items_t::iterator iter = mItems.begin();
+		iter != mItems.end();)
 	{
-		// No changes.
-		return;
+		items_t::iterator iit = iter++;
+		if(!(*iit)->isMovable())
+		{
+			return FALSE;
+		}
 	}
 
-	// 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())
+		if(!(*fit)->isMovable())
 		{
-			LLFolderViewItem* item = *(mItems.begin());
-			latest = item->getCreationDate();
-		}
-
-		if (!mFolders.empty())
-		{
-			LLFolderViewFolder* folder = *(mFolders.begin());
-			if (folder->getCreationDate() > latest)
-			{
-				latest = folder->getCreationDate();
-			}
+			return FALSE;
 		}
-		mSubtreeCreationDate = latest;
 	}
+	return TRUE;
 }
 
-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
+BOOL LLFolderViewFolder::isRemovable()
 {
-	if (isTrash())
-	{
-		return SG_TRASH_FOLDER;
-	}
-
-	if( mListener )
+	if( !(getViewModelItem()->isItemRemovable()) )
 	{
-		if(LLFolderType::lookupIsProtectedType(mListener->getPreferredType()))
-		{
-			return SG_SYSTEM_FOLDER;
-		}
+		return FALSE;
 	}
 
-	return SG_NORMAL_FOLDER;
-}
-
-BOOL LLFolderViewFolder::isMovable()
-{
-	if( mListener )
+	for (items_t::iterator iter = mItems.begin();
+		iter != mItems.end();)
 	{
-		if( !(mListener->isItemMovable()) )
+		items_t::iterator iit = iter++;
+		if(!(*iit)->isRemovable())
 		{
 			return FALSE;
 		}
-
-		for (items_t::iterator iter = mItems.begin();
-			iter != mItems.end();)
-		{
-			items_t::iterator iit = iter++;
-			if(!(*iit)->isMovable())
-			{
-				return FALSE;
-			}
-		}
-
-		for (folders_t::iterator iter = mFolders.begin();
-			iter != mFolders.end();)
-		{
-			folders_t::iterator fit = iter++;
-			if(!(*fit)->isMovable())
-			{
-				return FALSE;
-			}
-		}
 	}
-	return TRUE;
-}
-
 
-BOOL LLFolderViewFolder::isRemovable()
-{
-	if( mListener )
+	for (folders_t::iterator iter = mFolders.begin();
+		iter != mFolders.end();)
 	{
-		if( !(mListener->isItemRemovable()) )
+		folders_t::iterator fit = iter++;
+		if(!(*fit)->isRemovable())
 		{
 			return FALSE;
 		}
-
-		for (items_t::iterator iter = mItems.begin();
-			iter != mItems.end();)
-		{
-			items_t::iterator iit = iter++;
-			if(!(*iit)->isRemovable())
-			{
-				return FALSE;
-			}
-		}
-
-		for (folders_t::iterator iter = mFolders.begin();
-			iter != mFolders.end();)
-		{
-			folders_t::iterator fit = iter++;
-			if(!(*fit)->isRemovable())
-			{
-				return FALSE;
-			}
-		}
 	}
 	return TRUE;
 }
@@ -2187,6 +1520,12 @@ BOOL LLFolderViewFolder::isRemovable()
 // 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 +1533,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 +1561,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 +1589,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 +1604,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)
 	{
-		if(!was_open && openitem)
-		{
-			mListener->openItem();
-		}
-		else if(was_open && !openitem)
-		{
-			mListener->closeItem();
-		}
+		getViewModelItem()->openItem();
+	}
+	else if(was_open && !openitem)
+	{
+		getViewModelItem()->closeItem();
 	}
 
 	if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN)
@@ -2316,7 +1631,7 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r
 		mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);
 	}
 
-	if (was_open != mIsOpen)
+	if (was_open != isOpen())
 	{
 		requestArrange();
 	}
@@ -2329,7 +1644,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 = mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg);
 	if (accepted) 
 	{
 		mDragAndDropTarget = TRUE;
@@ -2385,23 +1700,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 +1710,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 +1732,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 +1756,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 +1787,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 +1811,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 +1835,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
 		}
 		else
 		{
-			setSelectionFromRoot(this, FALSE);
+			getRoot()->setSelection(this, FALSE);
 			toggleOpen();
 		}
 		handled = TRUE;
@@ -2554,7 +1849,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 +1858,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 +1869,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 +2080,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 +2136,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 +2148,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 +2160,4 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde
 		}
 	}
 }
+
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 3c7592046a15dc0d589f586af2e573363503e38f..a3c92a55e8d2ada043c05ee8afd703ccd69e95c1 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 @@ class LLFolderViewItem : public LLView
 
 	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,27 +79,20 @@ class LLFolderViewItem : public LLView
 	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*		mListener;
 	BOOL						mIsCurSelection;
 	BOOL						mSelectPending;
 	LLFontGL::StyleFlags		mLabelStyle;
@@ -153,20 +104,14 @@ class LLFolderViewItem : public LLView
 	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,46 +119,25 @@ class LLFolderViewItem : public LLView
 
 	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();
+	S32		getLastFilterGeneration() const;
 
 	// If 'selection' is 'this' then note that otherwise ignore.
 	// Returns TRUE if this item ends up being selected.
@@ -231,7 +155,7 @@ class LLFolderViewItem : public LLView
 	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 +176,56 @@ class LLFolderViewItem : public LLView
 
 	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 mListener; }
+	LLFolderViewModelItem* getViewModelItem( void ) { return mListener; }
+
+	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 +249,6 @@ class LLFolderViewItem : public LLView
 	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 +264,6 @@ class LLFolderViewFolder : public LLFolderViewItem
 	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 +271,16 @@ class LLFolderViewFolder : public LLFolderViewItem
 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 +294,25 @@ class LLFolderViewFolder : public LLFolderViewItem
 
 	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 +338,13 @@ class LLFolderViewFolder : public LLFolderViewItem
 	//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 +355,9 @@ class LLFolderViewFolder : public LLFolderViewItem
 	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 +377,6 @@ class LLFolderViewFolder : public LLFolderViewItem
 		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 +402,22 @@ class LLFolderViewFolder : public LLFolderViewItem
 									   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.h b/indra/newview/llfolderviewmodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..5304613219f6a31a2cb336c9d68c15adecbc8ea7
--- /dev/null
+++ b/indra/newview/llfolderviewmodel.h
@@ -0,0 +1,346 @@
+/** 
+ * @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 "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 bool contentsReady() = 0;
+	virtual void setFolderView(LLFolderView* folder_view) = 0;
+	virtual LLFolderViewFilter* getFilter() = 0;
+	virtual const LLFolderViewFilter* getFilter() const = 0;
+};
+
+class LLFolderViewModelCommon : public LLFolderViewModelInterface
+{
+public:
+	LLFolderViewModelCommon()
+	:	mTargetSortVersion(0),
+		mFolderView(NULL)
+	{}
+
+	virtual void requestSortAll()
+	{
+		// sort everything
+		mTargetSortVersion++;
+	}
+
+	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;
+
+	// 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)
+	{}
+
+	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); }
+
+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/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 11401d6c68b82761ea85ca8030dcdfe633e3fb07..a64ddd185db9f255826c2ddd37b5a603d7c1e344 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 b86c453d617693bced1035bd28af8d9a3c0654ce..002278601ac6cb5a02ba9007558858bc504b81d2 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 @@ class LLIsItemRemovable : public LLFolderViewFunctor
 	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 &current_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 dc9e88d54d84fb2c048609a5478eb0ad6b335098..e235d9cf5ffa4cc3220d778de545b6a9b62d8ac4 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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 									   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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 	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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 	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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 	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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 							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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 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 @@ class LLInvFVBridge : public LLFolderViewEventListener
 									 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 @@ class LLInventoryFVBridgeBuilder
 										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 @@ class LLItemBridge : public LLInvFVBridge
 	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 @@ class LLItemBridge : public LLInvFVBridge
 	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 @@ class LLItemBridge : public LLInvFVBridge
 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 @@ class LLFolderBridge : public LLInvFVBridge
 
 	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 @@ class LLFolderBridge : public LLInvFVBridge
 	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 @@ class LLFolderBridge : public LLInvFVBridge
 	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 @@ class LLFolderBridge : public LLInvFVBridge
 	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 @@ class LLFolderBridge : public LLInvFVBridge
 	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 @@ class LLSoundBridge : public LLItemBridge
 				  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 @@ class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
 		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 4d0af94f9f62b70b6b37f71ccc973d4444f59970..6a3313032286be94df14f3ad1a7c7866b32f6cea 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,71 +723,58 @@ 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))
@@ -991,60 +959,53 @@ const std::string& LLInventoryFilter::getFilterText()
 	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 +1018,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 +1058,6 @@ U32 LLInventoryFilter::getSortOrder() const
 { 
 	return mOrder; 
 }
-const std::string& LLInventoryFilter::getName() const 
-{ 
-	return mName; 
-}
 
 void LLInventoryFilter::setFilterCount(S32 count) 
 { 
@@ -1113,15 +1075,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 +1091,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 +1106,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 9e600c036f0e8679846b564bacbc478fb7db1d1c..af245a9c3bc8f6a9a629cf4f8570fc2845e7db45 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 @@ class LLInventoryFilter
 		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 @@ class LLInventoryFilter
 		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 @@ class LLInventoryFilter
 		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 @@ class LLInventoryFilter
 	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 @@ class LLInventoryFilter
 	// +-------------------------------------------------------------------+
 	// + 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 @@ class LLInventoryFilter
 	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 @@ class LLInventoryFilter
 	// +-------------------------------------------------------------------+
 	// + Default
 	// +-------------------------------------------------------------------+
-	BOOL 				isDefault() const;
-	BOOL 				isNotDefault() const;
+	bool 				isDefault() const;
+	bool 				isNotDefault() const;
 	void 				markDefault();
 	void 				resetDefault();
 
@@ -172,57 +240,44 @@ class LLInventoryFilter
 	// + 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 ab5b08291568165e81d6cb38c35349c9d6f25630..ff461236a209fdb6b47264e61b465b0f33ce1dcc 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 5cf9c528b01057ad0095a48f032ee286a7beb0bf..c6b1da0417a18131a40c56d6051848b4dc10ddd9 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -418,21 +418,6 @@ class LLFindNonRemovableObjects : public LLInventoryCollectFunctor
 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 @@ class LLInventoryState
 	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 85ecb133d07eefea4624693663a7f92dc71a37e1..9b0d12b353a7546cc817d28ffe25ac00a5a318ac 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 8382e875b48690a67c87feefa92ea03747aac248..3613bc49173c488566f2075611fa02cc17a660cf 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -362,15 +362,6 @@ class LLInventoryModel
 	// 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 71dd963f28c0dcc8ebd3a2a537cb7cb865293083..e4cabcc988002ea3423bb39d3e069cd4e6ab8c1d 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,6 +56,57 @@ 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 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();
+}
+
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInventoryPanelObserver
@@ -134,7 +186,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 +234,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 +255,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 +309,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 +329,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 +341,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 +361,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 +387,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 +405,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 +454,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 +471,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 +490,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 +551,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());
 						}
 					}
 				}
@@ -539,6 +581,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
 			{
 				// Remove the item's UI.
 				view_item->destroyView();
+                removeItemID(viewmodel_item->getUUID());
 			}
 		}
 	}
@@ -549,6 +592,11 @@ LLFolderView* LLInventoryPanel::getRootFolder()
 	return mFolderRoot; 
 }
 
+LLUUID LLInventoryPanel::getRootFolderID()
+{
+	return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID();
+}
+
 
 // static
 void LLInventoryPanel::onIdle(void *userdata)
@@ -568,16 +616,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 +630,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 +648,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 +672,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 +687,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 +699,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 +711,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 +790,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 +803,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 +814,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 +832,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 +936,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 +949,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 +958,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 +985,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 +998,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 +1044,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 +1085,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 +1238,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                                 */
@@ -1255,3 +1345,149 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
 	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
 }
 
+
+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) 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();
+	bool changed = false;
+
+	// 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 (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->setPassedFilter(false, false, filter_generation);
+		}
+		else
+		{
+			changed |= item->filter( filter );
+		}
+	}
+
+	// track latest generation to pass any child items
+	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);
+		}
+	}
+
+	changed |= (item->passedFilter() != passed_filter_before);
+	if (changed)
+	{
+		//TODO RN: ensure this still happens, but without dependency on folderview
+		LLFolderViewFolder* parent = mFolderViewItem->getParentFolder();
+		if (parent) parent->requestArrange();
+	}
+
+	return changed;
+}
+
+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 we didn't use all filter iterations
+	// that means we filtered all of our descendants
+	// so filter ourselves now
+	if (filter.getFilterCount() > 0)
+	{
+		const BOOL previous_passed_filter = mPassedFilter;
+		const BOOL passed_filter = filter.check(this);
+		const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) 
+								? filter.checkFolder(this)
+								: true;
+
+		// If our visibility will change as a result of this filter, then
+		// we need to be rearranged in our parent folder
+		LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder();
+		if (parent_folder && passed_filter != previous_passed_filter)
+		{
+			parent_folder->requestArrange();
+		}
+	
+		setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration());
+		//TODO RN: create interface for string highlighting
+		//mStringMatchOffset = filter.getStringMatchOffset(this);
+		filter.decrementFilterCount();
+	}
+	return changed;
+}
+
+LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel()
+{
+	return &mInventoryViewModel;
+}
+
+
+const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const
+{
+	return &mInventoryViewModel;
+}
+
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 6db59afb9b92a7a967a3bf5d81e4aeb30ac50b86..3195d9a36942501cad63c1f5fe5c2399dc4308de 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -30,6 +30,7 @@
 
 #include "llassetstorage.h"
 #include "lldarray.h"
+#include "llfolderviewitem.h"
 #include "llfloater.h"
 #include "llinventory.h"
 #include "llinventoryfilter.h"
@@ -38,22 +39,86 @@
 #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 LLFolderViewModelInventory;
+
+class LLFolderViewModelItemInventory
+	:	public LLFolderViewModelItemCommon
+{
+public:
+	LLFolderViewModelItemInventory()
+	:	mRootViewModel(NULL)
+	{}
+	void setRootViewModel(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:
+	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();
+
+};
+
 
 class LLInventoryPanel : public LLPanel
 {
@@ -85,7 +150,6 @@ class LLInventoryPanel : public LLPanel
 		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 +162,6 @@ class LLInventoryPanel : public LLPanel
 			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 +219,7 @@ class LLInventoryPanel : public LLPanel
 	// 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 +246,21 @@ class LLInventoryPanel : public LLPanel
 	
 	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 +268,13 @@ class LLInventoryPanel : public LLPanel
 	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 +295,6 @@ class LLInventoryPanel : public LLPanel
 	
 	void setSortOrder(U32 order);
 	U32 getSortOrder() const;
-	void requestSort();
 
 private:
 	std::string					mSortOrderSetting;
@@ -231,8 +307,7 @@ class LLInventoryPanel : public LLPanel
 	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 68a3b6d1cdd5957b8abb76ed6d0676ad1bb2e4b1..0b899d34f48c74058cf986fe7bbbeb2641702785 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 @@ class LLOpenFolderByID : public LLFolderViewFunctor
 // 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 b2f4e92473f587a0bce100d3e0d4da6f051e1bce..aa5f69739df42752b33b412e5ac5795553ff1b88 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 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	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 c11597f532366fd793cafca0d26a6910cfcf5336..6cef1f877b663fddd8a864392214b66ee13cec28 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 66c9c323cb76ef6ba1456b1a39955f02e0b5c2a5..3547156197728cf08fa2fa2d061813344861cefe 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 678e4f28433bade734f6c66edd5434915cf69547..6e5a52229784aee3381afe2fa5fb95882ce052b1 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 d6b827ee3ecde04a73fd747f093470eef49f6a26..209f3a40986f33cdb4156cd7e0effa2b130a5802 100644
--- a/indra/newview/llpanelmarketplaceinboxinventory.h
+++ b/indra/newview/llpanelmarketplaceinboxinventory.h
@@ -81,8 +81,6 @@ class LLInboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner
 	bool isFresh() const { return mFresh; }
 	
 protected:
-	void setCreationDate(time_t creation_date_utc);
-
 	bool mFresh;
 };
 
@@ -102,7 +100,7 @@ class LLInboxFolderViewItem : public LLFolderViewItem, public LLBadgeOwner
 
 	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 ff62cb23dbb18f6cc5b01fa6ff66d8e79e79136b..2885dd62660e02a9300abdbc3cb11a3e9d35853e 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 f84d6e5cc19c98388a6c90f4eebde6116b55efb9..450e1f7ed006b84b103a989787e98bddc2050742 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 @@ class LLTaskInvFVBridge : public LLFolderViewEventListener
 	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 @@ class LLTaskInvFVBridge : public LLFolderViewEventListener
 	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 @@ class LLTaskCategoryBridge : public LLTaskInvFVBridge
 	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 @@ class LLTaskCategoryBridge : public LLTaskInvFVBridge
 							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 607b705f7f85809392b13382305ca243070fc42b..7e857f8b31cc8c1a315283eff1abe49281862681 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 @@ class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener
 	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 35e2e96bab8effdac176544724408faa4ba72339..d690a1847736e97fb4146bccf33a9bc9d6e2bc23 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -270,7 +270,7 @@ class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu>
 
 		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 fe4cc0f55ff5f89a5f93bae0e91d894fd9f806c0..af29ab7ea93a59f5acdcf5eabc5f696086a2d205 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 52beacef9cf107a0f21d2e4a4ccc506fa7e797f5..791502990bfbd69a7a4c3aa0ec9c32c012dd3014 100644
--- a/indra/newview/llplacesinventorybridge.h
+++ b/indra/newview/llplacesinventorybridge.h
@@ -89,6 +89,7 @@ class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
 											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 f7823f4fe86938cfd3dd91262a7bc28ac0da93f3..d95d5eac19fcde424bc0e0ece6dc7ec0fe958144 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 853656905c9dc3b90c585064e65aa475e13eed23..b1432401870622ee13db755df8afad124834798b 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 4f9ab318a56807443cc0fdee6c3bad8f0b25d207..47bd620fc6bd4b3f6ce14ae96964be2de5d2a4bc 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 a33607f50d8a76177b133d0259118f325fad4ac6..e8b2808d4fd7e00538314726c2af239f3cc6d192 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -63,7 +63,7 @@ class LLSidepanelInventory : public LLPanel
 	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 ed9faa070601ea72801cee172df5fecdd9bd58fb..61a0331b72a737bd63515a40c9f5bb6e8451732e 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 @@ class LLFloaterTexturePicker : public LLFloater
 	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;
+		LLInventoryFilter* filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter();
 
-		bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() &&
+		bool is_filter_active = folder_view->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 45ca23cdfe2d3b19b49dd1f1410d99902731a57b..d81b016fc10018c26caff783f4407473d4678ae5 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 7822ef4da6548d688f39fd5c9bd2ec188467eabc..3cf03c3bc52085c496ee4ef2682ec6cd3ccc94ac 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 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	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 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	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 @@ class CreateGestureCallback : public LLInventoryCallback
 	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 dd78bbd49110658f97548f2f2ce56330083f3d18..b0e36d756d030f123a7d147755e7a62598046bcb 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 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO
 		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 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO
 		}
 
 		// 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