1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org>
4 # This file is part of the Patchwork package.
6 # Patchwork is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # Patchwork is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Patchwork; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 from patchwork.models import Person, State
22 from django.utils.safestring import mark_safe
23 from django.utils.html import escape
24 from django.contrib.auth.models import User
27 def __init__(self, filters):
28 self.filters = filters
33 """The 'name' of the filter, to be displayed in the filter UI"""
37 """The current condition of the filter, to be displayed in the
42 """The key for this filter, to appear in the querystring. A key of
43 None will remove the param=ley pair from the querystring."""
46 def set_status(self, *kwargs):
47 """Views can call this to force a specific filter status. For example,
48 a user's todo page needs to setup the delegate filter to show
49 that user's delegated patches"""
52 def parse(self, dict):
53 if self.param not in dict.keys():
55 self._set_key(dict[self.param])
57 def url_without_me(self):
58 return self.filters.querystring_without_filter(self)
60 def form_function(self):
61 return 'function(form) { return "unimplemented" }'
65 return mark_safe('<input type="hidden" value="%s">%s' % (self.param,
67 return self.condition()
74 return '%s: %s' % (self.name, self.kwargs())
77 class SubmitterFilter(Filter):
79 def __init__(self, filters):
80 super(SubmitterFilter, self).__init__(filters)
81 self.name = 'Submitter'
83 self.person_match = None
85 def _set_key(self, str):
87 self.person_match = None
90 submitter_id = int(str)
97 self.person = Person.objects.get(id = int(str))
102 people = Person.objects.filter(name__icontains = str)
107 self.person_match = str
112 user = self.person.user
114 return {'submitter__in':
115 Person.objects.filter(user = user).values('pk').query}
116 return {'submitter': self.person}
118 if self.person_match:
119 return {'submitter__name__icontains': self.person_match}
124 return self.person.name
125 elif self.person_match:
126 return self.person_match
132 name = self.person.name
133 return mark_safe(('<input onKeyUp="submitter_field_change(this)" ' +
134 'name="submitter" id="submitter_input" ' +
135 'value="%s"> ' % escape(name)) +
136 '<select id="submitter_select" ' +
137 'disabled="true"></select>')
141 return self.person.id
142 return self.person_match
144 class StateFilter(Filter):
147 action_req_str = 'Action Required'
149 def __init__(self, filters):
150 super(StateFilter, self).__init__(filters)
155 def _set_key(self, str):
158 if str == self.any_key:
163 self.state = State.objects.get(id=int(str))
170 if self.state is not None:
171 return {'state': self.state}
173 return {'state__in': \
174 State.objects.filter(action_required = True) \
179 return self.state.name
180 return self.action_req_str
183 if self.state is not None:
190 str = '<select name="%s">' % self.param
194 selected = 'selected'
195 str += '<option %s value="%s">any</option>' % (selected, self.any_key)
198 if self.applied and self.state == None:
199 selected = 'selected'
200 str += '<option %s value="">%s</option>' % \
201 (selected, self.action_req_str)
203 for state in State.objects.all():
205 if self.state and self.state == state:
206 selected = ' selected="true"'
208 str += '<option value="%d" %s>%s</option>' % \
209 (state.id, selected, state.name)
211 return mark_safe(str);
213 def form_function(self):
214 return 'function(form) { return form.x.value }'
216 def url_without_me(self):
217 qs = self.filters.querystring_without_filter(self)
220 return qs + '%s=%s' % (self.param, self.any_key)
222 class SearchFilter(Filter):
224 def __init__(self, filters):
225 super(SearchFilter, self).__init__(filters)
230 def _set_key(self, str):
238 return {'name__icontains': self.search}
249 value = escape(self.search)
250 return mark_safe('<input name="%s" value="%s">' %\
253 def form_function(self):
254 return mark_safe('function(form) { return form.x.value }')
256 class ArchiveFilter(Filter):
258 def __init__(self, filters):
259 super(ArchiveFilter, self).__init__(filters)
260 self.name = 'Archived'
261 self.archive_state = False
268 self.description_map = {
274 def _set_key(self, str):
275 self.archive_state = False
277 for (k, v) in self.param_map.iteritems():
279 self.archive_state = k
280 if self.archive_state == None:
284 if self.archive_state == None:
286 return {'archived': self.archive_state}
289 return self.description_map[self.archive_state]
292 if self.archive_state == False:
294 return self.param_map[self.archive_state]
298 for b in [False, True, None]:
299 label = self.description_map[b]
301 if self.archive_state == b:
302 selected = 'checked="true"'
303 s += ('<input type="radio" name="%(param)s" ' + \
304 '%(selected)s value="%(value)s">%(label)s' + \
305 ' ') % \
308 'selected': selected,
309 'value': self.param_map[b]
313 def url_without_me(self):
314 qs = self.filters.querystring_without_filter(self)
317 return qs + 'archive=both'
320 class DelegateFilter(Filter):
322 no_delegate_key = '-'
323 no_delegate_str = 'Nobody'
326 def __init__(self, filters):
327 super(DelegateFilter, self).__init__(filters)
328 self.name = 'Delegate'
329 self.param = 'delegate'
332 def _set_key(self, str):
333 if str == self.no_delegate_key:
340 self.delegate = User.objects.get(id = str)
348 return {'delegate': self.delegate}
352 return self.delegate.get_profile().name()
353 return self.no_delegate_str
356 delegates = User.objects.filter(userprofile__maintainer_projects =
357 self.filters.project)
359 str = '<select name="delegate">'
363 selected = 'selected'
365 str += '<option %s value="">------</option>' % selected
368 if self.applied and self.delegate is None:
369 selected = 'selected'
371 str += '<option %s value="%s">%s</option>' % \
372 (selected, self.no_delegate_key, self.no_delegate_str)
376 if d == self.delegate:
377 selected = ' selected'
379 str += '<option %s value="%s">%s</option>' % (selected,
380 d.id, d.get_profile().name())
383 return mark_safe(str)
387 return self.delegate.id
389 return self.no_delegate_key
392 def set_status(self, *args, **kwargs):
393 if 'delegate' in kwargs:
394 self.applied = self.forced = True
395 self.delegate = kwargs['delegate']
396 if self.AnyDelegate in args:
400 filterclasses = [SubmitterFilter, \
408 def __init__(self, request):
409 self._filters = map(lambda c: c(self), filterclasses)
410 self.dict = request.GET
413 for f in self._filters:
416 def set_project(self, project):
417 self.project = project
419 def filter_conditions(self):
421 for f in self._filters:
423 kwargs.update(f.kwargs())
426 def apply(self, queryset):
427 kwargs = self.filter_conditions()
430 return queryset.filter(**kwargs)
433 return [ (f.param, f.key()) for f in self._filters \
434 if f.key() is not None ]
436 def querystring(self, remove = None):
437 params = dict(self.params())
439 for (k, v) in self.dict.iteritems():
443 if remove is not None:
444 if remove.param in params.keys():
445 del params[remove.param]
447 return '?' + '&'.join(['%s=%s' % x for x in params.iteritems()])
449 def querystring_without_filter(self, filter):
450 return self.querystring(filter)
452 def applied_filters(self):
453 return filter(lambda x: x.applied, self._filters)
455 def available_filters(self):
458 def set_status(self, filterclass, *args, **kwargs):
459 for f in self._filters:
460 if isinstance(f, filterclass):
461 f.set_status(*args, **kwargs)