public Term (Term parent, Literal after) { this.parent = parent; if (parent != null) { if (after == null) parent.Add (this); else parent.SubTerms.Insert (parent.SubTerms.IndexOf (after) + 1, this); } }
protected Term(Term parent, Literal after) { this.parent = parent; SubTerms = new List<Term> (); if (parent != null) if (after == null) { parent.Add (this); } else { parent.SubTerms.Insert (parent.SubTerms.IndexOf (after) + 1, this); } }
public void Add(Term term) { SubTerms.Add (term); }
public static Term TermFromOperator(string op, Term parent, Literal after) { //Console.WriteLine ("finding type for operator {0}", op); //op = op.Trim (); op = op.ToLower (); if (AndTerm.Operators.Contains (op)) return new AndTerm (parent, after); if (OrTerm.Operators.Contains (op)) return new OrTerm (parent, after); Log.DebugFormat ("Do not have Term for operator {0}", op); return null; }
private void Update() { // Clear the last root term root_term = null; if (ParensValid () && ConstructQuery (null, 0, entry.Text)) { if (RootTerm != null) { //Log.DebugFormat("rootTerm = {0}", RootTerm); if (!(RootTerm is AndTerm)) { // A little hacky, here to make sure the root term is a AndTerm which will // ensure we handle the Hidden tag properly AndTerm root_parent = new AndTerm(null, null); RootTerm.Parent = root_parent; root_term = root_parent; } //Log.DebugFormat("rootTerm = {0}", RootTerm); if (!(RootTerm is AndTerm)) { // A little hacky, here to make sure the root term is a AndTerm which will // ensure we handle the Hidden tag properly AndTerm root_parent = new AndTerm(null, null); RootTerm.Parent = root_parent; root_term = root_parent; } //Log.DebugFormat ("condition = {0}", RootTerm.SqlCondition ()); query.TagTerm = new ConditionWrapper (RootTerm.SqlCondition ()); } else { query.TagTerm = null; //Log.Debug ("root term is null"); } } }
public AbstractLiteral(Term parent, Literal after) : base (parent, after) {}
void HandleTagsAdded(Tag[] tags, Term parent, Literal after) { InsertTerm (tags, parent, after); }
void HandleAttachTag(Tag tag, Term parent, Literal after) { InsertTerm (new Tag [] {tag}, parent, after); }
private static bool AppendTerm (ArrayList parts, Term term, Tag single_tag) { bool tag_matches = false; if (term != null) { Literal literal = term as Literal; if (literal != null) { if (literal.Tag == single_tag) tag_matches = true; if (literal.IsNegated) parts.Add (String.Format (Catalog.GetString ("Not {0}"), literal.Tag.Name)); else parts.Add (literal.Tag.Name); } else { foreach (Term subterm in term.SubTerms) { tag_matches |= AppendTerm (parts, subterm, single_tag); } } } return tag_matches; }
public Literal(Term parent, Tag tag, Literal after) : base(parent, after) { Tag = tag; }
public OrTerm(Term parent, Literal after) : base(parent, after) { }
public ArrayList InsertTerm(Tag [] tags, Term parent, Literal after) { int position; if (after != null) { position = WidgetPosition(after.Widget) + 1; } else { position = Children.Length - 1; } ArrayList added = new ArrayList(); foreach (Tag tag in tags) { //Console.WriteLine ("Adding tag {0}", tag.Name); // Don't put a tag into a Term twice if (parent != Root && (parent.FindByTag(tag, true)).Count > 0) { continue; } if (parent.Count > 0) { Widget sep = parent.SeparatorWidget(); InsertWidget(position, sep); position++; } // Encapsulate new OR terms within a new AND term of which they are the // only member, so later other terms can be AND'd with them // // TODO should really see what type of term the parent is, and // encapsulate this term in a term of the opposite type. This will // allow the query system to be expanded to work for multiple levels much easier. if (parent == rootTerm) { parent = new AndTerm(rootTerm, after); after = null; } Literal term = new Literal(parent, tag, after); term.TermAdded += HandleTermAdded; term.LiteralsMoved += HandleLiteralsMoved; term.AttachTag += HandleAttachTag; term.NegatedToggled += HandleNegated; term.Removing += HandleRemoving; term.Removed += HandleRemoved; term.RequireTag += Require; term.UnRequireTag += UnRequire; added.Add(term); // Insert this widget into the appropriate place in the hbox InsertWidget(position, term.Widget); } UpdateQuery(); return(added); }
private void HandleAttachTag(Tag tag, Term parent, Literal after) { InsertTerm(new Tag [] { tag }, parent, after); }
private void HandleTermAdded(Term parent, Literal after) { InsertTerm(parent, after); }
public TextLiteral (Term parent, string text) : base (parent, null) { this.text = text; }
public void CopyAndInvertSubTermsFrom(Term term, bool recurse) { is_negated = true; var termsToMove = new List<Term> (term.SubTerms); foreach (Term subterm in termsToMove) { if (recurse) subterm.Invert (true).Parent = this; else subterm.Parent = this; } }
public void Remove(Term term) { SubTerms.Remove (term); // Remove ourselves if we're now empty if (SubTerms.Count == 0 && Parent != null) Parent.Remove (this); }
private void HandleTermAdded (Term parent, Literal after) { InsertTerm (parent, after); }
public List<Literal> InsertTerm(Tag [] tags, Term parent, Literal after) { int position; if (after != null) position = WidgetPosition (after.Widget) + 1; else position = Children.Length - 1; var added = new List<Literal>(); foreach (Tag tag in tags) { //Console.WriteLine ("Adding tag {0}", tag.Name); // Don't put a tag into a Term twice if (parent != Root && (parent.FindByTag (tag, true)).Count > 0) continue; if (parent.Count > 0) { Widget sep = parent.SeparatorWidget (); InsertWidget (position, sep); position++; } // Encapsulate new OR terms within a new AND term of which they are the // only member, so later other terms can be AND'd with them // // TODO should really see what type of term the parent is, and // encapsulate this term in a term of the opposite type. This will // allow the query system to be expanded to work for multiple levels much easier. if (parent == rootTerm) { parent = new AndTerm (rootTerm, after); after = null; } Literal term = new Literal (parent, tag, after); term.TagsAdded += HandleTagsAdded; term.LiteralsMoved += HandleLiteralsMoved; term.AttachTag += HandleAttachTag; term.NegatedToggled += HandleNegated; term.Removing += HandleRemoving; term.Removed += HandleRemoved; term.RequireTag += Require; term.UnRequireTag += UnRequire; added.Add (term); // Insert this widget into the appropriate place in the hbox InsertWidget (position, term.Widget); } UpdateQuery (); return added; }
private void InsertTerm (Term parent, Literal after) { if (Literal.FocusedLiterals.Count != 0) { HandleLiteralsMoved (Literal.FocusedLiterals, parent, after); // Prevent them from being removed again Literal.FocusedLiterals = null; } else InsertTerm (tag_selection_widget.TagHighlight, parent, after); }
void HandleLiteralsMoved(List<Literal> literals, Term parent, Literal after) { preventUpdate = true; foreach (Literal term in literals) { Tag tag = term.Tag; // Don't listen for it to be removed since we are // moving it. We will update when we're done. term.Removed -= HandleRemoved; term.RemoveSelf (); // Add it to where it was dropped List<Literal> groups = InsertTerm (new [] {tag}, parent, after); if (term.IsNegated) foreach (Literal group in groups) group.IsNegated = true; } preventUpdate = false; UpdateQuery (); }
// Breaking the query the user typed into something useful involves running // it through the above regular expression recursively until it is broken down // into literals and operators that we can use to generate SQL queries. private bool ConstructQuery(Term parent, int depth, string txt) { return ConstructQuery(parent, depth, txt, false); }
void Init() { sepBox = null; preview = false; rootAdd = new Gtk.EventBox (); rootAdd.VisibleWindow = false; rootAdd.CanFocus = true; rootAdd.DragMotion += HandleDragMotion; rootAdd.DragDataReceived += HandleDragDataReceived; rootAdd.DragLeave += HandleDragLeave; help = new Gtk.Label ("<i>" + Catalog.GetString ("Drag tags here to search for them") + "</i>"); help.UseMarkup = true; help.Visible = true; rootBox = new HBox(); rootBox.Add (help); rootBox.Show (); rootAdd.Child = rootBox; rootAdd.Show (); Gtk.Drag.DestSet (rootAdd, DestDefaults.All, tag_dest_target_table, DragAction.Copy | DragAction.Move ); PackEnd (rootAdd, true, true, 0); rootTerm = new OrTerm (null, null); }
private bool ConstructQuery(Term parent, int depth, string txt, bool negated) { if (string.IsNullOrEmpty(txt)) return true; string indent = String.Format ("{0," + depth*2 + "}", " "); //Log.DebugFormat (indent + "Have text: {0}", txt); // Match the query the user typed against our regular expression Match match = term_regex.Match (txt); if (!match.Success) { //Log.Debug (indent + "Failed to match."); return false; } bool op_valid = true; string op = String.Empty; // For the moment at least we don't support operator precedence, so we require // that only a single operator is used for any given term unless it is made unambiguous // by using parenthesis. foreach (Capture capture in match.Groups ["Ops"].Captures) { if (op == String.Empty) op = capture.Value; else if (op != capture.Value) { op_valid = false; break; } } if (!op_valid) { Log.Information (indent + "Ambiguous operator sequence. Use parenthesis to explicitly define evaluation order."); return false; } if (match.Groups ["Terms"].Captures.Count == 1 && match.Groups["NotTerm"].Captures.Count != 1) { //Log.DebugFormat (indent + "Unbreakable term: {0}", match.Groups ["Terms"].Captures [0]); string literal; bool is_negated = false; Tag tag = null; if (match.Groups ["NotTag"].Captures.Count == 1) { literal = match.Groups ["NotTag"].Captures [0].Value; is_negated = true; } else { literal = match.Groups ["Terms"].Captures [0].Value; } is_negated = is_negated || negated; tag = App.Instance.Database.Tags.GetTagByName (literal); // New OR term so we can match against both tag and text search parent = new OrTerm(parent, null); // If the literal is the name of a tag, include it in the OR //AbstractLiteral term = null; if (tag != null) { new Literal (parent, tag, null); } // Always include the literal text in the search (path, comment, etc) new TextLiteral (parent, literal); // If the term was negated, negate the OR parent term if (is_negated) { parent = parent.Invert(true); } if (RootTerm == null) root_term = parent; return true; } else { Term us = null; if (op != null && op != String.Empty) { us = Term.TermFromOperator (op, parent, null); if (RootTerm == null) root_term = us; } foreach (Capture capture in match.Groups ["Term"].Captures) { string subterm = capture.Value.Trim (); if (subterm == null || subterm.Length == 0) continue; // Strip leading/trailing parens if (subterm [0] == '(' && subterm [subterm.Length - 1] == ')') { subterm = subterm.Remove (subterm.Length - 1, 1); subterm = subterm.Remove (0, 1); } //Log.DebugFormat (indent + "Breaking subterm apart: {0}", subterm); if (!ConstructQuery (us, depth + 1, subterm, negated)) return false; } foreach (Capture capture in match.Groups ["NotTerm"].Captures) { string subterm = capture.Value.Trim (); if (subterm == null || subterm.Length == 0) continue; // Strip leading/trailing parens if (subterm [0] == '(' && subterm [subterm.Length - 1] == ')') { subterm = subterm.Remove (subterm.Length - 1, 1); subterm = subterm.Remove (0, 1); } //Log.DebugFormat (indent + "Breaking not subterm apart: {0}", subterm); if (!ConstructQuery (us, depth + 1, subterm, true)) return false; } if (negated && us != null) { if (us == RootTerm) root_term = us.Invert(false); else us.Invert(false); } return true; } }