Inital commit
[patchwork] / apps / patchwork / forms.py
1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org>
3 #
4 # This file is part of the Patchwork package.
5 #
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.
10 #
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.
15 #
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
19
20
21 from django.contrib.auth.models import User
22 from django import newforms as forms
23
24 from patchwork.models import RegistrationRequest, Patch, State, Bundle, \
25          UserProfile
26
27 class RegisterForm(forms.ModelForm):
28     password = forms.CharField(widget = forms.PasswordInput)
29     email = forms.EmailField(max_length = 200)
30
31     class Meta:
32         model = RegistrationRequest
33         exclude = ['key']
34
35     def clean_email(self):
36         value = self.cleaned_data['email']
37         try:
38             User.objects.get(email = value)
39             raise forms.ValidationError(('The email address %s has ' +
40                     'has already been registered') % value)
41         except User.DoesNotExist:
42             pass
43         try:
44             RegistrationRequest.objects.get(email = value)
45             raise forms.ValidationError(('The email address %s has ' +
46                     'has already been registered') % value)
47         except RegistrationRequest.DoesNotExist:
48             pass
49         return value
50
51     def clean_username(self):
52         value = self.cleaned_data['username']
53         try:
54             User.objects.get(username = value)
55             raise forms.ValidationError(('The username %s has ' +
56                     'has already been registered') % value)
57         except User.DoesNotExist:
58             pass
59         try:
60             RegistrationRequest.objects.get(username = value)
61             raise forms.ValidationError(('The username %s has ' +
62                     'has already been registered') % value)
63         except RegistrationRequest.DoesNotExist:
64             pass
65         return value
66
67 class LoginForm(forms.Form):
68     username = forms.CharField(max_length = 30)
69     password = forms.CharField(widget = forms.PasswordInput)
70
71 class BundleForm(forms.ModelForm):
72     class Meta:
73         model = Bundle
74         fields = ['name', 'public']
75
76 class CreateBundleForm(forms.ModelForm):
77     def __init__(self, *args, **kwargs):
78         super(CreateBundleForm, self).__init__(*args, **kwargs)
79
80     class Meta:
81         model = Bundle
82         fields = ['name']
83
84     def clean_name(self):
85         name = self.cleaned_data['name']
86         count = Bundle.objects.filter(owner = self.instance.owner, \
87                 name = name).count()
88         if count > 0:
89             raise forms.ValidationError('A bundle called %s already exists' \
90                     % name)
91         return name
92
93 class DelegateField(forms.ModelChoiceField):
94     def __init__(self, project, *args, **kwargs):
95         queryset = User.objects.filter(userprofile__in = \
96                 UserProfile.objects \
97                         .filter(maintainer_projects = project) \
98                         .values('pk').query)
99         super(DelegateField, self).__init__(queryset, *args, **kwargs)
100
101
102 class PatchForm(forms.ModelForm):
103     def __init__(self, instance = None, project = None, *args, **kwargs):
104         if (not project) and instance:
105             project = instance.project
106         if not project:
107             raise Exception("meep")
108         super(PatchForm, self).__init__(instance = instance, *args, **kwargs)
109         self.fields['delegate'] = DelegateField(project)
110
111     class Meta:
112         model = Patch
113         fields = ['state', 'archived', 'delegate']
114
115 class UserProfileForm(forms.ModelForm):
116     class Meta:
117         model = UserProfile
118         fields = ['primary_project', 'patches_per_page']
119
120 class OptionalDelegateField(DelegateField):
121     no_change_choice = ('*', 'no change')
122
123     def __init__(self, no_change_choice = None, *args, **kwargs):
124         self.filter = None
125         if (no_change_choice):
126             self.no_change_choice = no_change_choice
127         super(OptionalDelegateField, self). \
128             __init__(initial = self.no_change_choice[0], *args, **kwargs)
129
130     def _get_choices(self):
131         choices = list(
132                 super(OptionalDelegateField, self)._get_choices())
133         choices.append(self.no_change_choice)
134         return choices
135
136     choices = property(_get_choices, forms.ChoiceField._set_choices)
137
138     def is_no_change(self, value):
139         return value == self.no_change_choice[0]
140
141     def clean(self, value):
142         if value == self.no_change_choice[0]:
143             return value
144         return super(OptionalDelegateField, self).clean(value)
145
146 class OptionalModelChoiceField(forms.ModelChoiceField):
147     no_change_choice = ('*', 'no change')
148
149     def __init__(self, no_change_choice = None, *args, **kwargs):
150         self.filter = None
151         if (no_change_choice):
152             self.no_change_choice = no_change_choice
153         super(OptionalModelChoiceField, self). \
154             __init__(initial = self.no_change_choice[0], *args, **kwargs)
155
156     def _get_choices(self):
157         choices = list(
158                 super(OptionalModelChoiceField, self)._get_choices())
159         choices.append(self.no_change_choice)
160         return choices
161
162     choices = property(_get_choices, forms.ChoiceField._set_choices)
163
164     def is_no_change(self, value):
165         return value == self.no_change_choice[0]
166
167     def clean(self, value):
168         if value == self.no_change_choice[0]:
169             return value
170         return super(OptionalModelChoiceField, self).clean(value)
171
172 class MultipleBooleanField(forms.ChoiceField):
173     no_change_choice = ('*', 'no change')
174     def __init__(self, *args, **kwargs):
175         super(MultipleBooleanField, self).__init__(*args, **kwargs)
176         self.choices = [self.no_change_choice] + \
177                 [(True, 'Archived'), (False, 'Unarchived')]
178
179     def is_no_change(self, value):
180         return value == self.no_change_choice[0]
181
182 class MultiplePatchForm(PatchForm):
183     state = OptionalModelChoiceField(queryset = State.objects.all())
184     archived = MultipleBooleanField()
185
186     def __init__(self, project, *args, **kwargs):
187         super(MultiplePatchForm, self).__init__(project = project,
188                 *args, **kwargs)
189         self.fields['delegate'] = OptionalDelegateField(project = project)
190
191     def save(self, instance, commit = True):
192         opts = instance.__class__._meta
193         if self.errors:
194             raise ValueError("The %s could not be changed because the data "
195                     "didn't validate." % opts.object_name)
196         data = self.cleaned_data
197         # remove 'no change fields' from the data
198         for f in opts.fields:
199             if not f.name in data:
200                 continue
201
202             field = getattr(self, f.name, None)
203             if not field:
204                 continue
205
206             if field.is_no_change(data[f.name]):
207                 del data[f.name]
208
209         return forms.save_instance(self, instance,
210                 self._meta.fields, 'changed', commit)
211
212 class UserPersonLinkForm(forms.Form):
213     email = forms.EmailField(max_length = 200)