Index: roundup/cgi/templating.py
===================================================================
--- roundup/cgi/templating.py (Revision 4543)
+++ roundup/cgi/templating.py (Arbeitskopie)
@@ -27,6 +27,8 @@
from roundup import i18n
from roundup.i18n import _
+from KeywordsExpr import render_keywords_expression_editor
+
try:
import cPickle as pickle
except ImportError:
@@ -2848,6 +2850,9 @@
raise AttributeError, name
return self.client.instance.templating_utils[name]
+ def keywords_expressions(self, request):
+ return render_keywords_expression_editor(request)
+
def html_calendar(self, request):
"""Generate a HTML calendar.
Index: roundup/cgi/KeywordsExpr.py
===================================================================
--- roundup/cgi/KeywordsExpr.py (Revision 0)
+++ roundup/cgi/KeywordsExpr.py (Revision 0)
@@ -0,0 +1,273 @@
+# This module is free software, you may redistribute it
+# and/or modify under the same terms as Python.
+
+WINDOW_CONTENT = '''\
+
Keyword Expression Editor:
+
+
+
+'''
+
+def list_nodes(request):
+ prop = request.form.getfirst("property")
+ cls = request.client.db.getclass(prop)
+ items = []
+ for nodeid in cls.getnodeids():
+ l = cls.getnode(nodeid).items()
+ l = dict([x for x in l if len(x) == 2])
+ try:
+ items.append((l['id'], l['name']))
+ except KeyError:
+ pass
+ items.sort(key=lambda x: int(x[0]))
+ return items
+
+def items_to_keywords(items):
+ return ',\n '.join(['["%s", "%s"]' % x for x in items])
+
+
+def render_keywords_expression_editor(request):
+ prop = request.form.getfirst("property")
+
+ window_content = WINDOW_CONTENT % {
+ 'prop' : prop,
+ 'keywords': items_to_keywords(list_nodes(request)),
+ 'original': ''
+ }
+
+ return window_content
+
+# vim: set et sts=4 sw=4 :
Index: roundup/backends/back_anydbm.py
===================================================================
--- roundup/backends/back_anydbm.py (Revision 4543)
+++ roundup/backends/back_anydbm.py (Arbeitskopie)
@@ -49,6 +49,60 @@
def db_nuke(config):
shutil.rmtree(config.DATABASE)
+class Equals:
+ def __init__(self, x):
+ self.x = x
+
+ def evaluate(self, v):
+ return self.x in v
+
+class Not:
+ def __init__(self, x):
+ self.x = x
+
+ def evaluate(self, v):
+ return not self.x.evaluate(v)
+
+class Or:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def evaluate(self, v):
+ return self.x.evaluate(v) or self.y.evaluate(v)
+
+class And:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def evaluate(self, v):
+ return self.x.evaluate(v) and self.y.evaluate(v)
+
+
+class Expression:
+
+ def __init__(self, v):
+ try:
+ opcodes = [int(x) for x in v]
+ if min(opcodes) >= -1: raise ValueError()
+
+ stack = []
+ for opcode in opcodes:
+ if opcode == -2: # not
+ stack.append(Not(stack.pop()))
+ elif opcode == -3: # and
+ stack.append(And(stack.pop(), stack.pop()))
+ elif opcode == -4: # or
+ stack.append(Or(stack.pop(), stack.pop()))
+ else: # =
+ stack.append(Equals(opcode))
+
+ compiled = stack.pop()
+ self.evaluate = lambda x: compiled.evaluate([int(y) for y in x])
+ except:
+ self.evaluate = lambda x: bool(set(x) & set(v))
+
#
# Now the database
#
@@ -1700,12 +1754,10 @@
if not v:
match = not nv
else:
- # othewise, make sure this node has each of the
+ # otherwise, make sure this node has each of the
# required values
- for want in v:
- if want in nv:
- match = 1
- break
+ expr = Expression(v)
+ if expr.evaluate(nv): match = 1
elif t == STRING:
if nv is None:
nv = ''
Index: share/roundup/templates/devel/html/page.html
===================================================================
--- share/roundup/templates/devel/html/page.html (Revision 4543)
+++ share/roundup/templates/devel/html/page.html (Arbeitskopie)
@@ -307,6 +307,20 @@
+
+
+ (edit)
+ |
+
Index: share/roundup/templates/classic/html/_generic.keywords_expr.html
===================================================================
--- share/roundup/templates/classic/html/_generic.keywords_expr.html (Revision 0)
+++ share/roundup/templates/classic/html/_generic.keywords_expr.html (Revision 0)
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
Index: share/roundup/templates/classic/html/page.html
===================================================================
--- share/roundup/templates/classic/html/page.html (Revision 4543)
+++ share/roundup/templates/classic/html/page.html (Arbeitskopie)
@@ -247,6 +247,22 @@
+
+
+
+ (expr)
+
+ |
+
Index: share/roundup/templates/classic/html/issue.search.html
===================================================================
--- share/roundup/templates/classic/html/issue.search.html (Revision 4543)
+++ share/roundup/templates/classic/html/issue.search.html (Arbeitskopie)
@@ -23,6 +23,7 @@
sort_input templates/page/macros/sort_input;
group_input templates/page/macros/group_input;
search_select templates/page/macros/search_select;
+ search_select_keywords templates/page/macros/search_select_keywords;
search_select_translated templates/page/macros/search_select_translated;
search_multiselect templates/page/macros/search_multiselect;">
@@ -54,7 +55,7 @@
db_klass string:keyword;
db_content string:name;">
Keyword: |
-
+ |
|