diff options
Diffstat (limited to 'indra/newview/llinventoryitemslist.cpp')
| -rw-r--r-- | indra/newview/llinventoryitemslist.cpp | 141 |
1 files changed, 122 insertions, 19 deletions
diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 9e936eee5b..15735ebde3 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -40,6 +40,10 @@ #include "llinventorymodel.h" #include "llviewerinventory.h" +bool LLInventoryItemsList::sListIdleRegistered = false; +LLInventoryItemsList::all_list_t LLInventoryItemsList::sAllLists; +LLInventoryItemsList::all_list_t::iterator LLInventoryItemsList::sAllListIter; + LLInventoryItemsList::Params::Params() {} @@ -47,6 +51,7 @@ LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p : LLFlatListViewEx(p) , mRefreshState(REFRESH_COMPLETE) , mForceRefresh(false) +, mNeedsArrange(true) { // TODO: mCommitOnSelectionChange is set to "false" in LLFlatListView // but reset to true in all derived classes. This settings might need to @@ -55,13 +60,39 @@ LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p setNoFilteredItemsMsg(LLTrans::getString("InventoryNoMatchingItems")); - gIdleCallbacks.addFunction(idle, this); + sAllLists.push_back(this); + sAllListIter = sAllLists.begin(); + + if (!sListIdleRegistered) + { + sAllListIter = sAllLists.begin(); + gIdleCallbacks.addFunction(idle, nullptr); + + LLEventPumps::instance().obtain("LLApp").listen( + "LLInventoryItemsList", + [](const LLSD& stat) + { + std::string status(stat["status"]); + if (status != "running") + { + // viewer is starting shutdown + gIdleCallbacks.deleteFunction(idle, nullptr); + } + return false; + }); + sListIdleRegistered = true; + } } // virtual LLInventoryItemsList::~LLInventoryItemsList() { - gIdleCallbacks.deleteFunction(idle, this); + auto it = std::find(sAllLists.begin(), sAllLists.end(), this); + if (it != sAllLists.end()) + { + sAllLists.erase(it); + sAllListIter = sAllLists.begin(); + } } void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item_array) @@ -99,7 +130,7 @@ void LLInventoryItemsList::updateSelection() for(std::vector<LLSD>::const_iterator cur_id_it = cur.begin(); cur_id_it != cur.end() && !mSelectTheseIDs.empty(); ++cur_id_it) { - uuid_vec_t::iterator select_ids_it = std::find(mSelectTheseIDs.begin(), mSelectTheseIDs.end(), *cur_id_it); + uuid_vec_t::iterator select_ids_it = std::find(mSelectTheseIDs.begin(), mSelectTheseIDs.end(), cur_id_it->asUUID()); if(select_ids_it != mSelectTheseIDs.end()) { selectItemByUUID(*select_ids_it); @@ -111,25 +142,56 @@ void LLInventoryItemsList::updateSelection() mSelectTheseIDs.clear(); } -void LLInventoryItemsList::doIdle() +bool LLInventoryItemsList::doIdle() { - if (mRefreshState == REFRESH_COMPLETE) return; + if (mRefreshState == REFRESH_COMPLETE) return true; // done + LL_PROFILE_ZONE_SCOPED; - if (isInVisibleChain() || mForceRefresh ) + if (isInVisibleChain() || mForceRefresh || !getFilterSubString().empty()) { refresh(); mRefreshCompleteSignal(this, LLSD()); + return false; // keep going } + return true; // done } //static void LLInventoryItemsList::idle(void* user_data) { - LLInventoryItemsList* self = static_cast<LLInventoryItemsList*>(user_data); - if ( self ) - { // Do the real idle - self->doIdle(); + if (sAllLists.empty()) + return; + + LL_PROFILE_ZONE_SCOPED; + + using namespace std::chrono; + auto start = steady_clock::now(); + const milliseconds time_limit = milliseconds(2); + const auto end_time = start + time_limit; + S32 max_update_count = 50; + + if (sAllListIter == sAllLists.end()) + { + sAllListIter = sAllLists.begin(); + } + + S32 updated = 0; + while (steady_clock::now() < end_time + && updated < max_update_count + && sAllListIter != sAllLists.end()) + { + LLInventoryItemsList* list = *sAllListIter; + // Refresh is split into multiple separate parts, + // so keep repeating it while there is time, until done. + // Todo: refresh() split is pointless now? + // Or still useful for large folders? + if (list->doIdle()) + { + // Item is done + ++sAllListIter; + updated++; + } } } @@ -141,6 +203,7 @@ void LLInventoryItemsList::refresh() { case REFRESH_ALL: { + LL_PROFILE_ZONE_NAMED("items_refresh_all"); mAddedItems.clear(); mRemovedItems.clear(); computeDifference(getIDs(), mAddedItems, mRemovedItems); @@ -157,24 +220,35 @@ void LLInventoryItemsList::refresh() mRefreshState = REFRESH_LIST_SORT; } - rearrangeItems(); - notifyParentItemsRectChanged(); break; } case REFRESH_LIST_ERASE: { + LL_PROFILE_ZONE_NAMED("items_refresh_erase"); uuid_vec_t::const_iterator it = mRemovedItems.begin(); for (; mRemovedItems.end() != it; ++it) { // don't filter items right away - removeItemByUUID(*it, false); + removeItemByUUID(*it, false /*don't rearrange*/); } mRemovedItems.clear(); - mRefreshState = REFRESH_LIST_SORT; // fix visibility and arrange + mRefreshState = REFRESH_LIST_SORT; // fix visibility + + // Assume that visible items were removed. + if (getVisible()) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + else + { + mNeedsArrange = true; + } break; } case REFRESH_LIST_APPEND: { + LL_PROFILE_ZONE_NAMED("items_refresh_append"); static const unsigned ADD_LIMIT = 25; // Note: affects perfomance unsigned int nadded = 0; @@ -212,18 +286,25 @@ void LLInventoryItemsList::refresh() LLSD action; action.with("match_filter", cur_filter); + bool new_visible_items = false; pairs_const_iterator_t pair_it = panel_list.begin(); for (; pair_it != panel_list.end(); ++pair_it) { item_pair_t* item_pair = *pair_it; if (item_pair->first->getParent() != NULL) { - updateItemVisibility(item_pair->first, action); + new_visible_items |= updateItemVisibility(item_pair->first, action); } } - rearrangeItems(); - notifyParentItemsRectChanged(); + mNeedsArrange |= new_visible_items; + if (mNeedsArrange && getVisible()) + { + // show changes now + rearrangeItems(); + notifyParentItemsRectChanged(); + mNeedsArrange = false; + } if (mAddedItems.size() > 0) { @@ -239,23 +320,44 @@ void LLInventoryItemsList::refresh() } case REFRESH_LIST_SORT: { + LL_PROFILE_ZONE_NAMED("items_refresh_sort"); // Filter, sort, rearrange and notify parent about shape changes - filterItems(true, true); + if (filterItems(true, true)) + { + mNeedsArrange = false; // just rearranged + } if (mAddedItems.size() == 0) { + if (mNeedsArrange) + { + // Done, last chance to rearrange + rearrangeItems(); + notifyParentItemsRectChanged(); + mNeedsArrange = false; + } // After list building completed, select items that had been requested to select before list was build updateSelection(); mRefreshState = REFRESH_COMPLETE; } else { + if (mNeedsArrange && getVisible()) + { + // show changes now + rearrangeItems(); + notifyParentItemsRectChanged(); + mNeedsArrange = false; + } mRefreshState = REFRESH_LIST_APPEND; } break; } default: - break; + { + mRefreshState = REFRESH_COMPLETE; + break; + } } setForceRefresh(mRefreshState != REFRESH_COMPLETE); @@ -280,6 +382,7 @@ void LLInventoryItemsList::computeDifference( LLPanel* LLInventoryItemsList::createNewItem(LLViewerInventoryItem* item) { + LL_PROFILE_ZONE_SCOPED; if (!item) { LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL; |
