void LLInventoryPanel::modelChanged(U32 mask) { static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); LLFastTimer t2(FTM_REFRESH); if (!mViewsInitialized) return; const LLInventoryModel* model = getModel(); if (!model) return; const LLInventoryModel::changed_items_t& changed_items = model->getChangedIDs(); if (changed_items.empty()) return; for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); items_iter != changed_items.end(); ++items_iter) { const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); LLFolderViewItem* view_item = mFolderRoot.get()->getItemByID(item_id); // 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. LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); ////////////////////////////// // LABEL Operation // Empty out the display name for relabel. if (mask & LLInventoryObserver::LABEL) { if (view_item) { // Request refresh on this item (also flags for filtering) LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener(); if(bridge) { // Clear the display name first, so it gets properly re-built during refresh() bridge->clearDisplayName(); view_item->refresh(); } // Singu note: Needed to propagate name change to wearables. view_item->nameOrDescriptionChanged(); } } ////////////////////////////// // DESCRIPTION Operation (singu only) // Alert listener. if ((mask & LLInventoryObserver::DESCRIPTION)) { if (view_item) { view_item->nameOrDescriptionChanged(); } } ////////////////////////////// // REBUILD Operation // Destroy and regenerate the UI. if (mask & LLInventoryObserver::REBUILD) { if (model_item && view_item) { view_item->destroyView(); } view_item = buildNewViews(item_id); view_folder = dynamic_cast<LLFolderViewFolder *>(view_item); } ////////////////////////////// // INTERNAL Operation // This could be anything. For now, just refresh the item. if (mask & LLInventoryObserver::INTERNAL) { if (view_item) { view_item->refresh(); } } ////////////////////////////// // SORT Operation // Sort the folder. if (mask & LLInventoryObserver::SORT) { if (view_folder) { view_folder->requestSort(); } } // We don't typically care which of these masks the item is actually flagged with, since the masks // may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into // Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks // panel). What's relevant is that the item and UI are probably out of sync and thus need to be // resynchronized. if (mask & (LLInventoryObserver::STRUCTURE | LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) { ////////////////////////////// // ADD Operation // Item exists in memory but a UI element hasn't been created for it. if (model_item && !view_item) { // Add the UI element for this item. buildNewViews(item_id); // Select any newly created object that has the auto rename at top of folder root set. if(mFolderRoot.get()->getRoot()->needsAutoRename()) { setSelection(item_id, FALSE); } } ////////////////////////////// // STRUCTURE Operation // This item already exists in both memory and UI. It was probably reparented. else if (model_item && view_item) { // Don't process the item if it is the root if (view_item->getRoot() != view_item) { LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot.get()->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.get()); if (mInventory) { const LLUUID trash_id = mInventory->findCategoryUUIDForType(LLFolderType::FT_TRASH); if (trash_id != model_item->getParentUUID() && (mask & LLInventoryObserver::INTERNAL) && new_parent->isOpen()) { setSelection(item_id, FALSE); } } } 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(); } } } } ////////////////////////////// // REMOVE Operation // This item has been removed from memory, but its associated UI element still exists. else if (!model_item && view_item) { // Remove the item's UI. view_item->destroyView(); } } } }
void LLInventoryPanel::modelChanged(U32 mask) { LLFastTimer t2(LLFastTimer::FTM_REFRESH); bool handled = false; if(mask & LLInventoryObserver::LABEL) { handled = true; // label change - empty out the display name for each object // in this change set. const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); std::set<LLUUID>::const_iterator id_it = changed_items.begin(); std::set<LLUUID>::const_iterator id_end = changed_items.end(); LLFolderViewItem* view = NULL; LLInvFVBridge* bridge = NULL; for (;id_it != id_end; ++id_it) { view = mFolders->getItemByID(*id_it); if(view) { // request refresh on this item (also flags for filtering) bridge = (LLInvFVBridge*)view->getListener(); if(bridge) { // Clear the display name first, so it gets properly re-built during refresh() bridge->clearDisplayName(); } view->refresh(); } } } if((mask & (LLInventoryObserver::STRUCTURE | LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) != 0) { handled = true; // Record which folders are open by uuid. LLInventoryModel* model = getModel(); if (model) { const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); std::set<LLUUID>::const_iterator id_it = changed_items.begin(); std::set<LLUUID>::const_iterator id_end = changed_items.end(); for (;id_it != id_end; ++id_it) { // sync view with model LLInventoryObject* model_item = model->getObject(*id_it); LLFolderViewItem* view_item = mFolders->getItemByID(*id_it); if (model_item) { if (!view_item) { // this object was just created, need to build a view for it if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD) { llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl; } buildNewViews(*id_it); // select any newly created object // that has the auto rename at top of folder // root set if(mFolders->getRoot()->needsAutoRename()) { setSelection(*id_it, FALSE); } } else { // this object was probably moved, check its parent if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE) { llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl; } LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID()); if (view_item->getParentFolder() != new_parent) { view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent, mFolders); } } } else { if (view_item) { if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE) { llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl; } // item in view but not model, need to delete view view_item->destroyView(); } else { llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl; } } } } } if (!handled) { // it's a small change that only requires a refresh. // *TODO: figure out a more efficient way to do the refresh // since it is expensive on large inventories mFolders->refresh(); } }