-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathattachments.py
299 lines (252 loc) · 9.91 KB
/
attachments.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
'''
Handling of attachments such as images or text snippits
'''
import grok
from zope.component import getUtility, getMultiAdapter
from zope.schema.interfaces import IVocabularyFactory
from zope.schema.vocabulary import SimpleVocabulary
from interfaces import IArticle, IAttachments, IAttachment
from resource import textStyle, popups, style
from layout import Content, ILayout
from colorise import ISourceHighlight
from menu import UtilItem
from permissions import Editing
#____________________________________________________________________________________
class ResourceTypes(grok.GlobalUtility):
""" The types of resources which may be included in our articles
*** NOTE *** Unsure why, but vocabularies defined like this
need zope.app.schema in setup.py
"""
grok.implements(IVocabularyFactory)
grok.name('gfn.resourceTypes')
formats = [
('image', u'A png, gif or jpeg image'),
('html', u'HTML Source'),
('javascript', u'Javascript Code'),
('python', u'Python Sources'),
('css', u'CSS Source')]
def __call__(self, context):
self.context = context
terms = []
for value, title in self.formats:
token = str(value)
terms.append(SimpleVocabulary.createTerm(value,token,title))
return SimpleVocabulary(terms)
#____________________________________________________________________________________
class Attachments(grok.Container):
''' Holds things which implement IAttachment
'''
grok.implements(IAttachments, ILayout)
title = u'Managing Attachments'
#____________________________________________________________________________________
class BackButton(UtilItem):
grok.context(IAttachments)
grok.order(0)
title = u'Back to article'
mclass = 'buttons'
@property
def link(self):
return self.context.__parent__
#____________________________________________________________________________________
class ManageAttachments(UtilItem):
grok.context(IArticle)
grok.require(Editing)
grok.order(-1)
title = u'Manage Attachments'
link = u'attachments'
mclass = 'buttons'
def condition(self):
a = self.context.attachments
return a is not None and len(a)
#____________________________________________________________________________________
class Image(grok.Model):
''' An attachment being an image
'''
grok.implements(IAttachment)
def __init__(self, name, description, fmt, fdata, text):
self.name = name
self.description = description
self.fmt = fmt
self.fdata = fdata
self.text = text
def link(self):
return '''<img src="attachments/{}" />'''.format(self.name)
#____________________________________________________________________________________
class ShowImage(grok.View):
grok.context(Image)
grok.name('index')
grok.require('zope.Public')
def render(self):
return self.context.fdata or self.context.text
#____________________________________________________________________________________
class Source(grok.Model):
''' An attachment being a text item
'''
grok.implements(IAttachment)
def __init__(self, name, description, fmt, fdata, text):
self.name = name
self.description = description
self.fmt = fmt
self.fdata = fdata
self.text = text
if fdata:
self.text = fdata.replace('\r\n', '\n')
def highlight(self):
pygments = getUtility(ISourceHighlight, name="Pygments")
return pygments(self.text, self.fmt) # Returns highlighted text
def link(self):
return '''<div class='attachment' name="%s" src="attachments/%s" />''' % (self.name, self.name)
#____________________________________________________________________________________
class ShowSource(grok.View):
grok.context(Source)
grok.name('index')
grok.require('zope.Public')
html = ''
def update(self):
self.html = self.context.highlight() # Set highlighted text
style.need()
textStyle.need()
#____________________________________________________________________________________
class Highlight(grok.View):
grok.context(Source)
grok.require('zope.Public')
def render(self):
return self.context.highlight() # Get highlighted text
#____________________________________________________________________________________
class ListAttachments(grok.Viewlet):
''' Displays a list of attachments and allows edit/delete on each item
'''
grok.context(IAttachments)
grok.viewletmanager(Content)
def update(self):
popups.need()
#____________________________________________________________________________________
class ModifySource(grok.EditForm):
grok.context(Source)
grok.name('modify')
grok.require(Editing)
def setUpWidgets(self, ignore_request=False):
super(ModifySource, self).setUpWidgets(ignore_request)
self.widgets['text'].cssClass = 'pre'
@grok.action(u'Update')
def Change(self, **data):
attachments = self.context.__parent__
name = data['name']
if name in attachments: del attachments[name]
if data['fmt']=='image':
src = attachments[name] = Image(**data)
else:
src = attachments[name] = Source(**data)
content = getMultiAdapter((src, self.request), name='index')
return content()
@grok.action(u'Cancel action', validator=lambda *_a, **_k: {})
def cancel(self):
attachments = self.context.__parent__
name = self.context.name
src = attachments[name]
content = getMultiAdapter((src, self.request), name='index')
return content()
#____________________________________________________________________________________
class ModifyImage(grok.EditForm):
grok.context(Image)
grok.name('modify')
grok.require(Editing)
form_fields = grok.AutoFields(Image).omit('text', 'fmt')
@grok.action(u'Update')
def Change(self, **data):
attachments = self.context.__parent__
name = data['name']
if name in attachments: del attachments[name]
src = attachments[name] = Image(**data)
return src.link()
@grok.action(u'Cancel action', validator=lambda *_a, **_k: {})
def cancel(self):
attachments = self.context.__parent__
name = self.context.name
src = attachments[name]
return src.link()
#____________________________________________________________________________________
class EditAttachment(grok.EditForm):
grok.context(IAttachment)
grok.name('edit')
grok.require(Editing)
camefrom = None
def update(self, camefrom = None):
self.camefrom = camefrom or self.url(self.context.__parent__)
@grok.action(u'Update')
def Change(self, **data):
attachments = self.context.__parent__
name = data['name']
if name in attachments: del attachments[name]
if data['fmt']=='image':
attachments[name] = Image(**data)
else:
attachments[name] = Source(**data)
self.redirect(self.camefrom)
@grok.action(u'Cancel action', validator=lambda *_a, **_k: {})
def cancel(self):
self.redirect(self.camefrom)
#____________________________________________________________________________________
class DeleteAttachment(grok.EditForm):
grok.context(IAttachment)
grok.name('delete')
grok.require(Editing)
form_fields = grok.Fields(IAttachment).omit('fdata', 'text')
@grok.action(u'Yes, Delete this attachment')
def Delete(self, **data):
attachments = self.context.__parent__
name = data['name']
if name in attachments: del attachments[name]
self.redirect(self.url(attachments))
@grok.action(u'No, get me out of here', validator=lambda *_a, **_k: {})
def cancel(self):
attachments = self.context.__parent__
self.redirect(self.url(attachments))
#____________________________________________________________________________________
class ArticleAttachment(grok.Adapter):
''' An adapter which creates an IAttachment for an IArticle
'''
grok.context(IArticle)
grok.implements(IAttachment)
name = None
description = None
fmt = u'python'
text = u''
fdata = None
#____________________________________________________________________________________
class AddAttachment(grok.EditForm):
''' This is an edit form for resources. These are stored with the article. We
return HTML which will insert the appropriate resource. For images, we
return an image tag. For source text, we return a div linking the
formatted text.
'''
grok.context(IArticle)
form_fields = grok.Fields(IAttachment) # Use the ArticleAttachment adapter
grok.name('attach')
grok.require(Editing)
def setUpWidgets(self, ignore_request=False):
super(AddAttachment, self).setUpWidgets(ignore_request)
self.widgets['text'].cssClass = 'pre'
def update(self):
''' As this view is called directly and displayed in a dialog window, we need to add the
css style explicitly. Also, grok.EditForm includes the HTML header.
'''
style.need()
@grok.action(u'Add this resource')
def addResource(self, **data):
if self.context.attachments is None:
attachments = self.context.attachments = Attachments()
else:
attachments = self.context.attachments
name = data['name']
if name in attachments: del attachments[name]
if data['fmt']=='image':
src = attachments[name] = Image(**data)
return src.link()
else:
src = attachments[name] = Source(**data)
content = getMultiAdapter((src, self.request), name='index')
return content()
@grok.action(u'Cancel action', validator=lambda *_a, **_k: {})
def cancel(self):
return ''