diff options
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 23 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 14 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.h | 15 | ||||
| -rw-r--r-- | indra/newview/llinventorypanel.cpp | 193 | ||||
| -rw-r--r-- | indra/newview/llinventorypanel.h | 5 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 3 | 
6 files changed, 233 insertions, 20 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d7c7c7b552..20b2e1334e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -838,6 +838,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  {  	const LLInventoryObject *obj = getInventoryObject();      bool single_folder_root = (mRoot == NULL); +    bool is_cof = isCOFFolder(); +    bool is_inbox = isInboxFolder();  	if (obj)  	{ @@ -853,7 +855,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  		}          bool is_agent_inventory = isAgentInventory(); -        if (is_agent_inventory && !single_folder_root) +        if (is_agent_inventory && !single_folder_root && !is_cof && !is_inbox)          {              items.push_back(std::string("New folder from selected"));              items.push_back(std::string("Subfolder Separator")); @@ -889,6 +891,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,              if (!isItemMovable() || !isItemRemovable())              {                  disabled_items.push_back(std::string("Cut")); +                disabled_items.push_back(std::string("New folder from selected"));              }  		}  		else @@ -898,7 +901,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  				items.push_back(std::string("Find Links"));  			} -			if (!isInboxFolder() && !single_folder_root) +			if (!is_inbox && !single_folder_root)  			{  				items.push_back(std::string("Rename"));  				if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) @@ -938,6 +941,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  			if (!isItemMovable() || !isItemRemovable())  			{  				disabled_items.push_back(std::string("Cut")); +                disabled_items.push_back(std::string("New folder from selected"));  			}  			if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder()) @@ -960,7 +964,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  	}  	// Don't allow items to be pasted directly into the COF or the inbox -	if (!isCOFFolder() && !isInboxFolder()) +	if (!is_cof && !is_inbox)  	{  		items.push_back(std::string("Paste"));  	} @@ -4445,6 +4449,15 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items  				items.push_back(std::string("Rename"));                  items.push_back(std::string("thumbnail")); +                if (cat->getIsFavorite()) +                { +                    items.push_back(std::string("Remove from Favorites")); +                } +                else +                { +                    items.push_back(std::string("Add to Favorites")); +                } +  				addDeleteContextMenuOptions(items, disabled_items);  				// EXT-4030: disallow deletion of currently worn outfit  				const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); @@ -8029,6 +8042,7 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)          buildContextMenuOptions(flags, items, disabled_items);  	items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); +    items.erase(std::remove(items.begin(), items.end(), std::string("New folder from selected")), items.end());  	hide_context_entries(menu, items, disabled_items);  } @@ -8072,6 +8086,9 @@ void LLFavoritesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)      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()); +    items.erase(std::remove(items.begin(), items.end(), std::string("New folder from selected")), items.end()); +      hide_context_entries(menu, items, disabled_items);  } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 135dfa3519..81be2c1f24 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2663,6 +2663,20 @@ bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryIt  	return FALSE;  } +bool LLFavoritesCollector::operator()(LLInventoryCategory* cat, +    LLInventoryItem* item) +{ +    if (item && item->getIsFavorite()) +    { +        return true; +    } +    if (cat && cat->getIsFavorite()) +    { +        return true; +    } +    return false; +} +  bool LLBuddyCollector::operator()(LLInventoryCategory* cat,  								  LLInventoryItem* item)  { diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 14038967c6..44f85bfb3e 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -325,6 +325,21 @@ protected:  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFavoritesCollector +// +// Simple class that collects calling cards that are not null, and not +// the agent. Duplicates are possible. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFavoritesCollector : public LLInventoryCollectFunctor +{ +public: +    LLFavoritesCollector() {} +    virtual ~LLFavoritesCollector() {} +    virtual bool operator()(LLInventoryCategory* cat, +        LLInventoryItem* item); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLBuddyCollector  //  // Simple class that collects calling cards that are not null, and not diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 3892bfee03..4682f2085b 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -865,7 +865,23 @@ void LLInventoryPanel::idle(void* user_data)      bool in_visible_chain = panel->isInVisibleChain(); -    if (!panel->mBuildViewsQueue.empty()) +    if (!panel->mBuildRootQueue.empty()) +    { +        const F64 max_time = in_visible_chain ? 0.006f : 0.001f; // 6 ms +        F64 curent_time = LLTimer::getTotalSeconds(); +        panel->mBuildViewsEndTime = curent_time + max_time; + +        while (curent_time < panel->mBuildViewsEndTime +            && !panel->mBuildRootQueue.empty()) +        { +            LLUUID item_id = panel->mBuildRootQueue.back(); +            panel->mBuildRootQueue.pop_back(); +            panel->findAndInitRootContent(item_id); + +            curent_time = LLTimer::getTotalSeconds(); +        } +    } +    else if (!panel->mBuildViewsQueue.empty())      {          const F64 max_time = in_visible_chain ? 0.006f : 0.001f; // 6 ms          F64 curent_time = LLTimer::getTotalSeconds(); @@ -949,7 +965,7 @@ void LLInventoryPanel::initializeViews(F64 max_time)  	// init everything      initRootContent(); -    if (mBuildViewsQueue.empty()) +    if (mBuildViewsQueue.empty() && mBuildRootQueue.empty())      {          mViewsInitialized = VIEWS_INITIALIZED;      } @@ -2252,12 +2268,19 @@ public:          getFilter().setFilterNoMarketplaceFolder();      } +    void removeItemID(const LLUUID& id) override; +  protected:      LLInventoryFavoritesItemsPanel(const Params&);      friend class LLUICtrlFactory; -    void initRootContent(const LLUUID& id); +    void findAndInitRootContent(const LLUUID& folder_id) override;      void initRootContent() override; + +    bool removeFavorite(const LLUUID& id, const LLInventoryObject* model_item); +    void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override; + +    std::set<LLUUID> mRootContentIDs;  };  LLInventoryFavoritesItemsPanel::LLInventoryFavoritesItemsPanel(const Params& params) @@ -2267,8 +2290,27 @@ LLInventoryFavoritesItemsPanel::LLInventoryFavoritesItemsPanel(const Params& par      mInvFVBridgeBuilder = &FAVORITES_BUILDER;  } -void LLInventoryFavoritesItemsPanel::initRootContent(const LLUUID& id) +void LLInventoryFavoritesItemsPanel::removeItemID(const LLUUID& id) +{ +    std::set<LLUUID>::iterator found = mRootContentIDs.find(id); +    if (found != mRootContentIDs.end()) +    { +        mRootContentIDs.erase(found); +        // check content for favorites +        mBuildRootQueue.emplace_back(id); +    } + +    LLInventoryPanel::removeItemID(id); +} + +void LLInventoryFavoritesItemsPanel::findAndInitRootContent(const LLUUID& id)  { +    F64 curent_time = LLTimer::getTotalSeconds(); +    if (mBuildViewsEndTime < curent_time) +    { +        mBuildRootQueue.emplace_back(id); +        return; +    }      LLViewerInventoryCategory::cat_array_t* categories;      LLViewerInventoryItem::item_array_t* items;      mInventory->lockDirectDescendentArrays(id, categories, items); @@ -2285,14 +2327,18 @@ void LLInventoryFavoritesItemsPanel::initRootContent(const LLUUID& id)              }              else if (cat->getIsFavorite())              { -                const LLUUID& parent_id = cat->getParentUUID(); -                LLFolderViewItem* folder_view_item = getItemByID(cat->getUUID()); // Should be NULL +                LLFolderViewItem* folder_view_item = getItemByID(cat->getUUID()); +                if (!folder_view_item) +                { +                    const LLUUID& parent_id = cat->getParentUUID(); +                    mRootContentIDs.emplace(cat->getUUID()); -                buildViewsTree(cat->getUUID(), parent_id, cat, folder_view_item, mFolderRoot.get(), BUILD_TIMELIMIT); +                    buildViewsTree(cat->getUUID(), parent_id, cat, folder_view_item, mFolderRoot.get(), BUILD_TIMELIMIT); +                }              } -            else // Todo: timelimits +            else              { -                initRootContent(cat->getUUID()); +                findAndInitRootContent(cat->getUUID());              }          }      } @@ -2303,12 +2349,17 @@ void LLInventoryFavoritesItemsPanel::initRootContent(const LLUUID& id)          for (S32 i = 0; i < count; ++i)          {              LLViewerInventoryItem* item = items->at(i); -            if (item->getIsFavorite() && typedViewsFilter(id, item)) +            const LLUUID item_id = item->getUUID(); +            if (item->getIsFavorite() && typedViewsFilter(item_id, item))              { -                const LLUUID& parent_id = item->getParentUUID(); -                LLFolderViewItem* folder_view_item = getItemByID(id); // Should be NULL +                LLFolderViewItem* folder_view_item = getItemByID(id); +                if (!folder_view_item) +                { +                    const LLUUID& parent_id = item->getParentUUID(); +                    mRootContentIDs.emplace(item_id); -                buildViewsTree(item->getUUID(), parent_id, item, folder_view_item, mFolderRoot.get(), BUILD_TIMELIMIT); +                    buildViewsTree(item_id, parent_id, item, folder_view_item, mFolderRoot.get(), BUILD_TIMELIMIT); +                }              }          }      } @@ -2316,9 +2367,123 @@ void LLInventoryFavoritesItemsPanel::initRootContent(const LLUUID& id)  void LLInventoryFavoritesItemsPanel::initRootContent()  { -    initRootContent(gInventory.getRootFolderID()); // My Inventory +    findAndInitRootContent(gInventory.getRootFolderID()); // My Inventory +} + +bool LLInventoryFavoritesItemsPanel::removeFavorite(const LLUUID& id, const LLInventoryObject* model_item) +{ +    std::set<LLUUID>::iterator found = mRootContentIDs.find(id); +    if (found == mRootContentIDs.end()) +    { +        return false; +    } + +    mRootContentIDs.erase(found); + +    // This item is in root's content, remove item's UI. +    LLFolderViewItem* view_item = getItemByID(id); +    if (view_item) +    { +        LLFolderViewFolder* parent = view_item->getParentFolder(); +        LLFolderViewModelItemInventory* viewmodel_item = static_cast<LLFolderViewModelItemInventory*>(view_item->getViewModelItem()); +        if (viewmodel_item) +        { +            removeItemID(viewmodel_item->getUUID()); +        } +        view_item->destroyView(); +        if (parent) +        { +            parent->getViewModelItem()->dirtyDescendantsFilter(); +            LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(parent->getViewModelItem()); +            if (viewmodel_folder) +            { +                updateFolderLabel(viewmodel_folder->getUUID()); +            } +            if (view_item->isFavorite()) +            { +                parent->updateHasFavorites(false); // favorite was removed +            } +        } +    } + +    return true;  } +void LLInventoryFavoritesItemsPanel::itemChanged(const LLUUID& id, U32 mask, const LLInventoryObject* model_item) +{ +    if (!model_item && !getItemByID(id)) +    { +        // remove operation, but item is not in panel already +        return; +    } + +    bool handled = false; + +    if (mask & (LLInventoryObserver::UPDATE_FAVORITE | +        LLInventoryObserver::STRUCTURE | +        LLInventoryObserver::ADD | +        LLInventoryObserver::REMOVE)) +    { +        if (model_item && model_item->getIsFavorite()) +        { +            LLFolderViewItem* view_item = getItemByID(id); +            if (!view_item) +            { +                const LLViewerInventoryCategory* cat = dynamic_cast<const LLViewerInventoryCategory*>(model_item); +                if (cat) +                { +                    // New favorite folder +                    if (cat->getPreferredType() != LLFolderType::FT_TRASH) +                    { +                        // If any descendants were in the list, remove them +                        LLFavoritesCollector is_favorite; +                        LLInventoryModel::cat_array_t cat_array; +                        LLInventoryModel::item_array_t item_array; +                        gInventory.collectDescendentsIf(id, cat_array, item_array, FALSE, is_favorite); +                        for (LLInventoryModel::cat_array_t::const_iterator it = cat_array.begin(); it != cat_array.end(); ++it) +                        { +                            removeFavorite((*it)->getUUID(), *it); +                        } +                        for (LLInventoryModel::item_array_t::const_iterator it = item_array.begin(); it != item_array.end(); ++it) +                        { +                            removeFavorite((*it)->getUUID(), *it); +                        } + +                        LLFolderViewItem* folder_view_item = getItemByID(cat->getUUID()); +                        if (!folder_view_item) +                        { +                            const LLUUID& parent_id = cat->getParentUUID(); +                            mRootContentIDs.emplace(cat->getUUID()); + +                            buildViewsTree(cat->getUUID(), parent_id, cat, folder_view_item, mFolderRoot.get(), BUILD_ONE_FOLDER); +                        } +                    } +                } +                else +                { +                    // New favorite item +                    if (model_item->getIsFavorite() && typedViewsFilter(id, model_item)) +                    { +                        const LLUUID& parent_id = model_item->getParentUUID(); +                        mRootContentIDs.emplace(id); + +                        buildViewsTree(id, parent_id, model_item, NULL, mFolderRoot.get(), BUILD_ONE_FOLDER); +                    } +                } +                handled = true; +            } +        } +        else +        { +            handled = removeFavorite(id, model_item); +        } +    } + +    if (!handled) +    { +        LLInventoryPanel::itemChanged(id, mask, model_item); +    } +}  /************************************************************************/  /* LLInventorySingleFolderPanel                                         */  /************************************************************************/ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index b6d21ea9a8..a03ec15777 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -251,7 +251,7 @@ public:  													bool reset_filter = false);  	static void setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id);  	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); -	void removeItemID(const LLUUID& id); +	virtual 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); @@ -335,6 +335,7 @@ protected:  	// Builds the UI.  Call this once the inventory is usable.  	void 				initializeViews(F64 max_time);      virtual void        initRootContent(); +    virtual void        findAndInitRootContent(const LLUUID& root_id) {};  	// Specific inventory colors  	static bool                 sColorSetInitialized; @@ -395,7 +396,7 @@ protected:      EViewsInitializationState	mViewsInitialized; // Whether views have been generated      F64							mBuildViewsEndTime; // Stop building views past this timestamp      std::deque<LLUUID>			mBuildViewsQueue; -    std::deque<LLUUID>			mBuildRootContent; +    std::deque<LLUUID>			mBuildRootQueue;  }; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b9a7c9448f..3a4ac96826 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1436,7 +1436,8 @@ void update_inventory_category(  	if(obj)  	{          if (LLFolderType::lookupIsProtectedType(obj->getPreferredType()) -            && (updates.size() != 1 || !updates.has("thumbnail"))) +            && (updates.size() != 1 +                || !(updates.has("thumbnail") || updates.has("favorite"))))  		{  			LLNotificationsUtil::add("CannotModifyProtectedCategories");  			return;  | 
