Skip to content

Commit

Permalink
Merge pull request #4217 from IvenBach/Issue4159
Browse files Browse the repository at this point in the history
Allow filtering of results in CodeInspections window
  • Loading branch information
retailcoder committed Oct 15, 2018
2 parents 91cf0d8 + 8ee0a23 commit e74ba3c
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 154 deletions.
81 changes: 44 additions & 37 deletions Rubberduck.Core/UI/CodeExplorer/CodeExplorerControl.xaml

Large diffs are not rendered by default.

91 changes: 75 additions & 16 deletions Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml
Expand Up @@ -9,7 +9,7 @@
ResxExtension.DefaultResxName="Rubberduck.Resources.RubberduckUI"
Language="{UICulture}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
d:DesignHeight="300" d:DesignWidth="500"
d:DataContext="{d:DesignInstance codeInspections:InspectionResultsViewModel}">
<UserControl.Resources>
<ResourceDictionary>
Expand All @@ -23,9 +23,7 @@
<codeInspections:InspectionImageSourceConverter x:Key="InspectionIconConverter" />
<codeInspections:InspectionTypeConverter x:Key="InspectionTypeConverter" />

<Style x:Key="IconStyle" TargetType="Image">
<Setter Property="Height" Value="16" />
<Setter Property="Width" Value="16" />
<Style x:Key="IconMargin" TargetType="Image">
<Setter Property="Margin" Value="4" />
</Style>

Expand All @@ -41,8 +39,25 @@
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>


<BitmapImage x:Key="CopyResultsImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/document-copy.png" />
<BitmapImage x:Key="SettingsImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/gear.png" />
<BitmapImage x:Key="RefreshImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/arrow-circle-double.png" />
<BitmapImage x:Key="FixImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/tick.png" />
<BitmapImage x:Key="GroupByImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Custom/PNG/GroupBy.png" />
<BitmapImage x:Key="FilterByHintImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/information-white.png" />
<BitmapImage x:Key="FilterBySuggestionImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/information.png" />
<BitmapImage x:Key="FilterByWarningImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/exclamation.png" />
<BitmapImage x:Key="FilterByErrorImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-circle.png" />

<Style TargetType="Image">
<Setter Property="Height" Value="16"/>
<Setter Property="Width" Value="16" />
</Style>


<Style TargetType="MenuItem">
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>

</ResourceDictionary>
</UserControl.Resources>
Expand All @@ -59,7 +74,7 @@
<ToolBar Style="{StaticResource ToolBarWithOverflowOnlyShowingWhenNeededStyle}">

<Button Command="{Binding RefreshCommand}">
<Image Height="16" Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/arrow-circle-double.png" />
<Image Source="{StaticResource RefreshImage}" />
</Button>

<Separator />
Expand All @@ -68,7 +83,7 @@
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=Fix}"
ItemsSource="{Binding QuickFixes}">
<MenuItem.Icon>
<Image Height="16" Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/tick.png" />
<Image Source="{StaticResource FixImage}" />
</MenuItem.Icon>
<MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
Expand All @@ -81,11 +96,11 @@
</Menu>

<Menu>
<MenuItem Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingGrid_GroupingStyle}" VerticalAlignment="Center">
<MenuItem Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingGrid_GroupingStyle}">
<MenuItem.Icon>
<Image Height="16" Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Custom/PNG/GroupBy.png" />
<Image Source="{StaticResource GroupByImage}" />
</MenuItem.Icon>

<MenuItem x:Name="GroupByInspectionType"
Style="{DynamicResource MenuItemStyle}"
VerticalAlignment="Center"
Expand All @@ -109,14 +124,58 @@

<Separator />

<Menu>
<MenuItem x:Name="FilterInspectionByError"
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterByError}"
IsChecked="{Binding FilterInspectionsByError, UpdateSourceTrigger=PropertyChanged}"
IsCheckable="True"
controls:MenuItemGroup.GroupName="InspectionResults_FilterBy">
<MenuItem.Icon>
<Image Source="{StaticResource FilterByErrorImage}" />
</MenuItem.Icon>
</MenuItem>

<MenuItem x:Name="FilterInspectionByWarning"
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterByWarning}"
IsChecked="{Binding FilterInspectionsByWarning, UpdateSourceTrigger=PropertyChanged}"
IsCheckable="True"
controls:MenuItemGroup.GroupName="InspectionResults_FilterBy">
<MenuItem.Icon>
<Image Source="{StaticResource FilterByWarningImage}" />
</MenuItem.Icon>
</MenuItem>

<MenuItem x:Name="FilterInspectionBySuggestion"
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterBySuggestion}"
IsChecked="{Binding FilterInspectionsBySuggestion, UpdateSourceTrigger=PropertyChanged}"
IsCheckable="True"
controls:MenuItemGroup.GroupName="InspectionResults_FilterBy">
<MenuItem.Icon>
<Image Source="{StaticResource FilterBySuggestionImage}" />
</MenuItem.Icon>
</MenuItem>

<MenuItem x:Name="FilterInspectionByHint"
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterByHint}"
IsChecked="{Binding FilterInspectionsByHint, UpdateSourceTrigger=PropertyChanged}"
IsCheckable="True"
controls:MenuItemGroup.GroupName="InspectionResults_FilterBy">
<MenuItem.Icon>
<Image Source="{StaticResource FilterByHintImage}" />
</MenuItem.Icon>
</MenuItem>
</Menu>

<Separator />

<Button Command="{Binding CopyResultsCommand}">
<Image Height="16" Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/document-copy.png" />
<Image Source="{StaticResource CopyResultsImage}" />
<Button.ToolTip>
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.CodeExplorer.CodeExplorerUI, Key=CodeExplorer_CopyToolTip}" />
</Button.ToolTip>
</Button>
<Button ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=Settings}" Command="{Binding OpenInspectionSettings}" BorderThickness="0" Background="Transparent">
<Image Height="16" Source="{StaticResource SettingsImage}" />
<Image Source="{StaticResource SettingsImage}" />
</Button>
</ToolBar>
</ToolBarTray>
Expand All @@ -132,7 +191,7 @@
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=CodeInspectionResults_Type}" SortDirection="{Binding}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="abstract1:IInspectionResult">
<Image Source="{Binding Inspection, Converter={StaticResource InspectionIconConverter}}" Height="16" />
<Image Source="{Binding Inspection, Converter={StaticResource InspectionIconConverter}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Expand All @@ -151,7 +210,7 @@
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=CodeInspectionResults_Type}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="abstract1:IInspectionResult">
<Image Source="{Binding Inspection, Converter={StaticResource InspectionIconConverter}}" Height="16" />
<Image Source="{Binding Inspection, Converter={StaticResource InspectionIconConverter}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Expand All @@ -175,7 +234,7 @@
<ColumnDefinition Width="25" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Style="{StaticResource IconStyle}" VerticalAlignment="Top" Grid.Column="0"
<Image Style="{StaticResource IconMargin}" VerticalAlignment="Top" Grid.Column="0"
Source="{Binding SelectedItem.Inspection.Severity, Converter={StaticResource SeverityIconConverter}}"/>
<TextBlock Grid.Column="1" Margin="4" Text="{Binding SelectedItem.Inspection.Description}" FontWeight="Bold" TextWrapping="WrapWithOverflow"/>
</Grid>
Expand All @@ -199,7 +258,7 @@
<controls:LinkButton Margin="4"
Visibility="{Binding CanExecuteQuickFixInProject, Converter={StaticResource BoolToVisibility}}"
Command="{Binding QuickFixInAllProjectsCommand}"
Content="{Resx ResxName=Rubberduck.Resources.Inspections.InspectionsUI, Key=QuickFix_AllOpenProjects}" />
Content="{Resx ResxName=Rubberduck.Resources.Inspections.InspectionsUI, Key=QuickFix_All}" />
<controls:LinkButton Margin="4"
Visibility="{Binding CanDisableInspection, Converter={StaticResource BoolToVisibility}}"
Command="{Binding DisableInspectionCommand}"
Expand Down
102 changes: 92 additions & 10 deletions Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs
Expand Up @@ -117,13 +117,14 @@ private void _configService_SettingsChanged(object sender, ConfigurationChangedE
_runInspectionsOnReparse = e.RunInspectionsOnReparse;
}

private ObservableCollection<IInspectionResult> _results = new ObservableCollection<IInspectionResult>();
private ObservableCollection<IInspectionResult> _resultsAll = new ObservableCollection<IInspectionResult>();
private ObservableCollection<IInspectionResult> _resultsGroupedAndFiltered = new ObservableCollection<IInspectionResult>();
public ObservableCollection<IInspectionResult> Results
{
get => _results;
get => _resultsGroupedAndFiltered;
private set
{
_results = value;
_resultsGroupedAndFiltered = value;
OnPropertyChanged();
}
}
Expand Down Expand Up @@ -203,6 +204,7 @@ public bool GroupByInspectionType
.ThenBy(t => t.QualifiedSelection.Selection.StartLine)
.ThenBy(t => t.QualifiedSelection.Selection.StartColumn)
.ToList());

}

_groupByInspectionType = value;
Expand Down Expand Up @@ -233,6 +235,85 @@ public bool GroupByLocation
}
}

private readonly List<CodeInspectionSeverity> _filterCriteria = new List<CodeInspectionSeverity>();

public bool FilterInspectionsByHint
{
get => _filterCriteria.Contains(CodeInspectionSeverity.Hint);
set
{
UpdateFilterCriteria(value, CodeInspectionSeverity.Hint);

FilterResults(_filterCriteria);
OnPropertyChanged();
}
}

public bool FilterInspectionsBySuggestion
{
get => _filterCriteria.Contains(CodeInspectionSeverity.Suggestion);
set
{
UpdateFilterCriteria(value, CodeInspectionSeverity.Suggestion);

FilterResults(_filterCriteria);
OnPropertyChanged();
}
}

public bool FilterInspectionsByWarning
{
get => _filterCriteria.Contains(CodeInspectionSeverity.Warning);
set
{
UpdateFilterCriteria(value, CodeInspectionSeverity.Warning);

FilterResults(_filterCriteria);
OnPropertyChanged();
}
}

public bool FilterInspectionsByError
{
get => _filterCriteria.Contains(CodeInspectionSeverity.Error);
set
{
UpdateFilterCriteria(value, CodeInspectionSeverity.Error);

FilterResults(_filterCriteria);
OnPropertyChanged();
}
}

private void UpdateFilterCriteria(bool isCriteria ,CodeInspectionSeverity criteria)
{
if (_filterCriteria.Contains(criteria) == isCriteria) { return; }

if (isCriteria)
{
_filterCriteria.Add(criteria);
}
else
{
_filterCriteria.Remove(criteria);
}
}

public void FilterResults(IEnumerable<CodeInspectionSeverity> inspections)
{
if (_filterCriteria.Any())
{
Results = new ObservableCollection<IInspectionResult>(_resultsAll
.GroupBy(result => result.Inspection.Severity)
.Where(group => _filterCriteria.Contains(group.Key))
.SelectMany(x => x));
}
else
{
Results = _resultsAll;
}
}

public INavigateCommand NavigateCommand { get; }
public CommandBase SetInspectionTypeGroupingCommand { get; }
public CommandBase SetLocationGroupingCommand { get; }
Expand Down Expand Up @@ -339,7 +420,8 @@ private async void RefreshInspections(CancellationToken token)
.ToList();
}

Results = new ObservableCollection<IInspectionResult>(results);
_resultsAll = new ObservableCollection<IInspectionResult>(results);
Results = _resultsAll;

_uiDispatcher.Invoke(() =>
{
Expand Down Expand Up @@ -502,21 +584,21 @@ private void ExecuteQuickFixInAllProjectsCommand(object parameter)
private void ExecuteCopyResultsCommand(object parameter)
{
const string xmlSpreadsheetDataFormat = "XML Spreadsheet";
if (_results == null)
if (_resultsAll == null)
{
return;
}
ColumnInfo[] columnInfos = { new ColumnInfo("Type"), new ColumnInfo("Project"), new ColumnInfo("Component"), new ColumnInfo("Issue"), new ColumnInfo("Line", hAlignment.Right), new ColumnInfo("Column", hAlignment.Right) };

var resultArray = _results.OfType<IExportable>().Select(result => result.ToArray()).ToArray();
var resultArray = _resultsAll.OfType<IExportable>().Select(result => result.ToArray()).ToArray();

var resource = _results.Count == 1
var resource = _resultsAll.Count == 1
? Resources.RubberduckUI.CodeInspections_NumberOfIssuesFound_Singular
: Resources.RubberduckUI.CodeInspections_NumberOfIssuesFound_Plural;

var title = string.Format(resource, DateTime.Now.ToString(CultureInfo.InvariantCulture), _results.Count);
var title = string.Format(resource, DateTime.Now.ToString(CultureInfo.InvariantCulture), _resultsAll.Count);

var textResults = title + Environment.NewLine + string.Join("", _results.OfType<IExportable>().Select(result => result.ToClipboardString() + Environment.NewLine).ToArray());
var textResults = title + Environment.NewLine + string.Join("", _resultsAll.OfType<IExportable>().Select(result => result.ToClipboardString() + Environment.NewLine).ToArray());
var csvResults = ExportFormatter.Csv(resultArray, title,columnInfos);
var htmlResults = ExportFormatter.HtmlClipboardFragment(resultArray, title,columnInfos);
var rtfResults = ExportFormatter.RTF(resultArray, title);
Expand All @@ -535,7 +617,7 @@ private void ExecuteCopyResultsCommand(object parameter)

private bool CanExecuteCopyResultsCommand(object parameter)
{
return !IsBusy && _results != null && _results.Any();
return !IsBusy && _resultsAll != null && _resultsAll.Any();
}

public Visibility EmptyUIRefreshVisibility => _state.Projects.Count > 0 ? Visibility.Hidden : Visibility.Visible;
Expand Down
20 changes: 10 additions & 10 deletions Rubberduck.Core/UI/Settings/GeneralSettings.xaml
Expand Up @@ -118,11 +118,11 @@
</Label>
<Label Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_LanguageLabel}" FontWeight="SemiBold" />
<ComboBox Width="210"
HorizontalAlignment="Left"
Margin="5"
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"
ItemsSource="{Binding Languages, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name" />
HorizontalAlignment="Left"
Margin="5"
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"
ItemsSource="{Binding Languages, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name" />

<CheckBox Margin="5,0,0,5" Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_ShowSplash}"
IsChecked="{Binding ShowSplashAtStartup}" />
Expand All @@ -136,11 +136,11 @@
<Label Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_MinimumLogLevelLabel}" FontWeight="SemiBold" />
<StackPanel Orientation="Horizontal">
<ComboBox Width="210"
HorizontalAlignment="Left"
Margin="5"
SelectedItem="{Binding SelectedLogLevel, Mode=TwoWay}"
ItemsSource="{Binding LogLevels, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name"/>
HorizontalAlignment="Left"
Margin="5"
SelectedItem="{Binding SelectedLogLevel, Mode=TwoWay}"
ItemsSource="{Binding LogLevels, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name"/>
<Button
Content="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GeneralSettings_ShowLogFolder}"
Padding="5"
Expand Down

0 comments on commit e74ba3c

Please sign in to comment.