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 django.contrib.auth.models import User
22 from django import forms
24 from patchwork.models import Patch, State, Bundle, UserProfile
25 from registration.forms import RegistrationFormUniqueEmail
26 from registration.models import RegistrationProfile
28 class RegistrationForm(RegistrationFormUniqueEmail):
29 first_name = forms.CharField(max_length = 30, required = False)
30 last_name = forms.CharField(max_length = 30, required = False)
31 username = forms.CharField(max_length=30, label=u'Username')
32 email = forms.EmailField(max_length=100, label=u'Email address')
33 password = forms.CharField(widget=forms.PasswordInput(),
35 password1 = forms.BooleanField(required = False)
36 password2 = forms.BooleanField(required = False)
38 def save(self, profile_callback = None):
39 user = RegistrationProfile.objects.create_inactive_user( \
40 username = self.cleaned_data['username'],
41 password = self.cleaned_data['password'],
42 email = self.cleaned_data['email'],
43 profile_callback = profile_callback)
44 user.first_name = self.cleaned_data.get('first_name', '')
45 user.last_name = self.cleaned_data.get('last_name', '')
48 # saving the userprofile causes the firstname/lastname to propagate
49 # to the person objects.
50 user.get_profile().save()
55 return self.cleaned_data
57 class LoginForm(forms.Form):
58 username = forms.CharField(max_length = 30)
59 password = forms.CharField(widget = forms.PasswordInput)
61 class BundleForm(forms.ModelForm):
64 fields = ['name', 'public']
66 class CreateBundleForm(forms.ModelForm):
67 def __init__(self, *args, **kwargs):
68 super(CreateBundleForm, self).__init__(*args, **kwargs)
75 name = self.cleaned_data['name']
76 count = Bundle.objects.filter(owner = self.instance.owner, \
79 raise forms.ValidationError('A bundle called %s already exists' \
83 class DeleteBundleForm(forms.Form):
84 name = 'deletebundleform'
85 form_name = forms.CharField(initial = name, widget = forms.HiddenInput)
86 bundle_id = forms.IntegerField(widget = forms.HiddenInput)
88 class DelegateField(forms.ModelChoiceField):
89 def __init__(self, project, *args, **kwargs):
90 queryset = User.objects.filter(userprofile__in = \
92 .filter(maintainer_projects = project) \
94 super(DelegateField, self).__init__(queryset, *args, **kwargs)
97 class PatchForm(forms.ModelForm):
98 def __init__(self, instance = None, project = None, *args, **kwargs):
99 if (not project) and instance:
100 project = instance.project
102 raise Exception("meep")
103 super(PatchForm, self).__init__(instance = instance, *args, **kwargs)
104 self.fields['delegate'] = DelegateField(project, required = False)
108 fields = ['state', 'archived', 'delegate']
110 class UserProfileForm(forms.ModelForm):
113 fields = ['primary_project', 'patches_per_page']
115 class OptionalDelegateField(DelegateField):
116 no_change_choice = ('*', 'no change')
119 def __init__(self, no_change_choice = None, *args, **kwargs):
121 if (no_change_choice):
122 self.no_change_choice = no_change_choice
123 super(OptionalDelegateField, self). \
124 __init__(initial = self.no_change_choice[0], *args, **kwargs)
126 def _get_choices(self):
128 super(OptionalDelegateField, self)._get_choices())
129 choices.append(self.no_change_choice)
132 choices = property(_get_choices, forms.ChoiceField._set_choices)
134 def is_no_change(self, value):
135 return value == self.no_change_choice[0]
137 def clean(self, value):
138 if value == self.no_change_choice[0]:
140 return super(OptionalDelegateField, self).clean(value)
142 class OptionalModelChoiceField(forms.ModelChoiceField):
143 no_change_choice = ('*', 'no change')
146 def __init__(self, no_change_choice = None, *args, **kwargs):
148 if (no_change_choice):
149 self.no_change_choice = no_change_choice
150 super(OptionalModelChoiceField, self). \
151 __init__(initial = self.no_change_choice[0], *args, **kwargs)
153 def _get_choices(self):
155 super(OptionalModelChoiceField, self)._get_choices())
156 choices.append(self.no_change_choice)
159 choices = property(_get_choices, forms.ChoiceField._set_choices)
161 def is_no_change(self, value):
162 return value == self.no_change_choice[0]
164 def clean(self, value):
165 if value == self.no_change_choice[0]:
167 return super(OptionalModelChoiceField, self).clean(value)
169 class MultipleBooleanField(forms.ChoiceField):
170 no_change_choice = ('*', 'no change')
171 def __init__(self, *args, **kwargs):
172 super(MultipleBooleanField, self).__init__(*args, **kwargs)
173 self.choices = [self.no_change_choice] + \
174 [(True, 'Archived'), (False, 'Unarchived')]
176 def is_no_change(self, value):
177 return value == self.no_change_choice[0]
179 # TODO: Check whether it'd be worth to use a TypedChoiceField here; I
180 # think that'd allow us to get rid of the custom valid_value() and
181 # to_python() methods.
182 def valid_value(self, value):
183 if value in [v1 for (v1, v2) in self.choices]:
187 def to_python(self, value):
188 if self.is_no_change(value):
190 elif value == 'True':
192 elif value == 'False':
195 raise ValueError('Unknown value: %s' % value)
197 class MultiplePatchForm(forms.Form):
198 state = OptionalModelChoiceField(queryset = State.objects.all())
199 archived = MultipleBooleanField()
201 def __init__(self, project, *args, **kwargs):
202 super(MultiplePatchForm, self).__init__(*args, **kwargs)
203 self.fields['delegate'] = OptionalDelegateField(project = project,
206 def save(self, instance, commit = True):
207 opts = instance.__class__._meta
209 raise ValueError("The %s could not be changed because the data "
210 "didn't validate." % opts.object_name)
211 data = self.cleaned_data
212 # Update the instance
213 for f in opts.fields:
214 if not f.name in data:
217 field = self.fields.get(f.name, None)
221 if field.is_no_change(data[f.name]):
224 setattr(instance, f.name, data[f.name])
230 class UserPersonLinkForm(forms.Form):
231 email = forms.EmailField(max_length = 200)