summaryrefslogtreecommitdiff
path: root/indra/newview/llinventoryitemslist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llinventoryitemslist.cpp')
-rw-r--r--indra/newview/llinventoryitemslist.cpp141
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;