public override IEnumerable <IJunkResult> FindJunk(ApplicationUninstallerEntry target)
        {
            var results = new List <IJunkResult>();

            if (_pfFiles == null || target.SortedExecutables == null || target.SortedExecutables.Length == 0)
            {
                return(results);
            }

            var targetExeNames = target.SortedExecutables
                                 .Attempt(Path.GetFileName)
                                 .Where(x => !string.IsNullOrEmpty(x))
                                 .Select(x => x.ToLowerInvariant())
                                 .ToList();

            var pfFileHits = targetExeNames
                             .SelectMany(fileName => _pfFiles[fileName]
                                         .Select(fullPath => new { fileName, fullPath }))
                             .ToList();

            var usedByOthers = AllUninstallers
                               .Where(x => x != target)
                               .SelectMany(x => x.SortedExecutables ?? Enumerable.Empty <string>())
                               .Attempt(Path.GetFileName)
                               .Where(x => !string.IsNullOrEmpty(x))
                               .Select(x => x.ToLowerInvariant());
            var usedByOthersLookup = new HashSet <string>(usedByOthers);

            foreach (var pfHit in pfFileHits)
            {
                var node = new FileSystemJunk(new FileInfo(pfHit.fullPath), target, this);
                node.Confidence.Add(ConfidenceRecords.ExplicitConnection);
                if (usedByOthersLookup.Contains(pfHit.fileName))
                {
                    node.Confidence.Add(ConfidenceRecords.UsedBySimilarNamedApp);
                }
                results.Add(node);
            }

            return(results);
        }
        internal UninstallerListViewUpdater(MainWindow reference)
        {
            _reference = reference;
            _listView  = new TypedObjectListView <ApplicationUninstallerEntry>(reference.uninstallerObjectListView);

            _iconGetter = new UninstallerIconGetter();
            _reference.olvColumnDisplayName.ImageGetter = _iconGetter.ColumnImageGetter;

            // Refresh items marked as invalid after corresponding setting change
            _settings.Subscribe((x, y) =>
            {
                if (CheckIsAppDisposed())
                {
                    return;
                }

                if (!_firstRefresh)
                {
                    _listView.ListView.RefreshObjects(AllUninstallers.Where(u => !u.IsValid).ToList());
                }
            }, x => x.AdvancedTestInvalid, this);

            // Refresh items marked as orphans after corresponding setting change
            _settings.Subscribe((x, y) =>
            {
                if (CheckIsAppDisposed())
                {
                    return;
                }

                if (!_firstRefresh)
                {
                    _listView.ListView.UpdateColumnFiltering();
                }
            }, x => x.AdvancedDisplayOrphans, this);
        }
        internal UninstallerListViewTools(MainWindow reference)
        {
            _reference = reference;
            _listView  = new TypedObjectListView <ApplicationUninstallerEntry>(reference.uninstallerObjectListView);
            SetupListView();

            _reference.filterEditor1.TargetFilterCondition = _filteringFilterCondition;

            // Start the processing thread when user changes the test certificates option
            _settings.Subscribe((x, y) =>
            {
                if (_firstRefresh)
                {
                    return;
                }
                if (y.NewValue)
                {
                    StartProcessingThread(FilteredUninstallers);
                }
                else
                {
                    StopProcessingThread(false);

                    if (CheckIsAppDisposed())
                    {
                        return;
                    }

                    _listView.ListView.SuspendLayout();
                    _listView.ListView.RefreshObjects(
                        AllUninstallers.Where(u => u.IsCertificateValid(true).HasValue).ToList());
                    _listView.ListView.ResumeLayout();
                }
            }, x => x.AdvancedTestCertificates, this);

            // Refresh items marked as invalid after corresponding setting change
            _settings.Subscribe((x, y) =>
            {
                if (CheckIsAppDisposed())
                {
                    return;
                }

                if (!_firstRefresh)
                {
                    _listView.ListView.RefreshObjects(AllUninstallers.Where(u => !u.IsValid).ToList());
                }
            }, x => x.AdvancedTestInvalid, this);

            // Refresh items marked as orphans after corresponding setting change
            _settings.Subscribe((x, y) =>
            {
                if (CheckIsAppDisposed())
                {
                    return;
                }

                if (!_firstRefresh)
                {
                    _listView.ListView.UpdateColumnFiltering();
                }
            }, x => x.AdvancedDisplayOrphans, this);

            AfterFiltering += (x, y) => StartProcessingThread(FilteredUninstallers);

            UninstallerFileLock = new object();

            _reference.FormClosed += (x, y) =>
            {
                // Prevent the thread from accessing disposed resources before getting aborted.
                StopProcessingThread(false);
                ProcessRatingsFinalize();
            };

            _settings.Subscribe((sender, args) => ProcessRatingsInitialize(), x => x.MiscUserRatings, this);
            //ProcessRatingsInitialize(); Is always called once at the start by the above
        }