void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) { LLViewerInventoryCategory* cat; if (!model || !get_is_category_renameable(model, cat_id) || (cat = model->getCategory(cat_id)) == NULL || cat->getName() == new_name) { return; } LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); new_cat->rename(new_name); new_cat->updateServer(FALSE); model->updateCategory(new_cat); model->notifyObservers(); }
void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) { outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id); if (outfits_iter != mOutfitsMap.end()) { LLViewerInventoryCategory *cat = gInventory.getCategory(category_id); if (!cat) return; std::string name = cat->getName(); // Update tab name with the new category name. LLAccordionCtrlTab* tab = outfits_iter->second; if (tab) { tab->setName(name); tab->setTitle(name); } } }
void LLInventoryCategoriesObserver::changed(U32 mask) { if (!mCategoryMap.size()) return; std::vector<LLUUID> deleted_categories_ids; for (category_map_t::iterator iter = mCategoryMap.begin(); iter != mCategoryMap.end(); ++iter) { const LLUUID& cat_id = (*iter).first; LLCategoryData& cat_data = (*iter).second; LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); if (!category) { LL_WARNS() << "Category : Category id = " << cat_id << " disappeared" << LL_ENDL; cat_data.mCallback(); // Keep track of those deleted categories so we can remove them deleted_categories_ids.push_back(cat_id); continue; } const S32 version = category->getVersion(); const S32 expected_num_descendents = category->getDescendentCount(); if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) || (expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)) { continue; } // Check number of known descendents to find out whether it has changed. LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(cat_id, cats, items); if (!cats || !items) { LL_WARNS() << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << LL_ENDL; // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean // that the cat just doesn't have any items or subfolders). // Unrecoverable, so just skip this category. llassert(cats != NULL && items != NULL); continue; } const S32 current_num_known_descendents = cats->size() + items->size(); bool cat_changed = false; // If category version or descendents count has changed // update category data in mCategoryMap if (version != cat_data.mVersion || current_num_known_descendents != cat_data.mDescendentsCount) { cat_data.mVersion = version; cat_data.mDescendentsCount = current_num_known_descendents; cat_changed = true; } // If any item names have changed, update the name hash // Only need to check if (a) name hash has not previously been // computed, or (b) a name has changed. if (!cat_data.mIsNameHashInitialized || (mask & LLInventoryObserver::LABEL)) { LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id); if (cat_data.mItemNameHash != item_name_hash) { cat_data.mIsNameHashInitialized = true; cat_data.mItemNameHash = item_name_hash; cat_changed = true; } } // If anything has changed above, fire the callback. if (cat_changed) cat_data.mCallback(); } // Remove deleted categories from the list for (std::vector<LLUUID>::iterator deleted_id = deleted_categories_ids.begin(); deleted_id != deleted_categories_ids.end(); ++deleted_id) { removeCategory(*deleted_id); } }
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLInventoryPanel *panel = mPtr; LLInventoryModel* model = panel->getModel(); if(!model) return true; std::set<LLUUID> selected_items; panel->getRootFolder()->getSelectionList(selected_items); std::string name; static int session_num = 1; LLDynamicArray<LLUUID> members; EInstantMessage type = IM_SESSION_CONFERENCE_START; std::set<LLUUID>::const_iterator iter; for (iter = selected_items.begin(); iter != selected_items.end(); iter++) { LLUUID item = *iter; LLFolderViewItem* folder_item = panel->getRootFolder()->getItemByID(item); if(folder_item) { LLFolderViewEventListener* fve_listener = folder_item->getListener(); if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) { LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); if(!bridge) return true; LLViewerInventoryCategory* cat = bridge->getCategory(); if(!cat) return true; name = cat->getName(); LLUniqueBuddyCollector is_buddy; LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; model->collectDescendentsIf(bridge->getUUID(), cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_buddy); S32 count = item_array.count(); if(count > 0) { // create the session gIMMgr->setFloaterOpen(TRUE); S32 i; LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id; for(i = 0; i < count; ++i) { id = item_array.get(i)->getCreatorUUID(); if(at.isBuddyOnline(id)) { members.put(id); } } } } else { LLFolderViewItem* folder_item = panel->getRootFolder()->getItemByID(item); if(!folder_item) return true; LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) { LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID()); if (inv_item) { LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id = inv_item->getCreatorUUID(); if(at.isBuddyOnline(id)) { members.put(id); } } } //if IT_CALLINGCARD } //if !IT_CATEGORY } } //for selected_items // the session_id is randomly generated UUID which will be replaced later // with a server side generated number if (name.empty()) { name = llformat("Session %d", session_num++); } gIMMgr->addSession( name, type, members[0], members); return true; }
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLInventoryPanel *panel = mPtr; LLInventoryModel* model = panel->getModel(); if(!model) return true; std::set<LLUUID> selected_items = panel->getRootFolder()->getSelectionList(); std::string name; static int session_num = 1; std::vector<LLUUID> members; EInstantMessage type = IM_SESSION_CONFERENCE_START; // [RLVa:KB] - Checked: 2013-05-08 (RLVa-1.4.9) bool fRlvCanStartIM = true; // [/RLVa:KB] for (std::set<LLUUID>::const_iterator iter = selected_items.begin(); iter != selected_items.end(); iter++) { LLUUID item = *iter; LLFolderViewItem* folder_item = panel->getRootFolder()->getItemByID(item); if(folder_item) { LLFolderViewEventListener* fve_listener = folder_item->getListener(); if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) { LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); if(!bridge) return true; LLViewerInventoryCategory* cat = bridge->getCategory(); if(!cat) return true; name = cat->getName(); LLUniqueBuddyCollector is_buddy; LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; model->collectDescendentsIf(bridge->getUUID(), cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_buddy); S32 count = item_array.size(); if(count > 0) { // create the session gIMMgr->setFloaterOpen(TRUE); LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id; for(S32 i = 0; i < count; ++i) { id = item_array.at(i)->getCreatorUUID(); if(at.isBuddyOnline(id)) { // [RLVa:KB] - Checked: 2013-05-08 (RLVa-1.4.9) fRlvCanStartIM &= RlvActions::canStartIM(id); // [RLVa:KB] members.push_back(id); } } } } else { LLFolderViewItem* folder_item = panel->getRootFolder()->getItemByID(item); if(!folder_item) return true; LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) { LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID()); if (inv_item) { LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id = inv_item->getCreatorUUID(); if(at.isBuddyOnline(id)) { // [RLVa:KB] - Checked: 2013-05-08 (RLVa-1.4.9) fRlvCanStartIM &= RlvActions::canStartIM(id); // [RLVa:KB] members.push_back(id); } } } //if IT_CALLINGCARD } //if !IT_CATEGORY } } //for selected_items // the session_id is randomly generated UUID which will be replaced later // with a server side generated number // [RLVa:KB] - Checked: 2013-05-08 (RLVa-1.4.9) if (!fRlvCanStartIM) { make_ui_sound("UISndIvalidOp"); RlvUtil::notifyBlocked(RLV_STRING_BLOCKED_STARTCONF); return true; } // [/RLVa:KB] if (name.empty()) { name = llformat("Session %d", session_num++); } gIMMgr->addSession( name, type, members[0], members); return true; }
void LLOutfitsList::refreshList(const LLUUID& category_id) { LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; // Collect all sub-categories of a given category. LLIsType is_category(LLAssetType::AT_CATEGORY); gInventory.collectDescendentsIf( category_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category); uuid_vec_t vadded; uuid_vec_t vremoved; // Create added and removed items vectors. computeDifference(cat_array, vadded, vremoved); // Handle added tabs. for (uuid_vec_t::const_iterator iter = vadded.begin(); iter != vadded.end(); ++iter) { const LLUUID cat_id = (*iter); LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); if (!cat) continue; std::string name = cat->getName(); outfit_accordion_tab_params tab_params(get_accordion_tab_params()); LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); if (!tab) continue; LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); wearable_list->setShape(tab->getLocalRect()); tab->addChild(wearable_list); tab->setName(name); tab->setTitle(name); // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. tab->setDisplayChildren(false); mAccordion->addCollapsibleCtrl(tab); // Start observing the new outfit category. LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list"); if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) { // Remove accordion tab if category could not be added to observer. mAccordion->removeCollapsibleCtrl(tab); // kill removed tab tab->die(); continue; } // Map the new tab with outfit category UUID. mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this, _1, _2, _3, cat_id)); // Setting tab focus callback to monitor currently selected outfit. tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id)); // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875) tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id)); // force showing list items that don't match current filter(EXT-7158) list->setForceShowingUnmatchedItems(true); // Setting list commit callback to monitor currently selected wearable item. list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1)); // Setting list refresh callback to apply filter on list change. list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); // Fetch the new outfit contents. cat->fetch(); // Refresh the list of outfit items after fetch(). // Further list updates will be triggered by the category observer. list->updateList(cat_id); // If filter is currently applied we store the initial tab state and // open it to show matched items if any. if (!sFilterSubString.empty()) { tab->notifyChildren(LLSD().with("action","store_state")); tab->setDisplayChildren(true); // Setting mForceRefresh flag will make the list refresh its contents // even if it is not currently visible. This is required to apply the // filter to the newly added list. list->setForceRefresh(true); list->setFilterSubString(sFilterSubString); } } // Handle removed tabs. for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter) { outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter)); if (outfits_iter != mOutfitsMap.end()) { const LLUUID& outfit_id = outfits_iter->first; LLAccordionCtrlTab* tab = outfits_iter->second; // An outfit is removed from the list. Do the following: // 1. Remove outfit category from observer to stop monitoring its changes. mCategoriesObserver->removeCategory(outfit_id); // 2. Remove the outfit from selection. deselectOutfit(outfit_id); // 3. Remove category UUID to accordion tab mapping. mOutfitsMap.erase(outfits_iter); // 4. Remove outfit tab from accordion. mAccordion->removeCollapsibleCtrl(tab); // kill removed tab if (tab != NULL) { tab->die(); } } } // Get changed items from inventory model and update outfit tabs // which might have been renamed. const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); items_iter != changed_items.end(); ++items_iter) { updateOutfitTab(*items_iter); } mAccordion->sort(); }
// Checked: 2010-03-14 (RLVa-1.1.3a) | Added: RLVa-1.2.0a void RlvRenameOnWearObserver::doneIdle() { const LLViewerInventoryCategory* pRlvRoot = NULL; LLVOAvatar* pAvatar = gAgentAvatarp; if ( (RlvSettings::getEnableSharedWear()) || (!RlvSettings::getSharedInvAutoRename()) || (LLStartUp::getStartupState() < STATE_STARTED) || (!pAvatar) || ((pRlvRoot = RlvInventory::instance().getSharedRoot()) == NULL) ) { delete this; return; } const LLViewerJointAttachment* pAttachPt = NULL; S32 idxAttachPt = 0; // RLV_ASSERT(mComplete.size() > 0); // Catch instances where we forgot to call startFetch() for (uuid_vec_t::const_iterator itItem = mComplete.begin(); itItem != mComplete.end(); ++itItem) { const LLUUID& idAttachItem = *itItem; // If the item resides under #RLV we'll rename it directly; otherwise settle for "renaming" all of its links residing under #RLV LLInventoryModel::item_array_t items; if (gInventory.isObjectDescendentOf(idAttachItem, pRlvRoot->getUUID())) items.push_back(gInventory.getItem(idAttachItem)); else items = gInventory.collectLinkedItems(idAttachItem, pRlvRoot->getUUID()); if (items.empty()) continue; if ( ((pAttachPt = pAvatar->getWornAttachmentPoint(idAttachItem)) == NULL) || ((idxAttachPt = RlvAttachPtLookup::getAttachPointIndex(pAttachPt)) == 0) ) { // RLV_ASSERT(false); continue; } static const std::string &new_category_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_NONE); for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++) { LLViewerInventoryItem* pItem = items.get(idxItem); if (!pItem) continue; S32 idxAttachPtItem = RlvAttachPtLookup::getAttachPointIndex(pItem); if ( (idxAttachPt == idxAttachPtItem) || (idxAttachPtItem) ) continue; std::string strAttachPt = pAttachPt->getName(); LLStringUtil::toLower(strAttachPt); // If we can modify the item then we rename it directly, otherwise we create a new folder and move it if (pItem->getPermissions().allowModifyBy(gAgent.getID())) { std::string strName = pItem->getName(); LLStringUtil::truncate(strName, DB_INV_ITEM_NAME_STR_LEN - strAttachPt.length() - 3); strName += " (" + strAttachPt + ")"; pItem->rename(strName); pItem->updateServer(FALSE); gInventory.addChangedMask(LLInventoryObserver::LABEL, pItem->getUUID()); } else { // Don't do anything if the item is a direct descendant of the shared root, or a folded folder LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID()); if ( (pFolder) && (pFolder->getUUID() != pRlvRoot->getUUID()) && (!RlvInventory::isFoldedFolder(pFolder, false)) ) { std::string strFolderName = ".(" + strAttachPt + ")"; // Rename the item's parent folder if it's called "New Folder", isn't directly under #RLV and contains exactly 1 object if ( (new_category_name == pFolder->getName()) && (pFolder->getParentUUID() != pRlvRoot->getUUID()) && (1 == RlvInventory::getDirectDescendentsCount(pFolder, LLAssetType::AT_OBJECT)) ) { pFolder->rename(strFolderName); pFolder->updateServer(FALSE); gInventory.addChangedMask(LLInventoryObserver::LABEL, pFolder->getUUID()); } else { // "No modify" item with a non-renameable parent: create a new folder named and move the item into it LLUUID idAttachFolder = gInventory.createNewCategory(pFolder->getUUID(), LLFolderType::FT_NONE, strFolderName); move_inventory_item(gAgent.getID(), gAgent.getSessionID(), pItem->getUUID(), idAttachFolder, std::string(), NULL); } } } } } gInventory.notifyObservers(); delete this; }
// Checked: 2010-02-28 (RLVa-1.1.3a) | Modified: RLVa-1.0.0h LLViewerInventoryCategory* RlvInventory::getSharedRoot() const { if (gInventory.isInventoryUsable()) { LLInventoryModel::cat_array_t* pFolders; LLInventoryModel::item_array_t* pItems; gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), pFolders, pItems); if (pFolders) { // NOTE: we might have multiple #RLV folders so we'll just go with the first one we come across LLViewerInventoryCategory* pFolder; for (S32 idxFolder = 0, cntFolder = pFolders->count(); idxFolder < cntFolder; idxFolder++) { if ( ((pFolder = pFolders->get(idxFolder)) != NULL) && (RlvInventory::cstrSharedRoot == pFolder->getName()) ) return pFolder; } } } return NULL; }
void AISUpdate::doUpdate() { // Do version/descendent accounting. for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin(); catit != mCatDescendentDeltas.end(); ++catit) { LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL; const LLUUID cat_id(catit->first); // Don't account for update if we just created this category. if (mCategoriesCreated.find(cat_id) != mCategoriesCreated.end()) { LL_DEBUGS("Inventory") << "Skipping version increment for new category " << cat_id << LL_ENDL; continue; } // Don't account for update unless AIS told us it updated that category. if (mCatVersionsUpdated.find(cat_id) == mCatVersionsUpdated.end()) { LL_DEBUGS("Inventory") << "Skipping version increment for non-updated category " << cat_id << LL_ENDL; continue; } // If we have a known descendent count, set that now. LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); if (cat) { S32 descendent_delta = catit->second; S32 old_count = cat->getDescendentCount(); LL_DEBUGS("Inventory") << "Updating descendent count for " << cat->getName() << " " << cat_id << " with delta " << descendent_delta << " from " << old_count << " to " << (old_count+descendent_delta) << LL_ENDL; LLInventoryModel::LLCategoryUpdate up(cat_id, descendent_delta); gInventory.accountForUpdate(up); } else { LL_DEBUGS("Inventory") << "Skipping version accounting for unknown category " << cat_id << LL_ENDL; } } // CREATE CATEGORIES for (deferred_category_map_t::const_iterator create_it = mCategoriesCreated.begin(); create_it != mCategoriesCreated.end(); ++create_it) { LLUUID category_id(create_it->first); LLPointer<LLViewerInventoryCategory> new_category = create_it->second; gInventory.updateCategory(new_category, LLInventoryObserver::CREATE); LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL; } // UPDATE CATEGORIES for (deferred_category_map_t::const_iterator update_it = mCategoriesUpdated.begin(); update_it != mCategoriesUpdated.end(); ++update_it) { LLUUID category_id(update_it->first); LLPointer<LLViewerInventoryCategory> new_category = update_it->second; // Since this is a copy of the category *before* the accounting update, above, // we need to transfer back the updated version/descendent count. LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID()); if (!curr_cat) { LL_WARNS("Inventory") << "Failed to update unknown category " << new_category->getUUID() << LL_ENDL; } else { new_category->setVersion(curr_cat->getVersion()); new_category->setDescendentCount(curr_cat->getDescendentCount()); gInventory.updateCategory(new_category); LL_DEBUGS("Inventory") << "updated category " << new_category->getName() << " " << category_id << LL_ENDL; } } // CREATE ITEMS for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin(); create_it != mItemsCreated.end(); ++create_it) { LLUUID item_id(create_it->first); LLPointer<LLViewerInventoryItem> new_item = create_it->second; // FIXME risky function since it calls updateServer() in some // cases. Maybe break out the update/create cases, in which // case this is create. LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL; gInventory.updateItem(new_item, LLInventoryObserver::CREATE); } // UPDATE ITEMS for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin(); update_it != mItemsUpdated.end(); ++update_it) { LLUUID item_id(update_it->first); LLPointer<LLViewerInventoryItem> new_item = update_it->second; // FIXME risky function since it calls updateServer() in some // cases. Maybe break out the update/create cases, in which // case this is update. LL_DEBUGS("Inventory") << "updated item " << item_id << LL_ENDL; //LL_DEBUGS("Inventory") << ll_pretty_print_sd(new_item->asLLSD()) << LL_ENDL; gInventory.updateItem(new_item); } // DELETE OBJECTS for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin(); del_it != mObjectsDeletedIds.end(); ++del_it) { LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL; gInventory.onObjectDeletedFromServer(*del_it, false, false, false); } // TODO - how can we use this version info? Need to be sure all // changes are going through AIS first, or at least through // something with a reliable responder. for (uuid_int_map_t::iterator ucv_it = mCatVersionsUpdated.begin(); ucv_it != mCatVersionsUpdated.end(); ++ucv_it) { const LLUUID id = ucv_it->first; S32 version = ucv_it->second; LLViewerInventoryCategory *cat = gInventory.getCategory(id); LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << LL_ENDL; if (cat->getVersion() != version) { LL_WARNS() << "Possible version mismatch for category " << cat->getName() << ", viewer version " << cat->getVersion() << " server version " << version << LL_ENDL; } } gInventory.notifyObservers(); }
bool LLInventoryPanel::beginIMSession() { std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); std::string name; static int session_num = 1; // LLDynamicArray<LLUUID> members; // [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h uuid_vec_t members; // [/RLVa:KB] // EInstantMessage type = IM_SESSION_CONFERENCE_START; std::set<LLUUID>::const_iterator iter; for (iter = selected_items.begin(); iter != selected_items.end(); iter++) { LLUUID item = *iter; LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); if(folder_item) { LLFolderViewEventListener* fve_listener = folder_item->getListener(); if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) { LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); if(!bridge) return true; LLViewerInventoryCategory* cat = bridge->getCategory(); if(!cat) return true; name = cat->getName(); LLUniqueBuddyCollector is_buddy; LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendentsIf(bridge->getUUID(), cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_buddy); S32 count = item_array.count(); if(count > 0) { //*TODO by what to replace that? //LLFloaterReg::showInstance("communicate"); // create the session LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id; for(S32 i = 0; i < count; ++i) { id = item_array.get(i)->getCreatorUUID(); if(at.isBuddyOnline(id)) { // members.put(id); // [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h members.push_back(id); // [/RLVa:KB] } } } } else { LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); if(!folder_item) return true; LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) { LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID()); if (inv_item) { LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id = inv_item->getCreatorUUID(); if(at.isBuddyOnline(id)) { // members.put(id); // [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h members.push_back(id); // [/RLVa:KB] } } } //if IT_CALLINGCARD } //if !IT_CATEGORY } } //for selected_items // the session_id is randomly generated UUID which will be replaced later // with a server side generated number if (name.empty()) { name = llformat("Session %d", session_num++); } // LLUUID session_id = gIMMgr->addSession(name, type, members[0], members); // if (session_id != LLUUID::null) // { // LLIMFloater::show(session_id); // } // [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h LLAvatarActions::startConference(members); // [/RLVa:KB] return true; }
void LLOutfitsList::refreshList(const LLUUID& category_id) { LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; // Collect all sub-categories of a given category. // <FS:ND> FIRE-6958/VWR-2862; Make sure to only collect folders of type FT_OUTFIT class ndOutfitsCollector: public LLIsType { public: ndOutfitsCollector() : LLIsType( LLAssetType::AT_CATEGORY ) { } virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if( !LLIsType::operator()( cat, item ) ) return false; if( cat && LLFolderType::FT_OUTFIT == cat->getPreferredType() ) return true; return false; } }; // LLIsType is_category(LLAssetType::AT_CATEGORY); ndOutfitsCollector is_category; // </FS:ND> gInventory.collectDescendentsIf( category_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category); uuid_vec_t vadded; uuid_vec_t vremoved; // Create added and removed items vectors. computeDifference(cat_array, vadded, vremoved); // <FS:ND> FIRE-6958/VWR-2862; Handle large amounts of outfits, write a least a warning into the logs. if( vadded.size() > 128 ) LL_WARNS() << "Large amount of outfits found: " << vadded.size() << " this may cause hangs and disconnects" << LL_ENDL; U32 nCap = gSavedSettings.getU32( "FSDisplaySavedOutfitsCap" ); if( nCap && nCap < vadded.size() ) { vadded.resize( nCap ); LL_WARNS() << "Capped outfits to " << nCap << " due to debug setting FSDisplaySavedOutfitsCap" << LL_ENDL; } // </FS:ND> // <FS:Ansariel> FIRE-12939: Add outfit count to outfits list getChild<LLTextBox>("OutfitcountText")->setTextArg("COUNT", llformat("%d", cat_array.size())); // Handle added tabs. for (uuid_vec_t::const_iterator iter = vadded.begin(); iter != vadded.end(); ++iter) { const LLUUID cat_id = (*iter); LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); if (!cat) continue; std::string name = cat->getName(); outfit_accordion_tab_params tab_params(get_accordion_tab_params()); LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); if (!tab) continue; LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); wearable_list->setShape(tab->getLocalRect()); tab->addChild(wearable_list); tab->setName(name); tab->setTitle(name); // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. tab->setDisplayChildren(false); // <FS:ND> Calling this when there's a lot of outfits causes horrible perfomance and disconnects, due to arrange eating so many cpu cycles. // mAccordion->addCollapsibleCtrl(tab); mAccordion->addCollapsibleCtrl(tab, false ); // </FS:ND> // Start observing the new outfit category. LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list"); if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) { // Remove accordion tab if category could not be added to observer. mAccordion->removeCollapsibleCtrl(tab); // kill removed tab tab->die(); continue; } // Map the new tab with outfit category UUID. mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this, _1, _2, _3, cat_id)); // Setting tab focus callback to monitor currently selected outfit. tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id)); // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875) tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id)); // force showing list items that don't match current filter(EXT-7158) list->setForceShowingUnmatchedItems(true); // Setting list commit callback to monitor currently selected wearable item. list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1)); // Setting list refresh callback to apply filter on list change. list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); // Fetch the new outfit contents. cat->fetch(); // Refresh the list of outfit items after fetch(). // Further list updates will be triggered by the category observer. list->updateList(cat_id); // If filter is currently applied we store the initial tab state and // open it to show matched items if any. if (!sFilterSubString.empty()) { tab->notifyChildren(LLSD().with("action","store_state")); tab->setDisplayChildren(true); // Setting mForceRefresh flag will make the list refresh its contents // even if it is not currently visible. This is required to apply the // filter to the newly added list. list->setForceRefresh(true); list->setFilterSubString(sFilterSubString); } } // <FS:ND> We called mAccordion->addCollapsibleCtrl with false as second paramter and did not let it arrange itself each time. Do this here after all is said and done. mAccordion->arrange(); // </FS:ND> // Handle removed tabs. for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter) { outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter)); if (outfits_iter != mOutfitsMap.end()) { const LLUUID& outfit_id = outfits_iter->first; LLAccordionCtrlTab* tab = outfits_iter->second; // An outfit is removed from the list. Do the following: // 1. Remove outfit category from observer to stop monitoring its changes. mCategoriesObserver->removeCategory(outfit_id); // 2. Remove the outfit from selection. deselectOutfit(outfit_id); // 3. Remove category UUID to accordion tab mapping. mOutfitsMap.erase(outfits_iter); // 4. Remove outfit tab from accordion. mAccordion->removeCollapsibleCtrl(tab); // kill removed tab if (tab != NULL) { tab->die(); } } } // Get changed items from inventory model and update outfit tabs // which might have been renamed. const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); items_iter != changed_items.end(); ++items_iter) { updateOutfitTab(*items_iter); } mAccordion->sort(); }