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):
146 def __init__(self, filters):
147 super(StateFilter, self).__init__(filters)
151 def _set_key(self, str):
153 self.state = State.objects.get(id=int(str))
160 return {'state': self.state}
163 return self.state.name
166 if self.state is None:
171 str = '<select name="%s">' % self.param
172 str += '<option value="">any</option>'
173 for state in State.objects.all():
175 if self.state and self.state == state:
176 selected = ' selected="true"'
178 str += '<option value="%d" %s>%s</option>' % \
179 (state.id, selected, state.name)
181 return mark_safe(str);
183 def form_function(self):
184 return 'function(form) { return form.x.value }'
186 class SearchFilter(Filter):
188 def __init__(self, filters):
189 super(SearchFilter, self).__init__(filters)
194 def _set_key(self, str):
202 return {'name__icontains': self.search}
213 value = escape(self.search)
214 return mark_safe('<input name="%s" value="%s">' %\
217 def form_function(self):
218 return mark_safe('function(form) { return form.x.value }')
220 class ArchiveFilter(Filter):
222 def __init__(self, filters):
223 super(ArchiveFilter, self).__init__(filters)
224 self.name = 'Archived'
225 self.archive_state = False
232 self.description_map = {
238 def _set_key(self, str):
239 self.archive_state = False
241 for (k, v) in self.param_map.iteritems():
243 self.archive_state = k
244 if self.archive_state == None:
248 if self.archive_state == None:
250 return {'archived': self.archive_state}
253 return self.description_map[self.archive_state]
256 if self.archive_state == False:
258 return self.param_map[self.archive_state]
262 for b in [False, True, None]:
263 label = self.description_map[b]
265 if self.archive_state == b:
266 selected = 'checked="true"'
267 s += ('<input type="radio" name="%(param)s" ' + \
268 '%(selected)s value="%(value)s">%(label)s' + \
269 ' ') % \
272 'selected': selected,
273 'value': self.param_map[b]
277 def url_without_me(self):
278 qs = self.filters.querystring_without_filter(self)
281 return qs + 'archive=both'
284 class DelegateFilter(Filter):
288 def __init__(self, filters):
289 super(DelegateFilter, self).__init__(filters)
290 self.name = 'Delegate'
291 self.param = 'delegate'
293 # default to applied, but no delegate - this will result in patches with
298 def _set_key(self, str):
306 self.delegate = User.objects.get(id = str)
314 return {'delegate': self.delegate}
318 return self.delegate.get_profile().name()
322 delegates = User.objects.filter(userprofile__maintainer_projects =
323 self.filters.project)
325 str = '<select name="delegate">'
329 selected = 'selected'
331 str += '<option %s value="*">------</option>' % selected
334 if self.delegate is None:
335 selected = 'selected'
337 str += '<option %s value="">Nobody</option>' % selected
341 if d == self.delegate:
342 selected = ' selected'
344 str += '<option %s value="%s">%s</option>' % (selected,
345 d.id, d.get_profile().name())
348 return mark_safe(str)
352 return self.delegate.id
357 def url_without_me(self):
358 qs = self.filters.querystring_without_filter(self)
361 return qs + ('%s=*' % self.param)
363 def set_status(self, *args, **kwargs):
364 if 'delegate' in kwargs:
365 self.applied = self.forced = True
366 self.delegate = kwargs['delegate']
367 if self.AnyDelegate in args:
371 filterclasses = [SubmitterFilter, \
379 def __init__(self, request):
380 self._filters = map(lambda c: c(self), filterclasses)
381 self.dict = request.GET
384 for f in self._filters:
387 def set_project(self, project):
388 self.project = project
390 def filter_conditions(self):
392 for f in self._filters:
394 kwargs.update(f.kwargs())
397 def apply(self, queryset):
398 kwargs = self.filter_conditions()
401 return queryset.filter(**kwargs)
404 return [ (f.param, f.key()) for f in self._filters \
405 if f.key() is not None ]
407 def querystring(self, remove = None):
408 params = dict(self.params())
410 for (k, v) in self.dict.iteritems():
414 if remove is not None:
415 if remove.param in params.keys():
416 del params[remove.param]
418 return '?' + '&'.join(['%s=%s' % x for x in params.iteritems()])
420 def querystring_without_filter(self, filter):
421 return self.querystring(filter)
423 def applied_filters(self):
424 return filter(lambda x: x.applied, self._filters)
426 def available_filters(self):
429 def set_status(self, filterclass, *args, **kwargs):
430 for f in self._filters:
431 if isinstance(f, filterclass):
432 f.set_status(*args, **kwargs)