Attachment 'Gallery2-1.3.5-8.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - Gallery2 parser
4
5 PURPOSE:
6 This parser is used to visualize a couple of images as a thumbnail gallery.
7 A description of an image including WikiName can be added optionally.
8 By default, the image name and its creation date are shown.
9 If you click on a thumbnail you get the webnails shown. By a menue you are able to toggle between the slides.
10
11 USAGE:
12 {{{
13 #!Gallery2 [columns=columns],[filter=filter],[mode=mode],
14 [show_text=show_text],[show_date=show_date], [show_tools=show_tools],
15 [sort_by_name=sort_by_name],[sort_by_date=sort_by_date], [sort_by_alias=sort_by_alias],
16 [reverse_sort=reverse_sort],
17 [only_items=only_items],[template_itemlist=template_itemlist],
18 [thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],
19 [image_for_webnail=image_for_webnail],
20 [border_thick=border_thick],[renew=renew],[help=help]
21 * [image1.jpg alias]
22 * [image2.jpg alias]
23 }}}
24
25 KEYWORD PARAMETERS:
26 columns: number of columns for thumbnails
27 filter: regex to select images
28 show_text: default is 1 description is shown
29 any other means no description
30 show_date: default is 1 date info from exif header if available is shown
31 show_tools: default is 1 icon toolbar is show any other disables this
32 sort_by_name: default is 1, the images are sorted by name, but not if only_items is 1
33 sort_by_date: default is 0, if set to 1 the images are sorted to the modification time
34 sort_by_alias default is 0, if set to 1 and only_items set to 1 it is used to order the images by the alias name
35 reverse_sort: default is 0, if set to 1 the file list is reversed
36 any other means no description
37 mode: default is 1 this means description below the image
38 any other number means description right of image
39 only_items: default is 0 if it is set to 1 only images which are described in listitem are shown
40 dependend on the order of the items
41 template_itemlist: default is 0, if set to 1 an item list is shown which could be copied into the parser area.
42 border_thick: default is 1 this is the thickness in pixeln of the outer frame
43 renew: default is 0 if set to 1 then all selected thumbnails_* and webnails_* removed.
44 Afterwards they are created from scratch.
45 thumbnail_width: default is 128
46 webnail_width: default is 640
47 text_width: default is 140
48 image_for_webnail default is 0 if set to 1 then the image is shown as preview and not the webnail
49 help: default is 0 if set a copy of the CALLING SEQUENCE is shown,
50 (there are some new ideas around to show help to an user so this will be later replaced)
51
52 OPTIONAL INPUTS:
53 itemlist : if it is used and only_items is 1 then only the images in this list are ahown.
54 The alias text is used as description of the image instead of the file name
55
56
57 EXAMPLE:
58 = GalleryTest =
59
60 == all images shown, one is decribed ==
61 {{{
62 { { {
63 #!Gallery2
64 * [100_1185.JPG Bremen, SpaceCenter]
65 } } }
66 }}}
67
68 Result: [[BR]]
69 {{{
70 #!Gallery2
71 * [100_1185.JPG Bremen, SpaceCenter]
72 }}}
73
74 == only thumbnails and only_items ==
75 {{{
76 { { {
77 #!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
78 * [100_1185.JPG Bremen, SpaceCenter]
79 * [100_1194.JPG Bremen]
80 } } }
81 }}}
82
83 Result: [[BR]]
84 {{{
85 #!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
86 * [100_1185.JPG Bremen, SpaceCenter]
87 * [100_1194.JPG Bremen]
88 }}}
89
90 == only_items by two columns and text right ==
91
92 {{{
93 { { {
94 #!Gallery2 mode=2,columns=2,only_items=1
95 * [100_1185.JPG Bremen, SpaceCenter]
96 * [100_1194.JPG Bremen]
97 } } }
98 }}}
99
100 Result: [[BR]]
101 {{{
102 #!Gallery2 mode=2,columns=2,only_items=1
103 * [100_1185.JPG Bremen, SpaceCenter]
104 * [100_1194.JPG Bremen, behind SpaceCenter]
105 }}}
106
107 ----
108
109 == only_items by two columns, date supressed ==
110
111 {{{
112 { { {
113 #!Gallery2 columns=2,only_items=1,show_date=0
114 * [100_1185.JPG Bremen, SpaceCenter]
115 * [100_1194.JPG Bremen, behind SpaceCenter]
116 } } }
117 }}}
118
119 Result: [[BR]]
120 {{{
121 #!Gallery2 columns=2,only_items=1,show_date=0
122 * [100_1185.JPG Bremen, SpaceCenter]
123 * [100_1194.JPG Bremen, behind SpaceCenter]
124 }}}
125
126
127 == filter regex used, mode 2, icons and date supressed, one column and border_thick=5 ==
128 {{{
129 { { {
130 #!Gallery2 columns=1,filter=100_118[0-5],mode=2,show_date=0,show_tools=0,border_thick=5
131 } } }
132 }}}
133
134 Result: [[BR]]
135 {{{
136 #!Gallery2 columns=1,filter=100_118[0-7],mode=2,show_date=0,show_tools=0,border_thick=5
137 }}}
138
139 == other macro calls ==
140 {{{
141 { { {
142 #!Gallery2 only_items=1,show_date=0
143 * [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
144 } } }
145 }}}
146
147 Result: [[BR]]
148 {{{
149 #!Gallery2 only_items=1,show_date=0
150 * [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
151 }}}
152
153 == renew means always new thumbnails and webnails of selection ==
154 {{{
155 { { {
156 #!Gallery2 only_items=1,show_date=0,show_tools=0,renew=1
157 * [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
158 } } }
159 }}}
160
161 Result: [[BR]]
162 {{{
163 #!Gallery2 only_items=1,show_date=0,renew=1
164 * [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
165 }}}
166
167 == template_itemlist ==
168 {{{
169 { { {
170 #!Gallery2 template_itemlist=1
171 * [100_1185.JPG Bremen, SpaceCenter]
172 } } }
173 }}}
174
175 Result: [[BR]]
176 {{{
177 #!Gallery2 template_itemlist=1
178 * [100_1185.JPG Bremen, SpaceCenter]
179 }}}
180
181 == help to show Calling Sequence ==
182 {{{
183 { { {
184 #!Gallery2 help=1
185 } } }
186 }}}
187
188 Result: [[BR]]
189 {{{
190 #!Gallery2 help=1
191 }}}
192
193
194 PROCEDURE:
195 Upload some images to a page and start with the examples.
196 Aliasing of the filenames is done by adding an itemlist, see example.
197
198 This script requires the PIL (Python Imaging Library) and the
199 EXIF routine from http://home.cfl.rr.com/genecash/digital_camera.html
200
201 At the moment I have added the EXIF routine to the parsers dir.
202 It's not the best place but during developing it is nice to have it there
203 If you put it to another place you have to change the line
204 from MoinMoin.parser import EXIF too.
205
206 This routine requires the Action macro gallery2Image which is used to rotate or delete a selected image.
207 Only users which have the rights to delete are able to execute this action macro.
208 The icons of these are only shown if you have enough rights.
209
210 The gallery2image macro does not take care of the EXIF header. This is lost by rotating.
211 If a file is deleted by this macro it is moved to a bak file.
212
213 Please remove the Version number from the script filename!
214
215 RESTRICTIONS:
216 The movie mode is not implemented at the moment. The implementation will be done in the action macro.
217
218
219 If you rotate an image at the moment the exif is destroyed. PIL ignores the exif header.
220 This is not a quite big problem normally files with an EXIF header are oriented correctly.
221
222 Required Images:
223 I have put them to wiki/modern/img/ dir. The icons were created by me. License: GPL
224
225 attachment:to_bak.png
226 attachment:to_left.png
227 attachment:to_right.png
228 attachment:to_slide.png
229 attachment:to_full.png
230
231 HISTORY:
232 While recognizing how to write MiniPage I got the idea to write a Gallery Parser.
233 We have used in our wikis in the past the Gallery macro of SimonRyan.
234 I have tried to modify it a bit to change it for 1.3 but my python skills weren't enough
235 or it was easier to write it completly new.
236 So this one shows now a way how a Gallery could be used by the parser and an action Macro.
237 Probably it is a good example for others who like to know how to do this
238
239 MODIFICATION HISTORY:
240 Version 1.3.3.-1
241 @copyright: 2005 by Reimar Bauer (R.Bauer@fz-juelich.de)
242 @license: GNU GPL, see COPYING for details.
243 2005-03-26: Version 1.3.3-2 keyword renew added
244 creation of thumbnails and webnails in two calls splitted
245 Version 1.3.3-3 bug fixed if itemlist is given to describe only some of the images
246 but only_items is not set to 1
247 Example code changed
248 2005-03-27: Version 1.3.3-4 Action macro added and the form to call it. User which have rights to delete
249 could use the functions of gallery2Image.
250 2005-08-03: Version 1.3.3-5 theme path for icons corrected and a platform independent path joining
251 os.unlink removed as suggested by CraigJohnson
252 sort_by_name is default if not only_items is 1
253 optional sort_by_date could be used
254 keyword template_itemlist added
255 keyword help added
256 extra frame by mode=2 removed
257 2005-08-06: Version 1.3.5-6 slideshow mode added
258 keyword image_for_webnail added
259 2005-08-09: Version 1.3.5-7 syntax changed from GET to POST
260 forms instead of links
261 filenames from images submitted to gallery2image too
262 new keyword sort_by_alias
263 internal code clean up
264 this version needs: gallery2image-1.3.5-5.py
265 2005-08-14: Version 1.3.5-8 (TW) cleanup, please read the diff and PEP8
266
267 """
268
269 Dependencies = []
270
271 from MoinMoin.action import AttachFile
272 from MoinMoin import wikiutil, config
273 from MoinMoin.Page import Page
274
275 import os, re, Image, StringIO
276
277 from MoinMoin.parser import EXIF
278
279 from MoinMoin.parser import wiki
280
281 #def ImageProcess(var):
282 # f=open('/tmp/workfile.txt', 'w')
283 # f.write(var)
284 # f.close()
285
286 def get_files(kw, path, files, quotes, request):
287 web = []
288 full = []
289 thumb = []
290 exif_date = []
291 img_type = []
292 description = []
293
294 ddict = {}
295 n = len(quotes['image'])
296 if n > 0:
297 i = 0
298 for txt in quotes['image']:
299 ddict[txt] = quotes['alias'][i]
300 i += 1
301
302 for attfile in files:
303 # only files not thumb or webnails
304 if attfile.find('thumbnail_') == -1 and attfile.find('webnail_') == -1:
305 # only images
306 if wikiutil.isPicture(attfile):
307 description.append(ddict.get(attfile, attfile))
308 full.append(attfile)
309
310 if kw['image_for_webnail'] == '1':
311 webnail = attfile
312 else:
313 fname, ext = os.path.splitext(attfile)
314 if ext in ('.gif', '.png'):
315 img_type.append('PNG')
316 webnail = 'webnail_%s.png' % fname
317 thumbfile = 'thumbnail_%s.png' % fname
318 else:
319 img_type.append("JPEG")
320 webnail = 'webnail_%s.jpg' % fname
321 thumbfile = 'thumbnail_%s.jpg' % fname
322
323 infile = os.path.join(path, attfile)
324 if os.path.exists(infile):
325 web.append(webnail)
326 thumb.append(thumbfile)
327
328 f = open(infile, 'rb')
329 tags = EXIF.process_file(f)
330 if tags.has_key('EXIF DateTimeOriginal'):
331 date = str(tags['EXIF DateTimeOriginal'])
332 date = date.replace(':', '-', 2)
333 else:
334 date = '--'
335 exif_date.append(date)
336 f.close()
337
338 return thumb, web, full, exif_date, img_type, description
339
340 def to_htmltext(text):
341 text = text.split(' ')
342 text = ' '.join(text)
343 return text
344
345 def to_wikiname(request, formatter, text):
346 ##taken from MiniPage
347 out = StringIO.StringIO()
348 request.redirect(out)
349 wikiizer = wiki.Parser(text.strip(), request)
350 wikiizer.format(formatter)
351 naw = out.getvalue() # XXX "naw" ???
352 request.redirect()
353 del out
354 return naw.strip()
355
356 def get_quotes(self, formatter):
357 quotes = self.raw.split('\n')
358 quotes = [quote.strip() for quote in quotes]
359 quotes = [quote[2:] for quote in quotes if quote.startswith('* ')]
360
361 image = []
362 text = []
363
364 for line in quotes:
365 im, na = line[1:-1].split(' ', 1)
366 text.append(na.strip())
367 image.append(im.strip())
368
369 return {
370 'alias': text,
371 'image': image,
372 }
373
374
375 class Parser:
376
377 def __init__(self, raw, request, **kw):
378 self.raw = raw
379 self.request = request
380 self.form = request.form
381 self._ = request.getText
382 self.kw = {
383 'sort_by_date': '0', # not implemented yet
384 'sort_by_name': '1',
385 'sort_by_alias': '0',
386 'template_itemlist': '0',
387 'reverse_sort': '0',
388 'border_thick': '1',
389 'columns': '4',
390 'filter': '.',
391 'mode': '1',
392 'help': '0',
393 'show_text': '1',
394 'show_date': '1',
395 'show_tools': '1',
396 'only_items': '0',
397 'image_for_webnail': '0',
398 'renew': '0',
399 'thumbnail_width': '128',
400 'webnail_width': '640',
401 'text_width': '140',
402 }
403
404 for arg in kw.get('format_args', '').split(','):
405 if arg.find('=') > -1:
406 key, value = arg.split('=')
407 self.kw[key] = wikiutil.escape(value, quote=1)
408
409 self.kw['width'] = str((int(self.kw['thumbnail_width']) + int(self.kw['text_width'])))
410
411
412 def format(self, formatter):
413 kw = self.kw
414 Dict = {}
415 quotes = get_quotes(self, formatter)
416 current_pagename = formatter.page.page_name
417 attachment_path = AttachFile.getAttachDir(self.request, current_pagename, create=1)
418
419 if kw['help'] == '1':
420 self.request.write('''
421 <br>
422 {{{<br>
423 #!Gallery2 [columns=columns],[filter=filter],[mode=mode],<br>
424 [show_text=show_text],[show_date=show_date], [show_tools=show_tools],<br>
425 [sort_by_name=sort_by_name],[sort_by_date=sort_by_date],[sort_by_alias=sort_by_alias]<br>
426 [reverse_sort=reverse_sort],<br>
427 [only_items=only_items],[template_itemlist=template_itemlist],<br>
428 [thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],<br>
429 [image_for_webnail=image_for_webnail],<br>
430 [border_thick=border_thick],[renew=renew],[help=help]<br>
431 * [image1.jpg alias]<br>
432 * [image2.jpg alias]<br>
433 }}}<br>''')
434 return
435
436 if kw['only_items'] == '1':
437 all_files = quotes['image']
438
439 if kw['sort_by_alias'] == '1':
440 new_ordered_files = []
441 alias_text = quotes['alias']
442
443 i = 0
444 for attfile in all_files:
445 infile = os.path.join(attachment_path, attfile)
446 ft_file = str(os.path.getmtime(infile)) + os.tmpnam()
447 Dict[alias_text[i]] = attfile
448 i += 1
449
450 keys = Dict.keys()
451 keys.sort()
452 for txt in keys:
453 new_ordered_files.append(Dict[txt])
454
455 all_files = new_ordered_files
456 Dict.clear()
457
458 else:
459 all_files = os.listdir(attachment_path)
460
461 result = []
462 for test in all_files:
463 if re.match(kw['filter'], test):
464 result.append(test)
465 all_files = result
466
467 if not all_files:
468 self.request.write("<br><br><h1>No matching image file found!</h1>")
469 return
470
471 if kw['sort_by_name'] == '1' and kw['only_items'] == '0':
472 all_files.sort()
473
474 if kw['sort_by_date'] == '1':
475 for attfile in all_files:
476 infile = os.path.join(attachment_path, attfile)
477 ft_file = str(os.path.getmtime(infile)) + os.tmpnam()
478 Dict[ft_file] = attfile
479
480 keys = Dict.keys()
481 keys.sort()
482 file_mdate = []
483 for txt in keys:
484 file_mdate.append(Dict[txt])
485 all_files = file_mdate
486 Dict.clear()
487
488 if kw['reverse_sort'] == '1':
489 all_files.reverse()
490
491 cells = []
492 cell_name = []
493 img = []
494
495 thumb, web, full, exif_date, imgtype, description = get_files(kw, attachment_path, all_files, quotes, self.request)
496
497 if kw['template_itemlist'] == '1':
498 self.request.write('Copy the following listitems into the parser area. Replace alias with the label you want. Afterwards disable template_itemlist by setting it to 0:<BR>')
499
500 i = 0
501 for attfile in full:
502 thumbfile = thumb[i]
503 img_type = imgtype[i]
504
505 infile = os.path.join(attachment_path, attfile)
506 webnail = web[i]
507 this_description = description[i]
508 this_exif_date = exif_date[i]
509
510 img.append(attfile)
511 if kw['template_itemlist'] == '1':
512 self.request.write(' * [%(attfile)s %(date)s]<br>' % {
513 'attfile' : attfile,
514 'date' : 'alias'
515 })
516
517 thumbf = os.path.join(attachment_path, thumbfile)
518 webf = os.path.join(attachment_path, webnail)
519
520 if kw['renew'] == '1':
521 if os.path.exists(thumbf):
522 os.unlink(thumbf)
523 if os.path.exists(webf):
524 os.unlink(webf)
525
526 if not os.path.exists(webf) or not os.path.exists(thumbf):
527 im = Image.open(infile)
528 if not os.path.exists(webf):
529 im.thumbnail(((int(kw['webnail_width'])),((int(kw['webnail_width'])))), Image.ANTIALIAS)
530 im.save(webf, img_type)
531 if not os.path.exists(thumbf):
532 im.thumbnail(((int(kw['thumbnail_width'])),((int(kw['thumbnail_width'])))), Image.ANTIALIAS)
533 im.save(thumbf, img_type)
534
535 alias_text = "%(this)s,%(all_other)s" % {
536 "this": this_description,
537 "all_other": '","'.join(description)}
538
539 text = '''
540 <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
541 <tt>
542 <input type="hidden" name="action" value="gallery2image">
543 <input type="hidden" name="do" value="VS">
544 <input type="hidden" name="full" value="%(full)s">
545 <input type="hidden" name="alias" value="%(alias)s">
546 <input type="hidden" name="exif_date" value="%(exif_date)s">
547 <input type="hidden" name="target" value="%(target)s">
548 <input type="image" value="submit" src=%(submit)s>
549 </tt>
550 </form>
551 ''' % {
552 'baseurl': self.request.getScriptname(),
553 'pagename': wikiutil.quoteWikinameURL(current_pagename),
554 'full': attfile + "," + ','.join(full),
555 'alias': to_htmltext(this_description + "!,!" + '!,!'.join(description)),
556 'exif_date': to_htmltext(this_exif_date + "," + ','.join(exif_date)),
557 'target': webnail + "," + ','.join(web),
558 'submit': AttachFile.getAttachUrl(current_pagename, thumbfile, self.request),
559 }
560 cells.append(text)
561 cell_name.append(attfile)
562 i += 1
563
564 result = []
565 if len(full) == 0:
566 result.append('Image not found')
567
568 n = len(cells)
569 cols = int(kw['columns'])
570 rows = n/cols
571 first = 0
572 z = 1
573 i = 0
574
575 ############################################
576 ##TODO: syntax change to formatter - later #
577 ############################################
578
579 # fixed width because of better visualisation on different browsers
580
581 result.append('<table border="%(border_thick)s" valign="bottom">' % kw)
582 l = 0
583 for line in cells:
584 if z == 1:
585 if cols > 1 and n > 1:
586 if kw['mode'] == '1':
587 result.append('<td width="%(thumbnail_width)s">' % kw)
588 #result.append(formatter.table_cell(1))
589 else:
590 result.append('<td width="%(width)s">' % kw)
591 if n > 1 and cols > 1:
592 result.append('<table border="1" valign="center">')
593
594 result.append('<tr valign="center">')
595 # image align center
596 result.append('<td align="center" valign="center" width="%(thumbnail_width)s">' % kw)
597 result.append(line)
598 result.append(formatter.table_cell(0))
599
600 if kw['show_text'] == '1':
601 if kw['mode'] == '1':
602 result.append(formatter.table_row(0))
603 result.append(formatter.table_row(1))
604 # text aligned left in mode 1
605 result.append('<td align="left" width="%(thumbnail_width)s">' % kw)
606 else:
607 # text aligned on top in mode 2
608 result.append('<td valign="top" width="%(text_width)s">' % kw)
609
610 result.append(to_wikiname(self.request, formatter, description[l]))
611
612 result.append(formatter.table_cell(0))
613 if kw['mode'] == '1':
614 result.append(formatter.table_row(0))
615 l += 1
616
617 if kw['show_date'] == '1':
618 if kw['mode'] == '1':
619 result.append(formatter.table_row(1))
620 result.append(formatter.table_cell(1))
621 result.append(exif_date[i])
622 result.append(formatter.table_cell(0))
623 result.append(formatter.table_row(0))
624
625 if kw['show_tools'] == '1':
626 result.append(formatter.table_row(1))
627 # tool bar centered
628 result.append('<td align="center">')
629 result.append('<table align="center">')
630 result.append('<tr><td>')
631 result.append('<form><tt>')
632 result.append('<input type="hidden" name="action" value="AttachFile">')
633 result.append('<input type="hidden" name="do" value=get>')
634 result.append('<input type="hidden" name="target" value="%s">' % img[i])
635 result.append('<input type="image" value="submit" src="/wiki/modern/img/to_full.png" title="load image">')
636 result.append('</tt></form>')
637 result.append('</td><td>')
638 result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><tt>' % {
639 'baseurl': self.request.getScriptname(),
640 'pagename': wikiutil.quoteWikinameURL(current_pagename)})
641
642 result.append('<input type="hidden" name="action" value="gallery2image">')
643 result.append('<input type="hidden" name="do" value="VS">')
644 result.append('<input type="hidden" name="full" value="%s">' % attfile + "," + ','.join(full))
645 result.append('<input type="hidden" name="alias" value="%s">' % to_htmltext(description[0] + "!,!" + '!,!'.join(description)))
646
647 result.append('<input type="hidden" name="target" value="%s">' % webnail + "," + ','.join(web))
648 result.append('<input type="hidden" name="exif_date" value="%s">' % to_htmltext(this_exif_date + "," + ','.join(exif_date)))
649 #result.append('<input type="hidden" name="target" value="%s">' % ','.join(img))
650 result.append('<input type="image" value="submit" src="/wiki/modern/img/to_slide.png" title="slide_show">') # XXX make theme variable
651 result.append('</tt></form>')
652 result.append('</td>')
653
654 if self.request.user.may.delete(current_pagename):
655 result.append('<td>')
656
657 result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><tt>' % {
658 'baseurl': self.request.getScriptname(),
659 'pagename': wikiutil.quoteWikinameURL(current_pagename)})
660
661 result.append('<input type="hidden" name="action" value="gallery2image">')
662 result.append('<input type="hidden" name="do" value="RL">')
663 result.append('<input type="hidden" name="target" value="%s">' % img[i])
664 result.append('<input type="image" value="submit" src="/wiki/modern/img/to_left.png" title="rotate to left">')
665 result.append('</tt></form>')
666 result.append('</td><td>')
667 result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><tt>' % {
668 'baseurl': self.request.getScriptname(),
669 'pagename': wikiutil.quoteWikinameURL(current_pagename)})
670
671 result.append('<input type="hidden" name="action" value="gallery2image">')
672 result.append('<input type="hidden" name="do" value="RR">')
673 result.append('<input type="hidden" name="target" value="%s">' % img[i])
674 result.append('<input type="image" value="submit" src="/wiki/modern/img/to_right.png" title="rotate to right">')
675
676 result.append('</tt></form>')
677 result.append('</td><td>')
678 result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><tt>' % {
679 'baseurl': self.request.getScriptname(),
680 'pagename': wikiutil.quoteWikinameURL(current_pagename)})
681
682 result.append('<input type="hidden" name="action" value="gallery2image">')
683 result.append('<input type="hidden" name="do" value="RM">')
684 result.append('<input type="hidden" name="target" value="%s">' % img[i])
685 result.append('<input type="image" value="submit" src="/wiki/modern/img/to_bak.png" title="move to bak">')
686 result.append('</tt></form>')
687 result.append('</td>')
688 result.append('</tr>')
689 result.append('</table>')
690
691 result.append(formatter.table_cell(0))
692 if kw['show_date'] == '1':
693 if not kw['mode'] == '1':
694 result.append(formatter.table_cell(1))
695 result.append(exif_date[i])
696 result.append(formatter.table_cell(0))
697 if kw['show_tools'] == '1':
698 result.append(formatter.table_row(0))
699 if n > 1 and cols > 1:
700 result.append(formatter.table(0))
701 if z != cols and i < n-1:
702 result.append(formatter.table_cell(1))
703 if z == cols:
704 result.append(formatter.table_cell(0))
705 result.append(formatter.table_row(0))
706 z += 1
707 i += 1
708 if z > cols:
709 z = 1
710
711 result.append(formatter.table(0))
712 ##Output
713 self.request.write(''.join(result))
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.