@@ -168,6 +168,8 @@ void AssetListViewModel::OnDataModelStringValueChanged(gsl::index nIndex, const
168168 const auto * pItem = pGameContext.Assets ().GetItemAt (nIndex);
169169 if (pItem != nullptr )
170170 {
171+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
172+
171173 const auto nFilteredIndex = GetFilteredAssetIndex (*pItem);
172174 if (nFilteredIndex != -1 )
173175 m_vFilteredAssets.SetItemValue (nFilteredIndex, AssetSummaryViewModel::LabelProperty, args.tNewValue );
@@ -179,6 +181,8 @@ void AssetListViewModel::OnDataModelStringValueChanged(gsl::index nIndex, const
179181 const auto * pAsset = pGameContext.Assets ().GetItemAt (nIndex);
180182 if (pAsset != nullptr )
181183 {
184+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
185+
182186 const auto nFilteredIndex = GetFilteredAssetIndex (*pAsset);
183187 if (nFilteredIndex != -1 )
184188 m_vFilteredAssets.SetItemValue (nFilteredIndex, args.Property , args.tNewValue );
@@ -194,11 +198,16 @@ void AssetListViewModel::OnDataModelIntValueChanged(gsl::index nIndex, const Int
194198 const auto * pAsset = pGameContext.Assets ().GetItemAt (nIndex);
195199 Expects (pAsset != nullptr );
196200 const auto * pAchievement = dynamic_cast <const ra::data::models::AchievementModel*>(pAsset);
197- if (pAchievement != nullptr && GetFilteredAssetIndex (*pAsset) >= 0 )
201+ if (pAchievement != nullptr )
198202 {
199- auto nPoints = GetTotalPoints ();
200- nPoints += args.tNewValue - args.tOldValue ;
201- SetValue (TotalPointsProperty, nPoints);
203+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
204+
205+ if (GetFilteredAssetIndex (*pAsset) >= 0 )
206+ {
207+ auto nPoints = GetTotalPoints ();
208+ nPoints += args.tNewValue - args.tOldValue ;
209+ SetValue (TotalPointsProperty, nPoints);
210+ }
202211 }
203212 }
204213 else if (args.Property == ra::data::models::AssetModelBase::StateProperty)
@@ -280,6 +289,8 @@ void AssetListViewModel::OnDataModelIntValueChanged(gsl::index nIndex, const Int
280289 const auto * pAsset = pGameContext.Assets ().GetItemAt (nIndex);
281290 if (pAsset != nullptr )
282291 {
292+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
293+
283294 const auto nFilteredIndex = GetFilteredAssetIndex (*pAsset);
284295 if (nFilteredIndex != -1 )
285296 {
@@ -301,21 +312,25 @@ void AssetListViewModel::OnDataModelIntValueChanged(gsl::index nIndex, const Int
301312
302313 RA_LOG_INFO (" %s %u ID changed from %d to %d" , ra::data::models::AssetModelBase::GetAssetTypeString (pAsset->GetType ()), pAsset->GetID (), args.tOldValue , args.tNewValue );
303314
304- // have to find the filtered item using the old ID
305- for (gsl::index nScanIndex = 0 ; nScanIndex < gsl::narrow_cast<gsl::index>(m_vFilteredAssets.Count ()); ++nScanIndex)
306315 {
307- auto * pItem = m_vFilteredAssets.GetItemAt (nScanIndex);
308- if (pItem != nullptr && pItem->GetId () == args.tOldValue && pItem->GetType () == nType)
316+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
317+
318+ // have to find the filtered item using the old ID
319+ for (gsl::index nScanIndex = 0 ; nScanIndex < gsl::narrow_cast<gsl::index>(m_vFilteredAssets.Count ()); ++nScanIndex)
309320 {
310- nFilteredIndex = nScanIndex;
311- break ;
321+ auto * pItem = m_vFilteredAssets.GetItemAt (nScanIndex);
322+ if (pItem != nullptr && pItem->GetId () == args.tOldValue && pItem->GetType () == nType)
323+ {
324+ nFilteredIndex = nScanIndex;
325+ break ;
326+ }
312327 }
313- }
314328
315- if (nFilteredIndex != -1 )
316- m_vFilteredAssets.SetItemValue (nFilteredIndex, AssetSummaryViewModel::IdProperty, args.tNewValue );
329+ if (nFilteredIndex != -1 )
330+ m_vFilteredAssets.SetItemValue (nFilteredIndex, AssetSummaryViewModel::IdProperty, args.tNewValue );
317331
318- AddOrRemoveFilteredItem (*pAsset);
332+ AddOrRemoveFilteredItem (*pAsset);
333+ }
319334 }
320335 }
321336}
@@ -332,19 +347,23 @@ void AssetListViewModel::OnDataModelRemoved(_UNUSED gsl::index nIndex)
332347 const auto & pGameContext = ra::services::ServiceLocator::Get<ra::data::context::GameContext>();
333348 if (!pGameContext.Assets ().IsUpdating ())
334349 {
335- // the item has already been removed from the vAssets collection, and all we know about it
336- // is the index where it was located. scan through the vFilteredAssets collection and remove
337- // any that no longer exist in the vAssets collection.
338- for (gsl::index nFilteredIndex = 0 ; nFilteredIndex < gsl::narrow_cast<gsl::index>(m_vFilteredAssets.Count ()); ++nFilteredIndex)
339350 {
340- auto * pItem = m_vFilteredAssets.GetItemAt (nFilteredIndex);
341- if (pItem != nullptr )
351+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
352+
353+ // the item has already been removed from the vAssets collection, and all we know about it
354+ // is the index where it was located. scan through the vFilteredAssets collection and remove
355+ // any that no longer exist in the vAssets collection.
356+ for (gsl::index nFilteredIndex = 0 ; nFilteredIndex < gsl::narrow_cast<gsl::index>(m_vFilteredAssets.Count ()); ++nFilteredIndex)
342357 {
343- if (!pGameContext.Assets ().FindAsset (pItem->GetType (), pItem->GetId ()))
358+ auto * pItem = m_vFilteredAssets.GetItemAt (nFilteredIndex);
359+ if (pItem != nullptr )
344360 {
345- m_vFilteredAssets.RemoveAt (nFilteredIndex);
346- UpdateButtons ();
347- break ;
361+ if (!pGameContext.Assets ().FindAsset (pItem->GetType (), pItem->GetId ()))
362+ {
363+ m_vFilteredAssets.RemoveAt (nFilteredIndex);
364+ UpdateButtons ();
365+ break ;
366+ }
348367 }
349368 }
350369 }
@@ -376,12 +395,16 @@ void AssetListViewModel::UpdateTotals()
376395 int nAchievementCount = 0 ;
377396 int nTotalPoints = 0 ;
378397
379- for (const auto & pAsset : m_vFilteredAssets)
380398 {
381- if (pAsset.GetType () == ra::data::models::AssetType::Achievement)
399+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
400+
401+ for (const auto & pAsset : m_vFilteredAssets)
382402 {
383- ++nAchievementCount;
384- nTotalPoints += pAsset.GetPoints ();
403+ if (pAsset.GetType () == ra::data::models::AssetType::Achievement)
404+ {
405+ ++nAchievementCount;
406+ nTotalPoints += pAsset.GetPoints ();
407+ }
385408 }
386409 }
387410
@@ -425,23 +448,27 @@ void AssetListViewModel::ApplyFilter()
425448 if (m_bInitializingFilter)
426449 return ;
427450
428- const auto & pGameContext = ra::services::ServiceLocator::Get<ra::data::context::GameContext>();
429- m_vFilteredAssets.BeginUpdate ();
430-
431- // first pass: remove any filtered items no longer in the source collection
432- for (gsl::index nIndex = gsl::narrow_cast<gsl::index>(m_vFilteredAssets.Count ()) -1 ; nIndex >= 0 ; --nIndex)
433451 {
434- auto * pItem = m_vFilteredAssets.GetItemAt (nIndex);
435- if (pItem != nullptr )
452+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
453+
454+ const auto & pGameContext = ra::services::ServiceLocator::Get<ra::data::context::GameContext>();
455+ m_vFilteredAssets.BeginUpdate ();
456+
457+ // first pass: remove any filtered items no longer in the source collection
458+ for (gsl::index nIndex = gsl::narrow_cast<gsl::index>(m_vFilteredAssets.Count ()) - 1 ; nIndex >= 0 ; --nIndex)
436459 {
437- if (!pGameContext.Assets ().FindAsset (pItem->GetType (), pItem->GetId ()))
438- m_vFilteredAssets.RemoveAt (nIndex);
460+ auto * pItem = m_vFilteredAssets.GetItemAt (nIndex);
461+ if (pItem != nullptr )
462+ {
463+ if (!pGameContext.Assets ().FindAsset (pItem->GetType (), pItem->GetId ()))
464+ m_vFilteredAssets.RemoveAt (nIndex);
465+ }
439466 }
440- }
441467
442- // second pass: update visibility of each item in the source collection
443- for (const auto & pAsset : pGameContext.Assets ())
444- AddOrRemoveFilteredItem (pAsset);
468+ // second pass: update visibility of each item in the source collection
469+ for (const auto & pAsset : pGameContext.Assets ())
470+ AddOrRemoveFilteredItem (pAsset);
471+ }
445472
446473 m_vFilteredAssets.EndUpdate ();
447474
@@ -528,7 +555,13 @@ void AssetListViewModel::AddOrRemoveFilteredItem(gsl::index nAssetIndex)
528555 const auto * pAsset = pGameContext.Assets ().GetItemAt (nAssetIndex);
529556 if (pAsset != nullptr )
530557 {
531- if (AddOrRemoveFilteredItem (*pAsset))
558+ bool bUpdated = false ;
559+ {
560+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
561+ bUpdated = AddOrRemoveFilteredItem (*pAsset);
562+ }
563+
564+ if (bUpdated)
532565 {
533566 UpdateTotals ();
534567 UpdateButtons ();
@@ -633,6 +666,8 @@ void AssetListViewModel::OpenEditor(const AssetSummaryViewModel* pAsset)
633666
634667bool AssetListViewModel::HasSelection (ra::data::models::AssetType nAssetType) const
635668{
669+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
670+
636671 for (const auto & pItem : m_vFilteredAssets)
637672 {
638673 if (pItem.IsSelected ())
@@ -722,6 +757,8 @@ void AssetListViewModel::DoUpdateButtons()
722757 {
723758 SetValue (CanCreateProperty, true );
724759
760+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
761+
725762 for (const auto & pItem : m_vFilteredAssets)
726763 {
727764 switch (pItem.GetChanges ())
@@ -937,6 +974,8 @@ void AssetListViewModel::GetSelectedAssets(std::vector<ra::data::models::AssetMo
937974{
938975 auto & pGameContext = ra::services::ServiceLocator::GetMutable<ra::data::context::GameContext>();
939976
977+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
978+
940979 for (const auto & pItem : m_vFilteredAssets)
941980 {
942981 if (pItem.IsSelected ())
@@ -1094,13 +1133,17 @@ void AssetListViewModel::SaveSelected()
10941133 if (sSaveButtonText .at (0 ) == ' &' ) // "&Save" / "&Save All"
10951134 {
10961135 // save - find the selected items (allow empty to mean all)
1097- for (const auto & pItem : m_vFilteredAssets)
10981136 {
1099- if (pItem.IsSelected ())
1137+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
1138+
1139+ for (const auto & pItem : m_vFilteredAssets)
11001140 {
1101- auto * pAsset = pGameContext.Assets ().FindAsset (pItem.GetType (), pItem.GetId ());
1102- if (pAsset != nullptr )
1103- vSelectedAssets.push_back (pAsset);
1141+ if (pItem.IsSelected ())
1142+ {
1143+ auto * pAsset = pGameContext.Assets ().FindAsset (pItem.GetType (), pItem.GetId ());
1144+ if (pAsset != nullptr )
1145+ vSelectedAssets.push_back (pAsset);
1146+ }
11041147 }
11051148 }
11061149
@@ -1431,13 +1474,17 @@ void AssetListViewModel::ResetSelected()
14311474
14321475 bool bCoreAssetSelected = false ;
14331476 std::vector<const AssetSummaryViewModel*> vSelectedAssets;
1434- for (const auto & pItem : m_vFilteredAssets)
14351477 {
1436- if (pItem.IsSelected ())
1478+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
1479+
1480+ for (const auto & pItem : m_vFilteredAssets)
14371481 {
1438- vSelectedAssets.push_back (&pItem);
1482+ if (pItem.IsSelected ())
1483+ {
1484+ vSelectedAssets.push_back (&pItem);
14391485
1440- bCoreAssetSelected |= (pItem.GetCategory () == ra::data::models::AssetCategory::Core);
1486+ bCoreAssetSelected |= (pItem.GetCategory () == ra::data::models::AssetCategory::Core);
1487+ }
14411488 }
14421489 }
14431490
@@ -1757,8 +1804,8 @@ void AssetListViewModel::CreateNew()
17571804 nType = vmNewAsset.GetSelectedType ();
17581805 }
17591806
1760- FilteredAssets ().BeginUpdate ();
17611807 bool bUpdateAsset = true ;
1808+ gsl::index nIndex = -1 ;
17621809
17631810 auto & pGameContext = ra::services::ServiceLocator::GetMutable<ra::data::context::GameContext>();
17641811 ra::data::models::AssetModelBase* pNewAsset = nullptr ;
@@ -1795,6 +1842,7 @@ void AssetListViewModel::CreateNew()
17951842 }
17961843
17971844 Expects (pNewAsset != nullptr );
1845+
17981846 pNewAsset->SetSubsetID (GetSubsetFilter ());
17991847
18001848 if (bUpdateAsset)
@@ -1808,23 +1856,28 @@ void AssetListViewModel::CreateNew()
18081856
18091857 EnsureAppearsInFilteredList (*pNewAsset);
18101858
1811- const auto nId = ra::to_signed (pNewAsset->GetID ());
1812-
1813- // select the new viewmodel, and deselect everything else
1814- gsl::index nIndex = -1 ;
1815- for (gsl::index i = 0 ; i < ra::to_signed (m_vFilteredAssets.Count ()); ++i)
18161859 {
1817- auto * pItem = m_vFilteredAssets.GetItemAt (i);
1818- if (pItem != nullptr )
1860+ std::lock_guard<std::mutex> lock (m_mtxFilteredItems);
1861+
1862+ FilteredAssets ().BeginUpdate ();
1863+
1864+ const auto nId = ra::to_signed (pNewAsset->GetID ());
1865+
1866+ // select the new viewmodel, and deselect everything else
1867+ for (gsl::index i = 0 ; i < ra::to_signed (m_vFilteredAssets.Count ()); ++i)
18191868 {
1820- if (pItem->GetId () == nId && pItem->GetType () == nType)
1821- {
1822- pItem->SetSelected (true );
1823- nIndex = i;
1824- }
1825- else
1869+ auto * pItem = m_vFilteredAssets.GetItemAt (i);
1870+ if (pItem != nullptr )
18261871 {
1827- pItem->SetSelected (false );
1872+ if (pItem->GetId () == nId && pItem->GetType () == nType)
1873+ {
1874+ pItem->SetSelected (true );
1875+ nIndex = i;
1876+ }
1877+ else
1878+ {
1879+ pItem->SetSelected (false );
1880+ }
18281881 }
18291882 }
18301883 }
0 commit comments