Skip to content

Commit 4831962

Browse files
author
David Khristepher Santos
committed
Add AND and OR for Tag filter
1 parent 283ea7b commit 4831962

9 files changed

Lines changed: 143 additions & 62 deletions

File tree

Diffusion.Common/Query/QueryOptions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
namespace Diffusion.Common.Query;
55

6+
public enum TagsMode
7+
{
8+
AND,
9+
OR
10+
}
11+
612
public class QueryOptions
713
{
814
public QueryOptions()
@@ -35,4 +41,5 @@ public QueryOptions()
3541
[JsonIgnore]
3642
public bool IsEmpty => Filter.IsEmpty && string.IsNullOrEmpty(Query);
3743

44+
public TagsMode TagsMode { get; set; }
3845
}

Diffusion.Database/QueryCombiner.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,26 @@ private static void ApplyFilters(ref string query, ref IEnumerable<object> bindi
183183

184184
if (options.TagIds is { Count: > 0 })
185185
{
186-
var placeholders = string.Join(",", options.TagIds.Select(a => "?"));
187-
filters.Add($"SELECT DISTINCT m1.Id FROM Image m1 INNER JOIN ImageTag it ON it.ImageId = m1.Id INNER JOIN Tag t ON t.Id = it.TagId WHERE t.Id IN ({placeholders})");
188-
bindings = bindings.Concat(options.TagIds.Cast<object>());
186+
switch (options.TagsMode)
187+
{
188+
case TagsMode.OR:
189+
{
190+
// OR
191+
var placeholders = string.Join(",", options.TagIds.Select(a => "?"));
192+
filters.Add($"SELECT DISTINCT m1.Id FROM Image m1 INNER JOIN ImageTag it ON it.ImageId = m1.Id INNER JOIN Tag t ON t.Id = it.TagId WHERE t.Id IN ({placeholders})");
193+
bindings = bindings.Concat(options.TagIds.Cast<object>());
194+
break;
195+
}
196+
case TagsMode.AND:
197+
{
198+
foreach (var tagId in options.TagIds)
199+
{
200+
filters.Add($"SELECT DISTINCT m1.Id FROM Image m1 INNER JOIN ImageTag it ON it.ImageId = m1.Id WHERE it.TagId = ?");
201+
bindings = bindings.Append(tagId);
202+
}
203+
break;
204+
}
205+
}
189206
}
190207

191208
if (options.Models is { Count: > 0 })

Diffusion.Toolkit/Configuration/Settings.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Windows;
44
using System.Windows.Interop;
5+
using Diffusion.Common.Query;
56
using Diffusion.Toolkit.Controls;
67

78
namespace Diffusion.Toolkit.Configuration;
@@ -32,7 +33,7 @@ public Settings()
3233
SortAlbumsBy = "Name";
3334
SortBy = "Date Created";
3435
SortQueriesBy = "Name";
35-
36+
3637
SortDirection = "Z-A";
3738
MetadataSection = new MetadataSectionSettings();
3839
MetadataSection.Attach(this);
@@ -465,6 +466,12 @@ public bool LoopVideo
465466
get;
466467
set => UpdateValue(ref field, value);
467468
}
469+
470+
public TagsMode TagsMode
471+
{
472+
get;
473+
set => UpdateValue(ref field, value);
474+
}
468475
}
469476

470477
public class PreviewWindowState
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows.Data;
4+
using Diffusion.Common.Query;
5+
6+
namespace Diffusion.Toolkit.Converters;
7+
8+
public class TagsModeConverter : IValueConverter
9+
{
10+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11+
{
12+
return ((TagsMode)value).ToString() == (string)parameter;
13+
}
14+
15+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
16+
{
17+
return (string)parameter == "AND" ? TagsMode.AND : TagsMode.OR;
18+
}
19+
}

Diffusion.Toolkit/Models/SearchModel.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Windows;
66
using System.Windows.Input;
77
using Diffusion.Common;
8+
using Diffusion.Common.Query;
89
using Diffusion.Database.Models;
910
using Diffusion.Toolkit.Common;
1011
using Diffusion.Toolkit.Controls;
@@ -438,4 +439,10 @@ public bool HasNoImagePaths
438439
get;
439440
set => SetField(ref field, value);
440441
}
442+
443+
public TagsMode TagsMode
444+
{
445+
get;
446+
set => SetField(ref field, value);
447+
}
441448
}

Diffusion.Toolkit/Pages/Search.xaml

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
xmlns:behaviors="clr-namespace:Diffusion.Toolkit.Behaviors"
1616
xmlns:system="clr-namespace:System;assembly=System.Runtime"
1717
xmlns:mdXaml="clr-namespace:MdXaml;assembly=MdXaml"
18+
xmlns:query="clr-namespace:Diffusion.Common.Query;assembly=Diffusion.Common"
1819
lex:LocalizeDictionary.Provider="{StaticResource LocalizationProvider}"
1920
lex:LocalizeDictionary.Separation="."
2021
lex:LocalizeDictionary.DefaultProvider="{StaticResource LocalizationProvider}"
@@ -37,6 +38,7 @@
3738
<converters:InverseBoolToVisibilityConverter x:Key="invBoolToVisCol"></converters:InverseBoolToVisibilityConverter>
3839
<converters:FolderModeVisibilityConverter x:Key="addrVis"></converters:FolderModeVisibilityConverter>
3940
<converters:FilterActiveConverter x:Key="FilterActiveConverter"></converters:FilterActiveConverter>
41+
<converters:TagsModeConverter x:Key="TagsModeConverter"></converters:TagsModeConverter>
4042
<converters:SizeConverter x:Key="SizeConverter"></converters:SizeConverter>
4143
<converters:ZeroConverter x:Key="ZeroConverter"></converters:ZeroConverter>
4244
<converters:NumberFormatConverter x:Key="NumberFormatConverter"></converters:NumberFormatConverter>
@@ -676,61 +678,71 @@
676678
</Button>
677679
</Grid>
678680
</controls:AccordionControl.ButtonAreaContent>
679-
<ItemsControl ItemsSource="{Binding Path=MainModel.Tags}" PreviewMouseWheel="UIElement_OnPreviewMouseWheel">
680-
<ItemsControl.ItemTemplate>
681-
<DataTemplate>
682-
<Grid Background="Transparent" HorizontalAlignment="Stretch" Margin="2,0,2,0">
683-
<Grid.ColumnDefinitions>
684-
<ColumnDefinition Width="20"/>
685-
<ColumnDefinition/>
686-
</Grid.ColumnDefinitions>
687-
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding IsTicked}" Click="TagCheck_OnClick"></CheckBox>
688-
<Button Grid.Column="1" Style="{StaticResource SmallButton}"
681+
<Grid Background="Transparent">
682+
<Grid.RowDefinitions>
683+
<RowDefinition Height="16"/>
684+
<RowDefinition Height="*"/>
685+
</Grid.RowDefinitions>
686+
<StackPanel Orientation="Horizontal">
687+
<RadioButton IsChecked="{Binding TagsMode, Converter={StaticResource TagsModeConverter}, ConverterParameter=AND}" GroupName="TagsMode" Margin="0,0,10,0" Content="AND"></RadioButton>
688+
<RadioButton IsChecked="{Binding TagsMode, Converter={StaticResource TagsModeConverter}, ConverterParameter=OR}" GroupName="TagsMode" Content="OR"></RadioButton>
689+
</StackPanel>
690+
<ItemsControl Grid.Row="1" ItemsSource="{Binding Path=MainModel.Tags}" PreviewMouseWheel="UIElement_OnPreviewMouseWheel">
691+
<ItemsControl.ItemTemplate>
692+
<DataTemplate>
693+
<Grid Background="Transparent" HorizontalAlignment="Stretch" Margin="2,0,2,0">
694+
<Grid.ColumnDefinitions>
695+
<ColumnDefinition Width="20"/>
696+
<ColumnDefinition/>
697+
</Grid.ColumnDefinitions>
698+
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding IsTicked}" Click="TagCheck_OnClick"></CheckBox>
699+
<Button Grid.Column="1" Style="{StaticResource SmallButton}"
689700
Tag="{Binding .}"
690701
AllowDrop="True"
691702
ToolTip="{Binding Name}"
692703
Click="Tag_OnClick"
693704
RenderTransformOrigin="0.179,0.476">
694-
<Button.ContextMenu>
695-
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
696-
<MenuItem Header="{lex:Loc Search.Navigation.Tags.ContextMenu.Rename}" Command="{Binding Source={StaticResource Proxy}, Path=Data.RenameTagCommand}" CommandParameter="{Binding .}"></MenuItem>
697-
<MenuItem Header="{lex:Loc Search.Navigation.Tags.ContextMenu.Remove}" Command="{Binding Source={StaticResource Proxy}, Path=Data.RemoveTagCommand}" CommandParameter="{Binding .}"></MenuItem>
698-
</ContextMenu>
699-
</Button.ContextMenu>
700-
<Button.Template>
701-
<ControlTemplate TargetType="{x:Type Button}">
702-
<Grid>
703-
<Grid.Style>
704-
<Style TargetType="Grid">
705-
<Setter Property="Background" Value="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"/>
706-
<Style.Triggers>
707-
<DataTrigger Binding="{Binding IsTicked}" Value="true">
708-
<Setter Property="Background" Value="{StaticResource HighlightBrush}"></Setter>
709-
</DataTrigger>
710-
</Style.Triggers>
711-
</Style>
712-
</Grid.Style>
713-
<Grid.ColumnDefinitions>
714-
<ColumnDefinition Width="0"></ColumnDefinition>
715-
<ColumnDefinition Width="*"/>
716-
<ColumnDefinition Width="70"/>
717-
</Grid.ColumnDefinitions>
718-
<fa:FontAwesome Icon="Filter" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="{StaticResource DisabledForegroundBrush}"></fa:FontAwesome>
719-
<Label FontFamily="Calibri" FontWeight="Light" FontSize="16" Padding="4" Grid.Column="1" Content="{Binding Name, Converter={StaticResource UnderlineConverter}}"></Label>
720-
<Label FontFamily="Calibri" FontWeight="Light" FontSize="16" Padding="4" Grid.Column="2" Content="{Binding TagCount, Converter={StaticResource NumberFormatConverter}}" HorizontalAlignment="Right"></Label>
721-
</Grid>
722-
</ControlTemplate>
723-
</Button.Template>
724-
</Button>
725-
</Grid>
726-
</DataTemplate>
727-
</ItemsControl.ItemTemplate>
728-
<ItemsControl.ItemsPanel>
729-
<ItemsPanelTemplate>
730-
<StackPanel Orientation="Vertical"/>
731-
</ItemsPanelTemplate>
732-
</ItemsControl.ItemsPanel>
733-
</ItemsControl>
705+
<Button.ContextMenu>
706+
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
707+
<MenuItem Header="{lex:Loc Search.Navigation.Tags.ContextMenu.Rename}" Command="{Binding Source={StaticResource Proxy}, Path=Data.RenameTagCommand}" CommandParameter="{Binding .}"></MenuItem>
708+
<MenuItem Header="{lex:Loc Search.Navigation.Tags.ContextMenu.Remove}" Command="{Binding Source={StaticResource Proxy}, Path=Data.RemoveTagCommand}" CommandParameter="{Binding .}"></MenuItem>
709+
</ContextMenu>
710+
</Button.ContextMenu>
711+
<Button.Template>
712+
<ControlTemplate TargetType="{x:Type Button}">
713+
<Grid>
714+
<Grid.Style>
715+
<Style TargetType="Grid">
716+
<Setter Property="Background" Value="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"/>
717+
<Style.Triggers>
718+
<DataTrigger Binding="{Binding IsTicked}" Value="true">
719+
<Setter Property="Background" Value="{StaticResource HighlightBrush}"></Setter>
720+
</DataTrigger>
721+
</Style.Triggers>
722+
</Style>
723+
</Grid.Style>
724+
<Grid.ColumnDefinitions>
725+
<ColumnDefinition Width="0"></ColumnDefinition>
726+
<ColumnDefinition Width="*"/>
727+
<ColumnDefinition Width="70"/>
728+
</Grid.ColumnDefinitions>
729+
<fa:FontAwesome Icon="Filter" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="{StaticResource DisabledForegroundBrush}"></fa:FontAwesome>
730+
<Label FontFamily="Calibri" FontWeight="Light" FontSize="16" Padding="4" Grid.Column="1" Content="{Binding Name, Converter={StaticResource UnderlineConverter}}"></Label>
731+
<Label FontFamily="Calibri" FontWeight="Light" FontSize="16" Padding="4" Grid.Column="2" Content="{Binding TagCount, Converter={StaticResource NumberFormatConverter}}" HorizontalAlignment="Right"></Label>
732+
</Grid>
733+
</ControlTemplate>
734+
</Button.Template>
735+
</Button>
736+
</Grid>
737+
</DataTemplate>
738+
</ItemsControl.ItemTemplate>
739+
<ItemsControl.ItemsPanel>
740+
<ItemsPanelTemplate>
741+
<StackPanel Orientation="Vertical"/>
742+
</ItemsPanelTemplate>
743+
</ItemsControl.ItemsPanel>
744+
</ItemsControl>
745+
</Grid>
734746
</controls:AccordionControl>
735747

736748
<controls:AccordionControl
@@ -924,7 +936,7 @@
924936
</DataTrigger>
925937
</Style.Triggers>
926938
</Style>
927-
939+
928940
</Grid.Style>
929941
<Grid.RowDefinitions>
930942
<RowDefinition Height="*"/>

0 commit comments

Comments
 (0)