// Returns the tag at the specified tag path public ImageTag GetTag(string tagPath) { // Check if tag is present in tag table // TODO: Optimisation? Use tag table to search for tag along path (from specified tag -> root), then continue traversing down if (ContainsTag(tagPath)) { return(TagTable[tagPath]); } // Start at root tag ImageTag tag = RootTag; // Attempt to navigate to specified tag String[] tagNames = tagPath.Split(':'); foreach (String tagName in tagNames) { ImageTag child = tag.Children.Find(t => t.Name == tagName); if (child == null) { string errorMessage = $"Tag matching path [{tag.Path}:{tagName}] not found"; Log.WriteLine(errorMessage, MessageType.Error); errorMessage = $"Failed to locate tag [{tagPath}]"; Log.WriteLine(errorMessage, MessageType.Error); throw new ArgumentException(errorMessage); } tag = child; } Log.WriteLine($"Located tag [{tagPath}]"); return(tag); }
// Remove the specified tag public void RemoveTag(ImageTag tag) { // Root tag can not be removed if (tag.Type == ImageTagTypes.Root) { return; } // Remove tag from parent tag.Parent.Children.Remove(tag); // Check if this makes the parent unused if (tag.Parent.TaggedImages.Count == 0 && tag.Parent.Children.Count == 0) { RemoveTag(tag.Parent); } // Delete tag // TODO: How though? string path = tag.Path; Log.WriteLine($"Deleted tag [{path}]"); // Remove tag entry in tag table TagTable.Remove(path); Log.WriteLine($"Removed database entry for tag [{path}]"); }
public void AddTagInteraction(string imageHash, string interactionTagPath, string affectedTagPath) { // Make sure image and tags are in database AssertContainsImage(imageHash, $"Unable to add tag interaction, image {imageHash} not found in database!"); AssertContainsTag(interactionTagPath, $"Unable to add tag interaction, tag {interactionTagPath} not found in database!"); AssertContainsTag(affectedTagPath, $"Unable to add tag interaction, tag {affectedTagPath} not found in database!"); // Retrieve image and tag from database Image image = ImageTable[imageHash]; ImageTag interactionTag = TagTable[interactionTagPath]; ImageTag affectedTag = TagTable[affectedTagPath]; // TODO: Rework interaction tags then modify + reenable this part // Make sure interaction tag is of correct type //if (interactionTag.Type != ImageTagTypes.Interaction) //{ //Log.WriteLine($"Unable to add non-interaction tag {interactionTagPath} to {affectedTagPath}", MessageType.Warning); //return; //} // Create tag interaction if does not exist if (!image.TagInteractions.ContainsKey(interactionTagPath)) { image.TagInteractions.Add(interactionTagPath, new ImageTagInteractions(interactionTag)); } // Add tag interaction ImageTagInteractions interactions = image.TagInteractions[interactionTagPath]; interactions.AffectedTags.Add(affectedTag); Log.WriteLine($"Added interaction {interactionTagPath} to {affectedTagPath}"); }
private void DisplayTagTree(ImageTag tag, int level) { // TODO: Can likely be optimised if (tag.Type != ImageTagTypes.Root && CurrentTags.Contains(tag)) { DisplayTag(tag, level); } foreach (ImageTag child in tag.Children) { DisplayTagTree(child, level + 1); } }
private void RedrawTags() { // Clear tag list and tag input box TagList.Items.Clear(); NewTagName.Text = string.Empty; AutoCompleteText = string.Empty; // Fetch tag list CurrentTags = DB.GetTags(CurrentHash); ImageTag RootTag = DB.RootTag; // Display tags DisplayTagTree(RootTag, 0); }
// Add a tag at the specified tag path public ImageTag AddTagAtPath(string path, ImageTagTypes type = ImageTagTypes.Regular) { // If tag already exists, only update type if (ContainsTag(path)) { ChangeTagType(path, type); return(TagTable[path]); } // Start at root tag ImageTag tag = RootTag; // Navigate to parent tag String[] tagNames = path.Split(':'); foreach (String tagName in tagNames.Take(tagNames.Length - 1)) { ImageTag child = tag.Children.Find(t => t.Name == tagName); if (child == null) { // Tag along path not found, display warning message string errorMessage = $"Tag matching path [" + ((tag.Type == ImageTagTypes.Root) ? "" : $"{tag.Path}:") + $"{tagName}] not found"; Log.WriteLine(errorMessage, MessageType.Warning); // Create the missing tag child = new ImageTag(tagName, tag); Log.WriteLine($"Created tag [{child.Path}]"); // Add the tag to the tag table TagTable.Add(child.Path, child); Log.WriteLine($"Created tag table entry for tag [{child.Path}]"); } tag = child; } // Create leaf tag under parent tag ImageTag leaf = new ImageTag(tagNames.Last(), tag, type); Log.WriteLine($"Created leaf tag [{leaf.Path}] with parent [{leaf.Parent.Path}]"); // Add new tag to tag table TagTable.Add(path, leaf); Log.WriteLine($"Created tag table entry for tag [{leaf.Path}]"); // Return newly created tag return(leaf); }
public void InitialiseTag(string name, ImageTag parent, ImageTagTypes type = ImageTagTypes.Regular) { this.Name = name; this.Type = type; this.Parent = parent; if (Parent != null) { Parent.Children.Add(this); } // Set tag path if (parent == null || parent.Type == ImageTagTypes.Root) { this.Path = Name; } else { this.Path = $"{parent.Path}:{Name}"; } }
// Remove the tag at the specified tag path public void RemoveTagAtPath(string path) { // Get parent tag and leaf tag name ImageTag parent = RootTag; string name = path; if (path.Contains(':')) { int lastColon = path.LastIndexOf(':'); name = path.Substring(lastColon + 1); String parentPath = path.Substring(0, lastColon); parent = GetTag(parentPath); } // Get leaf tag ImageTag tag = parent.Children.Find(t => t.Name == name); // Delete tag RemoveTag(tag); }
public void UnassignTag(string imageHash, string tagPath) { // Make sure image and tag are in database AssertContainsImage(imageHash, $"Image [{imageHash}] not found in database, can not unassign tag [{tagPath}]!"); AssertContainsTag(tagPath, $"Tag [{tagPath}] not found in database, can not unassign from image [{imageHash}]!"); // Retrieve image and tag from database Image image = ImageTable[imageHash]; ImageTag tag = TagTable[tagPath]; // Remove links between image and tag image.Tags.Remove(tag); tag.TaggedImages.Remove(image); Log.WriteLine($"Tag [{tagPath}] removed from image [{imageHash}]"); // Unassign tag's ancestors, if no longer needed if (tag.Parent != null && tag.Parent.Type != ImageTagTypes.Root && !tag.Parent.Children.Any(c => image.Tags.Contains(c)) && image.Tags.Contains(tag.Parent)) { UnassignTag(imageHash, tag.Parent.Path); } // Also unassign all descendant tags for (int i = 0; i < tag.Children.Count; i++) { ImageTag child = tag.Children[i]; if (image.Tags.Contains(child)) { UnassignTag(imageHash, child.Path); } } // Delete tag if no longer used if (tag.TaggedImages.Count == 0 && tag.Children.Count == 0) { Log.WriteLine($"Tag [{tagPath}] no longer used, deleting"); RemoveTag(tag); } }
public void LoadTags() { // Check if tag file exists string tagFile = Path.Combine(DataDir, "tags.txt"); if (!File.Exists(tagFile)) { return; } // Read tag data from file using (StreamReader sr = new StreamReader(File.OpenRead(tagFile))) { string line = sr.ReadLine(); while (!string.IsNullOrWhiteSpace(line)) { string[] split = line.Split(' '); ImageTagTypes type = (ImageTagTypes)int.Parse(split[0]); ImageTag tag = AddTagAtPath(split[1], type); line = sr.ReadLine(); } } }
// Create a child tag underneath the specified parent tag public ImageTag(string name, ImageTag parent, ImageTagTypes type = ImageTagTypes.Regular) { InitialiseTag(name, parent, type); }
public ImageTagInteractions(ImageTag interactionTag) { InteractionTag = interactionTag; }
private void DisplayTag(ImageTag tag, int level) { string tagName = tag.Name; // Create tag container DockPanel dockPanel = new DockPanel(); dockPanel.Tag = tag.Path; Color bg = Colors.Transparent; if (tag.Type != ImageTagTypes.Regular) { bg = TagTypeColour(tag.Type); } else if (level % 2 == 0) { bg = Color.FromArgb(15, 255, 255, 255); } else { bg = Color.FromArgb(10, 0, 0, 0); } dockPanel.Background = new SolidColorBrush(bg); dockPanel.Margin = new Thickness(16 * level - 16, 0, 0, 0); // Create delete button Button delete = new Button { Content = "×", FontSize = 14, Width = 32, Margin = new Thickness(4, 0, 0, 0), HorizontalAlignment = HorizontalAlignment.Right, Foreground = Brushes.WhiteSmoke, Background = Brushes.Transparent, BorderBrush = new SolidColorBrush(Color.FromArgb(60, 255, 255, 255)), }; delete.Click += DeleteTag_Click; DockPanel.SetDock(delete, Dock.Right); dockPanel.Children.Add(delete); // Create label containing the tag name Label nameLabel = new Label { // TODO: There is probably a better workaround than this Content = new TextBlock() { Text = tagName }, Padding = new Thickness(4, 0, 4, 0), BorderBrush = new SolidColorBrush(Color.FromArgb(60, 255, 255, 255)), Tag = tag.Path, }; nameLabel.PreviewMouseDown += Tag_PreviewMouseDown; nameLabel.PreviewMouseUp += Tag_PreviewMouseUp; dockPanel.Children.Add(nameLabel); // Create labels containing added interaction tags IEnumerable <ImageTag> interactionList = DB.GetTagInteractions(CurrentHash, tag.Path); if (interactionList != null) { foreach (ImageTag interaction in interactionList) { Label interactionLabel = new Label { // TODO: There is probably a better workaround than this Content = new TextBlock() { Text = interaction.Name }, Padding = new Thickness(2, 0, 2, 0), Margin = new Thickness(4, 0, 0, 0), BorderBrush = new SolidColorBrush(Color.FromArgb(60, 255, 255, 255)), Tag = interaction.Path }; dockPanel.Children.Add(interactionLabel); } } // Create empty slot for an interaction tag Label emptyLabel = new Label { Width = 32, Padding = new Thickness(2, 0, 2, 0), Margin = new Thickness(4, 0, 0, 0), BorderBrush = new SolidColorBrush(Color.FromArgb(30, 255, 255, 255)), Tag = tag.Path }; emptyLabel.PreviewMouseDown += Tag_PreviewMouseDown; emptyLabel.PreviewMouseUp += Tag_PreviewMouseUp; dockPanel.Children.Add(emptyLabel); // Add tag to listbox TagList.Items.Add(dockPanel); }