Attachment 'Gallery2-1.5.4-16.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         Optional a description of an image could be added including WikiName.
   8         On default the image name and it's creation date is 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     CALLING SEQUENCE:
  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                  [album=album],[album_name=album_name],[front_image=front_image],
  19                  [thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],
  20                  [image_for_webnail=image_for_webnail],
  21                  [sequence_name=sequence_name], [sequence_fps=sequence_fps],
  22                  [border_thick=border_thick],[renew=renew],[help=help]
  23       * [image1.jpg alias]
  24       * [image2.jpg alias]
  25       }}}
  26 
  27     KEYWORD PARAMETERS:
  28         columns:           number of columns for thumbnails
  29         filter:            regex to select images
  30         show_text:         default is 1 description is shown
  31                            any other means no description
  32         show_date:         default is 1 date info from exif header if available is shown
  33         show_tools:        default is 1 icon toolbar is show any other disables this
  34         sort_by_name:      default is 1, the images are sorted by name, but not if only_items is 1
  35         sort_by_date:      default is 0, if set to 1 the images are sorted to the modification time
  36                            if they do have all the same time then the result is random
  37         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
  38         reverse_sort:      default is 0, if set to 1 the file list is reversed
  39                            any other means no description
  40         mode:              default is 1 this means description below the image
  41                            any other number means description right of image
  42         only_items:        default is 0 if it is set to 1 only images which are described in listitem are shown
  43                            dependend on the order of the items
  44         template_itemlist: default is 0, if set to 1 an item list is shown which could be copied into the script. 
  45         album:             default is 0 if set to 1 only the first image of a series is shown but slideshow over all images 
  46         album_name:        useful for album. default is 'album' use it as short name for the album. 
  47         front_image:       Useful for album.  default is ''. The first image is shown in front of the album and slideshow.
  48                            If set to an existing image name this is shown in front of album and slideshow. 
  49                            The slide show could start by this somewhere.
  50         border_thick:      default is 1 this is the thickness in pixeln of the outer frame
  51         renew:             default is 0 if set to 1 then all selected thumbnails_* and webnails_* removed.
  52                            Afterwards they are new created.
  53         thumbnail_width:   default is 128
  54         webnail_width:     default is 640
  55         text_width:        default is 140		   
  56         image_for_webnail  default is 0 if set to 1 then the image is shown as preview and not the webnail
  57         sequence_name:     default is ''  if set this name is used for an image
  58                            sequence with an duration of one image per second.
  59         sequence_fps:      (frames per second) default is 1 it is not allowed to set values below 1
  60         help:              default is 0 if set a copy of the CALLING SEQUENCE is shown, 
  61                            (there are some new ideas around to show help to an user so this will be later replaced)
  62                            
  63 
  64     OPTIONAL INPUTS:
  65         itemlist : if it is used and only_items is 1 then only the images in this list are ahown.
  66                    The alias text is used as description of the image instead of the file name
  67 
  68 
  69     EXAMPLE:
  70 = GalleryTest =
  71 
  72 == all images shown, one is decribed ==
  73 {{{
  74 { { {
  75 #!Gallery2
  76 * [100_1185.JPG Bremen, SpaceCenter]
  77 } } }
  78 }}}
  79 
  80 Result: [[BR]]
  81  {{{
  82 #!Gallery2
  83 * [100_1185.JPG Bremen, SpaceCenter]
  84 }}}
  85 
  86 == only thumbnails and only_items ==
  87 {{{
  88 { { {
  89 #!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
  90  * [100_1185.JPG Bremen, SpaceCenter]
  91  * [100_1194.JPG Bremen]
  92 } } }
  93 }}}
  94 
  95 Result: [[BR]]
  96  {{{
  97 #!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
  98  * [100_1185.JPG Bremen, SpaceCenter]
  99  * [100_1194.JPG Bremen]
 100 }}}
 101 
 102 == only_items by two columns and text right ==
 103 
 104 {{{
 105 { { {
 106 #!Gallery2 mode=2,columns=2,only_items=1
 107  * [100_1185.JPG Bremen, SpaceCenter]
 108  * [100_1194.JPG Bremen]
 109 } } }
 110 }}}
 111 
 112 Result: [[BR]]
 113  {{{
 114 #!Gallery2 mode=2,columns=2,only_items=1
 115  * [100_1185.JPG Bremen, SpaceCenter]
 116  * [100_1194.JPG Bremen, behind SpaceCenter]
 117 }}}
 118 
 119 ----
 120 
 121 == only_items by two columns, date supressed ==
 122 
 123 {{{
 124 { { {
 125 #!Gallery2 columns=2,only_items=1,show_date=0
 126  * [100_1185.JPG Bremen, SpaceCenter]
 127  * [100_1194.JPG Bremen, behind SpaceCenter]
 128 } } }
 129 }}}
 130 
 131 Result: [[BR]]
 132  {{{
 133 #!Gallery2 columns=2,only_items=1,show_date=0
 134  * [100_1185.JPG Bremen, SpaceCenter]
 135  * [100_1194.JPG Bremen, behind SpaceCenter]
 136 }}}
 137 
 138 
 139 == filter regex used, mode 2, icons and date supressed, one column and border_thick=5 ==
 140 {{{
 141 { { {
 142 #!Gallery2 columns=1,filter=100_118[0-5],mode=2,show_date=0,show_tools=0,border_thick=5
 143 } } }
 144 }}}
 145 
 146 Result: [[BR]]
 147  {{{
 148 #!Gallery2 columns=1,filter=100_118[0-7],mode=2,show_date=0,show_tools=0,border_thick=5
 149 }}}
 150 
 151 == other macro calls ==
 152 {{{
 153 { { {
 154 #!Gallery2 only_items=1,show_date=0
 155  * [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
 156 } } }
 157 }}}
 158 
 159 Result: [[BR]]
 160  {{{
 161 #!Gallery2 only_items=1,show_date=0
 162  * [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
 163 }}}
 164 
 165 == renew means always new thumbnails and webnails of selection ==
 166 {{{
 167 { { {
 168 #!Gallery2 only_items=1,show_date=0,show_tools=0,renew=1
 169  * [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
 170 } } }
 171 }}}
 172 
 173 Result: [[BR]]
 174  {{{
 175 #!Gallery2 only_items=1,show_date=0,renew=1
 176  * [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
 177 }}}
 178 
 179 == template_itemlist ==
 180 {{{
 181 { { {
 182 #!Gallery2 template_itemlist=1
 183 * [100_1185.JPG Bremen, SpaceCenter]
 184 } } }
 185 }}}
 186 
 187 Result: [[BR]]
 188  {{{
 189 #!Gallery2 template_itemlist=1
 190 * [100_1185.JPG Bremen, SpaceCenter]
 191 }}}
 192 
 193 == help to show Calling Sequence ==
 194  {{{
 195 { { {
 196 #!Gallery2 help=1
 197 } } }
 198 }}}
 199 
 200 Result: [[BR]]
 201 {{{
 202 #!Gallery2 help=1
 203 }}}
 204 
 205 
 206     PROCEDURE:
 207       ABOUT:
 208       While I have first implemented Gallery2 for something like photos I do use it at work since a while for
 209       output of model calculations too.
 210       Because of the possibility to share a standalone playable file to colleagues I have first decided to use
 211       fli or mpeg as output format for an image sequence. mpeg is not quite good for displaying our data
 212       and fli does sometimes eat a lot of cpu power. Both would make a lot of work getting them working
 213       on a non posix OS. For further development it would be better to have a python only version of Gallery2.
 214       That's the reason why I switch the sequence format to flash now. I do use the library of Matthias Kramm
 215       (http://www.swftools.org).
 216       
 217       HOWTO:
 218       Download some images to a page and start with the examples.
 219       Aliasing of the filenames are done by adding an itemlist, see example.
 220 
 221       NEEDS:
 222       This routine requires the Action macro gallery2image which is used to rotate or delete a
 223       selected image. The actual version is gallery2image-1.5.4-13.py.
 224       Only users which have the rights to delete are able to execute this action macro. 
 225       The icons of these are only shown if you have enough rights. 
 226       Furthermore it requires:
 227        * the PIL (Python Imaging Library).
 228        * the EXIF routine from http://home.cfl.rr.com/genecash/digital_camera.html
 229          (you need a modifed version you'll get it from the Gallery2 documentation page)
 230        * the SWF library from http://www.swftools.org
 231 
 232       Do install them to the usual python library path.
 233       
 234       REQUIRED IMAGES:
 235       You have to put them into wiki/mg/ dir. e.g.: http://moinmoin.wikiwikiweb.de/ParserMarket/Gallery2/ModernImages
 236       
 237       GENERAL:
 238       Please remove the Version number from the code!
 239 
 240       If you want to upload many files at once please look on MoinMoin versions less 1.5.0
 241       at FeatureRequests/UploadMultipleAttachmentFiles/RulesForUnzip
 242       
 243       With many images you can get in trouble by the SurgeProtection for attachment. Then you have to adjust the parameters see HelpOnConfiguration/SurgeProtection. 
 244       
 245       RESTRICTIONS:
 246       If you rotate an image at the moment the exif is destroyed. PIL ignores the exif header.
 247       This is not a quite big problem normally files with an EXIF header are right rotated.
 248       
 249       HISTORY:
 250       While recognizing how to write MiniPage I got the idea to write a Gallery Parser.
 251       We have used in our wikis in the past the Gallery macro of SimonRyan.
 252       I have tried to modify it a bit to change it for 1.3 but my python skills weren't enough
 253       or it was easier to write it completly new.
 254       So this one shows now a way how a Gallery could be used by the parser and an action Macro.
 255       Probably it is a good example for others who like to know how to do this
 256 
 257       OUTLOOK:
 258       Dependent on Matthias Kramm's python interface development the webnails could be exchanged to a
 259       flash animation with action controls. That will ommit the javascript slide show and will give less files.
 260       swftools is able to do this by now but that will need an os.system call. At the moment I like to avoid this.
 261       If you are interested the command is swfcombine -o output.swf movie_control.swf viewport=input.swf.
 262       It is still in the code but commented off. movie_control.swf embbeds the controls 24 pixels above the flash so it's a good idea to resize the flash by the -X and -Y option.
 263 
 264     MODIFICATION HISTORY:
 265         Version 1.3.3.-1
 266         @copyright: 2005 by Reimar Bauer (R.Bauer@fz-juelich.de)
 267         @license: GNU GPL, see COPYING for details.
 268         2005-03-26: Version 1.3.3-2 keyword renew added
 269                     creation of thumbnails and webnails in two calls splitted
 270                     Version 1.3.3-3 bug fixed if itemlist is given to describe only some of the images
 271                                     but only_items is not set to 1
 272                                     Example code changed
 273         2005-03-27: Version 1.3.3-4 Action macro added and the form to call it. User which have rights to delete
 274                                     could use the functions of gallery2Image.
 275         2005-08-03: Version 1.3.3-5 theme path for icons corrected and a platform independent path joining
 276                                     os.unlink removed as suggested by CraigJohnson
 277                                     sort_by_name is default if not only_items is 1
 278                                     optional sort_by_date could be used
 279                                     keyword template_itemlist added 
 280                                     keyword help added
 281                                     extra frame by mode=2 removed 
 282         2005-08-06: Version 1.3.5-6 slideshow mode added
 283                                     keyword image_for_webnail added
 284         2005-08-13: Version 1.3.5-7 syntax changed from GET to POST
 285                                     forms instead of links
 286                                     filenames from images submitted to gallery2image too
 287                                     new keyword sort_by_alias
 288                                     internal code clean up
 289                                     this version needs: gallery2image-1.3.5-5.py
 290         2005-08-14: Version 1.3.5-8 (TW) cleanup                                    
 291         2005-08-14: Version 1.3.5-9 html code for tables changed
 292                                     because of the ugly extra space of form elements
 293                                     div tag removed so now we use the page style
 294                                     slide show action goes to right webnail now
 295                                     this version needs: gallery2image-1.3.5-5.py
 296        2005-08-17: Version 1.3.5-10 html code separated in functions     
 297                                     structure of code changed, now you see the thumbnails after creation
 298                                     bug removed if quote is given but file does not exist
 299        2005-09-02: Version 1.3.5-11 keyword album, album_name and front_image added          
 300                                     image urls changed to complete server url      
 301        2005-11-12: Version 1.3.5-12 bug fixed for image_for_webnail=1            
 302                                     bug fixed at last cell table end tr instead of td
 303                                     bug fixed don't render a filename as WikiName
 304                                     bug fixed " is allowed in alias name
 305                                     bug fixed ' is allowed in alias name
 306                                     bug fixed linebreak by a space in alias  
 307                                     not quite a bug but makes it very difficult to code in 
 308                                     gallery2image so additional id removed in alias name
 309       2005-11-17: Version 1.3.5-13  implementation of sequence video clips at first step for posix only 
 310                                     sequence_type could be used to ommit the autoselection
 311                                     fli/flc files are used for gif and png files,  mpeg files for
 312                                     jpeg files. Duration on both is 1 image/second 
 313                                     feature added of recognising the right url pattern (http opr https)
 314       
 315  
 316                                     
 317      Version 1.5.4-16 2006-08-02 based on 1.3.5-13                    
 318      FlorianFesti: major changes    more flexible but better aligned layout
 319                                     better support for border_width=0              
 320                                     use of cfg.url_prefix insted of hard coding /wiki
 321                                          
 322      ReimarBauer:                   PEP8 style
 323                                     mode2 changed to Florians style too
 324                                     some other changes to get things compatible to previous versions
 325                                     flash (swf) format is used as sequence format
 326                                     keyword sequence_fps added
 327                                     keyword eo_info added
 328                                     EXIF.py moved to python lib 
 329                                        used the version of StigIversen
 330                                        
 331                                     file names of webnails and thumbnails does now have a prefix of tmp.   
 332                                     direct serving of webnails and thumbnails is possible but not default
 333                                        You have to set the var document_root in your wikiconfig.py to the absolute path of
 334                                        the wiki alias. For the default installation it is document_root = '/usr/share/moin/htdocs'
 335                                        Using this method MoinMoin can't use acls for the webnails and thumbnails.
 336                                        
 337                                    
 338 """
 339 Dependencies = ['time'] # do not cache
 340 
 341 from MoinMoin.action import AttachFile
 342 from MoinMoin import wikiutil, config
 343 from MoinMoin.Page import Page
 344 
 345 import os, re, sys, Image, StringIO, codecs
 346 from random import randint
 347 
 348 try:
 349     import EXIF
 350 except ImportError:
 351     EXIF = None
 352 
 353 try:
 354     import SWF
 355 except ImportError:
 356     SWF = None
 357 
 358 
 359 from MoinMoin.parser import wiki
 360 
 361 class Parser:
 362 
 363     def __init__(self, raw, request, **kw):
 364         self.sort_by_date = '0'
 365         self.sort_by_name = '1'
 366         self.sort_by_alias = '0'
 367         self.album = '0'
 368         self.album_name = 'album'
 369         self.front_image = ''
 370         self.template_itemlist = '0'
 371         self.reverse_sort = '0'
 372         self.border_thick = '1'
 373         self.columns = '4'
 374         self.filter = '.'
 375         self.mode = '1'
 376         self.help = '0'
 377         self.show_text = '1'
 378         self.show_date = '1'
 379         self.show_tools = '1'
 380         self.only_items = '0'
 381         self.image_for_webnail = '0'
 382         self.renew = '0'
 383         self.thumbnail_width = '128'
 384         self.webnail_width = '640'
 385         self.text_width = '140'
 386         self.sequence_name = ''
 387         self.sequence_fps = '1'
 388         self.eo_info = '0'
 389 
 390         for arg in kw.get('format_args', '').split(','):
 391 
 392             if arg.find('=') > -1:
 393                 key, value = arg.split('=')
 394                 setattr(self, key, wikiutil.escape(value.strip(), quote=1))
 395 
 396         self.width = str(int(self.thumbnail_width) +
 397                          int(self.text_width))
 398 
 399         self.raw = raw
 400         self.request = request
 401         self.form = request.form
 402         self._ = request.getText
 403 
 404         self.outer_table_style = ' border="%s"' % self.border_thick
 405         self.inner_table_style = ' style="border-style:none; margin:10px;"'
 406         self.td_style = ' align="center" style="padding:0; margin:2px 2px; border-style:none"'
 407 
 408     def images2swf(request, images, swf_filename, swf_fps, description, exif_date):
 409     ## this code is based on
 410     ## http://www.quiss.org/swftools/python/jpeg2swf_exif.py
 411     ## by Matthias Kramm
 412     ##
 413     ## Thanks Matthias
 414 
 415         xmax, ymax = 0, 0
 416         depth = 1
 417         SWF.verbose(0)
 418         # verbose is not used everybody
 419         swf = SWF.create(version=6, bbox=(0, 0, 0, 0), fps=float(swf_fps))
 420 
 421         i = 0
 422         for filename in images:
 423             pic = Image.open(filename)
 424             pic.load()
 425 
 426             width, height = pic.size
 427             if width > xmax: xmax = width
 428             if height > ymax: ymax = height
 429 
 430             pic = pic.convert("RGBA")
 431             image = SWF.Image(pic.im)
 432 
 433             swf.tags += image
 434             shape = SWF.ImageShape(image)
 435             swf.tags += shape
 436             swf.tags += SWF.PlaceObject(shape, depth=depth)
 437             depth += 1
 438             swf.tags += SWF.ShowFrame()
 439 
 440             i += 1
 441 
 442         swf.bbox = (0, 0, xmax, ymax)
 443         swf.save(swf_filename)
 444 
 445         return xmax, ymax
 446 
 447     def show_tools_restricted(self, this_target):
 448         if not self.request.user.may.delete(self.pagename):
 449             return ''
 450 
 451         return '''
 452         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 453           <td%(style)s>
 454             <input type="hidden" name="action" value="gallery2image">
 455             <input type="hidden" name="do" value="RL">
 456             <input type="hidden" name="target" value="%(this_target)s">
 457             <input type="image" value="submit" src="%(htdocs)s/img/to_right.png" title="rotate to left">
 458           </td>
 459         </form>
 460         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 461           <td%(style)s>
 462             <input type="hidden" name="action" value="gallery2image">
 463             <input type="hidden" name="do" value="RR">
 464             <input type="hidden" name="target" value="%(this_target)s">
 465             <input type="image"  value="submit" src="%(htdocs)s/img/to_left.png" title="rotate to right" >
 466           </td>
 467         </form>
 468         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 469           <td%(style)s>
 470             <input type="hidden" name="action" value="gallery2image">
 471             <input type="hidden" name="do" value="RM">
 472             <input type="hidden" name="target" value="%(this_target)s">
 473             <input type="image" value="submit" src="%(htdocs)s/img/to_bak.png" title="move to bak" >
 474            </td>
 475         </form>''' % {
 476             'baseurl': self.request.getBaseURL(),
 477             'style': self.td_style,
 478             'htdocs': self.request.cfg.url_prefix,
 479             "pagename": self.quoted_pagename,
 480             "this_target": this_target}
 481 
 482     def tools_html(self, idx):
 483         this_image = self.full[idx]
 484 
 485         text = '''
 486             <TABLE align="center" width="%(thumbnail_width)s"%(tablestyle)s>
 487                 <TR>
 488                     <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 489                         <td%(style)s>
 490                             <input type="hidden" name="action" value="AttachFile">
 491                             <input type="hidden" name="do" value="get">
 492                             <input type="hidden" name="target" value='%(this_target)s'>
 493                             <input type="image" value="submit" src="%(htdocs)s/img/to_full.png" title="load image">
 494                         </td>
 495                     </form>
 496                     <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 497                         <td%(style)s>
 498                             <input type="hidden" name="action" value="gallery2image">
 499                             <input type="hidden" name="do" value="VS">
 500                             <input type="hidden" name="full" value='%(full)s'>
 501                             <input type="hidden" name="alias" value='%(description)s'>
 502                             <input type="hidden" name="target" value='%(target)s'>
 503                             <input type="hidden" name="exif_date" value='%(exif_date)s'>
 504                             <input type="image" value="submit" src="%(htdocs)s/img/to_slide.png" title="slide_show" >
 505                        </td>
 506                     </form>
 507                     %(show_tools_restricted)s
 508                 </TR>
 509             </TABLE>'''   % {
 510             "baseurl": self.request.getScriptname(),
 511             "pagename": self.quoted_pagename,
 512             "htdocs": self.request.cfg.url_prefix,
 513             "tablestyle": self.inner_table_style,
 514             "style": self.td_style,
 515             "thumbnail_width": self.thumbnail_width,
 516             "full": self.full[idx] + ',' + ','.join(self.full),
 517             "description": self.description[idx] + '!,!' + '!,!'.join(self.description),
 518             "exif_date": self.to_htmltext(self.exif_date[idx] + ',' +
 519                                          ','.join(self.exif_date)),
 520             "target": self.webimg[idx] + ',' + ','.join(self.webimg),
 521             "this_target": self.full[idx],
 522             "thumbnail": "%s%s" % (self.static_url, self.thumb[idx]),
 523             "show_tools_restricted":self.show_tools_restricted(this_image)
 524             }
 525 
 526         return text
 527 
 528     def show_alias_mode2(self, idx):
 529        if self.show_text == '1':
 530            return '''
 531             <td valign="top" width="%(text_width)s" %(style)s>
 532            %(this_alias)s
 533         </td>''' % {
 534         "this_alias":self.description[idx],
 535         "text_width":self.text_width,
 536         "style": ' align="left" style="padding:0px; margin:2px 2px; border-style:none"'}
 537        else:
 538           return ''
 539 
 540     def show_date_mode2(self, idx):
 541        if self.show_date == '1':
 542            return '''
 543                   <td%(style)s><p>%(this_exif_date)s</p></td>''' % {
 544                   "style": self.td_style,
 545                   "this_exif_date": self.to_htmltext(self.exif_date[idx]) }
 546        else:
 547             return ''
 548 
 549     def show_tools_mode2(self, idx):
 550         if self.show_tools == '1':
 551             return "<td align=""center""%(style)s> %(tools)s </td>" % {
 552                 "style":self.td_style,
 553                 "tools":self.tools_html(idx)}
 554         else:
 555             return ''
 556 
 557     def mode2_html(self, idx):
 558         text = '''
 559         <tr valign="center">
 560         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 561             <td align="center" valign="center" width="%(thumbnail_width)s"
 562             %(tdstyle)s>
 563                 <input type="hidden" name="action" value="gallery2image">
 564                 <input type="hidden" name="do" value="VS">
 565                 <input type="hidden" name="full" value='%(full)s'>
 566                 <input type="hidden" name="alias" value='%(description)s'>
 567                 <input type="hidden" name="exif_date" value='%(exif_date)s'>
 568                 <input type="hidden" name="target" value='%(target)s'>
 569                 <input type="image" value="submit" src="%(thumbnail)s">
 570             </td>
 571         </form>
 572             %(alias_html)s 
 573     </tr>
 574     <tr>%(tools_html)s%(date_html)s</tr>''' % {
 575      "tdstyle": self.td_style,
 576      "baseurl": self.request.getScriptname(),
 577      "pagename": self.quoted_pagename,
 578      "thumbnail_width": self.thumbnail_width,
 579      "full": self.full[idx] + ',' + ','.join(self.full),
 580      "description": self.description[idx] + '!,!' + '!,!'.join(self.description),
 581      "exif_date": self.to_htmltext(self.exif_date[idx] + ',' +
 582                                   ','.join(self.exif_date)),
 583      "target": self.webimg[idx] + ',' + ','.join(self.webimg),
 584      "thumbnail": "%s%s" % (self.static_url, self.thumb[idx]),
 585      "tools_html": self.show_tools_mode2(idx),
 586      "date_html": self.show_date_mode2(idx),
 587      "alias_html": self.show_alias_mode2(idx)
 588      }
 589 
 590         return text
 591 
 592     def show_tools_mode1(self, idx):
 593         if self.show_tools == '1':
 594             text = "<tr><td align=""center""%(style)s>%(tools)s </td></tr>" % {
 595                 "style":self.td_style,
 596                 "tools":self.tools_html(idx)}
 597         else:
 598             text = ''
 599         return text
 600 
 601     def show_date_mode1(self, idx):
 602        if self.show_date == '1':
 603            return '''
 604         <TR>
 605         <td%(style)s>%(this_exif_date)s</td>
 606     </TR>''' % {
 607     "style":self.td_style,
 608     "this_exif_date": self.to_htmltext(self.exif_date[idx])}
 609        else:
 610            return ''
 611 
 612     def show_alias_mode1(self, idx):
 613        if self.show_text == '1':
 614            return '''
 615         <TR>
 616         <td width="%(thumbnail_width)s" %(style)s> %(this_alias)s</td>
 617     </TR>''' % {
 618     "thumbnail_width": self.thumbnail_width,
 619     "style": ' align="left" style="padding:0em; margin:2px 2px; border-style:none"',
 620     "this_alias": self.description[idx]}
 621        else:
 622            return ''
 623 
 624     def mode1_html(self, idx):
 625         text = '''
 626     <table width="%(thumbnail_width)s" align="center" valign="center"%(style)s>
 627     <TR align="center" valign="center">
 628         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 629             <td align="center" valign="middle" width="%(thumbnail_width)s"
 630             %(tdstyle)s>
 631                 <input type="hidden" name="action" value="gallery2image">
 632                 <input type="hidden" name="do" value="VS">
 633                 <input type="hidden" name="full" value='%(full)s'>
 634                 <input type="hidden" name="alias" value='%(description)s'>
 635                 <input type="hidden" name="exif_date" value='%(exif_date)s'>
 636                 <input type="hidden" name="target" value='%(target)s'>
 637                 <input type="image" value="submit" src="%(thumbnail)s" >
 638             </td>
 639         </form>
 640     </TR>
 641       %(alias_html)s
 642       %(date_html)s
 643       %(tools_html)s
 644 </table>'''%       {
 645      "tdstyle": self.td_style,
 646      "style": self.inner_table_style,
 647      "baseurl": self.request.getScriptname(),
 648      "pagename": self.quoted_pagename,
 649      "full": self.full[idx] + ',' + ','.join(self.full),
 650      "description": self.description[idx] + '!,!' + '!,!'.join(self.description),
 651      "exif_date": self.to_htmltext(self.exif_date[idx] + ',' +
 652                                   ','.join(self.exif_date)),
 653      "target": self.webimg[idx] + ',' + ','.join(self.webimg),
 654      "thumbnail": "%s%s" % (self.static_url, self.thumb[idx]),
 655      "thumbnail_width": self.thumbnail_width,
 656      "tools_html": self.show_tools_mode1(idx),
 657      "date_html": self.show_date_mode1(idx),
 658      "alias_html": self.show_alias_mode1(idx)
 659      }
 660 
 661         return text
 662 
 663     def get_files(self, path, files, quotes):
 664         self.web = []
 665         self.full = []
 666         self.thumb = []
 667         self.exif_date = []
 668         self.imgtype = []
 669         self.description = []
 670 
 671         ddict = {}
 672         n = len(quotes['image'])
 673         if n > 0:
 674             i = 0
 675             for txt in quotes['image']:
 676                 ddict[txt] = quotes['alias'][i]
 677                 i += 1
 678 
 679         self.video_type = 'swf'
 680         self.source_type = ''
 681         for attfile in files:
 682             # only files not thumb or webnails
 683             if not attfile.startswith('tmp.') and attfile.find('thumbnail_') == -1 and attfile.find('webnail_') == -1:
 684             #previous naming left for compatibility
 685                 # only images
 686                 if wikiutil.isPicture(attfile):
 687                     self.description.append(ddict.get(attfile, attfile))
 688                     self.full.append(attfile)
 689 
 690                     fname, ext = os.path.splitext(attfile)
 691                     if ext in ('.gif', '.png'):
 692                         self.imgtype.append('PNG')
 693                         webnail = 'tmp.webnail_%s.png' % fname
 694                         thumbfile = 'tmp.thumbnail_%s.png' % fname
 695                         video_type = 'swf'
 696                         source_type = ext[1:]
 697                     else:
 698                         self.imgtype.append("JPEG")
 699                         webnail = 'tmp.webnail_%s.jpg' % fname
 700                         thumbfile = 'tmp.thumbnail_%s.jpg' % fname
 701                         video_type = 'swf'
 702                         source_type = 'jpg'
 703 
 704                     infile = os.path.join(path, attfile)
 705                     if os.path.exists(infile):
 706                          self.web.append(webnail)
 707                          self.thumb.append(thumbfile)
 708 
 709 
 710                     f = open(infile, 'rb')
 711                     tags = EXIF.process_file(f, 'DateTimeOriginal')
 712                     f.close()
 713                     if tags.has_key('EXIF DateTimeOriginal'):
 714                         date = str(tags['EXIF DateTimeOriginal'])
 715                         date = date.replace(':', '-', 2)
 716                     else:
 717                         date = '--'
 718 
 719                     self.exif_date.append(date)
 720 
 721 
 722     def to_htmltext(self, text):
 723         if text.find ("'"):
 724             text = text.split("'")
 725             text = '&#39;'.join(text)
 726         return text
 727 
 728     def to_wikiname(self, formatter, text):
 729         ##taken from MiniPage
 730         out = StringIO.StringIO()
 731         self.request.redirect(out)
 732         wikiizer = wiki.Parser(text.strip(), self.request)
 733         wikiizer.format(formatter)
 734         result = out.getvalue()
 735         self.request.redirect()
 736         del out
 737 
 738         result = result.replace('<a id="line-1"></a>', '')
 739         result = result.replace('<p>', '')
 740         result = result.replace('</p>', '')
 741         result = result.strip()
 742         return result
 743 
 744 
 745     def get_quotes(self, formatter):
 746         quotes = self.raw.split('\n')
 747         quotes = [quote.strip() for quote in quotes]
 748         quotes = [quote[2:] for quote in quotes if quote.startswith('* ')]
 749 
 750         image = []
 751         text = []
 752 
 753         for line in quotes:
 754             im, na = line[1:-1].split(' ', 1)
 755             na = na.strip()
 756             na = self.to_htmltext(na)
 757             na = self.to_wikiname(formatter, na)
 758             text.append(na)
 759             image.append(im.strip())
 760 
 761         return {
 762             'alias': text,
 763             'image': image,
 764         }
 765 
 766     def print_help(self):
 767         self.request.write('''
 768 <br>
 769 {{{<br>
 770 #!Gallery2 [columns=columns],[filter=filter],[mode=mode],<br>
 771            [show_text=show_text],[show_date=show_date], [show_tools=show_tools],<br>
 772            [sort_by_name=sort_by_name],[sort_by_date=sort_by_date],[sort_by_alias=sort_by_alias]<br>
 773            [reverse_sort=reverse_sort],<br>
 774            [only_items=only_items],[template_itemlist=template_itemlist],<br>
 775            [album=album],[album_name=album_name],[front_image=front_image],<br>
 776            [thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],<br>
 777            [image_for_webnail=image_for_webnail],<br>
 778            [sequence_name=sequence_name],[sequence_fps=sequence_fps]<br>
 779            [border_thick=border_thick],[renew=renew],[help=help]<br>
 780  * [image1.jpg alias]<br>
 781  * [image2.jpg alias]<br>
 782 }}}<br>''')
 783 
 784     def format(self, formatter):
 785         if self.help == '1':
 786             self.print_help()
 787             return
 788         Dict = {}
 789         quotes = self.get_quotes(formatter)
 790         current_pagename = formatter.page.page_name
 791         self.pagename = current_pagename
 792         self.quoted_pagename = wikiutil.quoteWikinameURL(self.pagename)
 793         attachment_path = AttachFile.getAttachDir(self.request, current_pagename, create=1)
 794 
 795         if hasattr(self.request.cfg, 'document_root'):
 796 
 797             self.static_path = "%(dir)s/tmp/Gallery2%(wiki_name)s/%(pagename)s" % {
 798                  "wiki_name": self.request.getScriptname(),
 799                  "pagename": self.pagename,
 800                  "dir": self.request.cfg.document_root,
 801                  }
 802             if os.path.exists(self.static_path) == 0:
 803                  os.makedirs(self.static_path)
 804 
 805             self.static_url = "%(prefix)s/tmp/Gallery2%(wiki_name)s/%(pagename)s/" % {
 806                  "prefix": self.request.cfg.url_prefix,
 807                  "wiki_name": self.request.getScriptname(),
 808                  "pagename": self.pagename,
 809                  }
 810         else:
 811             self.static_path = attachment_path
 812             self.static_url = AttachFile.getAttachUrl(self.pagename, '', self.request)
 813 
 814 
 815         if self.only_items == '1':
 816             all_files = quotes['image']
 817             result = []
 818             for attfile in all_files:
 819                 infile = os.path.join(attachment_path, attfile)
 820                 if os.path.exists(infile):
 821                    result.append(attfile)
 822             all_files = result
 823 
 824             if self.sort_by_alias == '1':
 825                 new_ordered_files = []
 826                 alias_text = quotes['alias']
 827 
 828                 i = 0
 829                 for attfile in all_files:
 830                     infile = os.path.join(attachment_path, attfile)
 831                     Dict[alias_text[i]] = attfile
 832                     i += 1
 833 
 834                 keys = Dict.keys()
 835                 keys.sort()
 836                 for txt in keys:
 837                     new_ordered_files.append(Dict[txt])
 838 
 839                 all_files = new_ordered_files
 840                 Dict.clear()
 841 
 842         else:
 843             all_files = os.listdir(attachment_path)
 844 
 845 
 846         if self.filter != '.':
 847             result = []
 848             for test in all_files:
 849                 if re.match(self.filter, test):
 850                   result.append(test)
 851 
 852             all_files = result
 853 
 854         if not all_files:
 855             self.request.write("<br><br><h1>No matching image file found!</h1>")
 856             return
 857 
 858         if self.sort_by_name == '1' and self.only_items == '0':
 859             all_files.sort()
 860 
 861         if self.sort_by_date == '1':
 862            for attfile in all_files:
 863                infile = os.path.join(attachment_path, attfile)
 864                ft_file = "%s%s" % (str(os.path.getmtime(infile)), str(randint(0, 65535)))
 865                Dict[ft_file] = attfile
 866 
 867            keys = Dict.keys()
 868            keys.sort()
 869            file_mdate = []
 870            for txt in keys:
 871                file_mdate.append(Dict[txt])
 872            all_files = file_mdate
 873            Dict.clear()
 874 
 875         if self.reverse_sort == '1':
 876              all_files.reverse()
 877 
 878         cells = []
 879         cell_name = []
 880         img = []
 881 
 882         self.get_files(attachment_path, all_files, quotes)
 883 
 884         if self.template_itemlist == '1':
 885             self.request.write('Copy the following listitems into the script. Replace alias with the label you want. Afterwards disable template_itemlist by setting it to 0:<BR>')
 886             for attfile in self.full:
 887                 self.request.write(' * [%(attfile)s %(date)s]<br>\n' % {
 888                                    'attfile': attfile,
 889                                    'date': 'alias'
 890                                     })
 891 
 892         i = 0
 893         z = 1
 894         cols = int(self.columns)
 895 
 896         n = len(self.full)
 897         if  self.album == '0':
 898             self.request.write("<table%s>" % self.outer_table_style)
 899             if self.mode == '1' or cols > 1:
 900                 self.request.write('<TR valign="top">')
 901                 self.request.write('<TD%s>' % self.td_style)
 902 
 903 
 904         if self.album == '1':
 905             if self.front_image == '':
 906                 front_image = self.full[0]
 907             else:
 908                 front_image = self.front_image
 909             ii = 0
 910             for tst in self.full:
 911                 if tst == front_image:
 912                     break
 913                 ii += 1
 914 
 915         for attfile in self.full:
 916             if  self.album == '1':
 917                 if tst == front_image:
 918                    i = ii
 919 
 920             this_description = self.description[i]
 921             this_exif_date = self.exif_date[i]
 922             this_webnail = self.web[i]
 923             this_imgtype = self.imgtype[i]
 924             this_thumbfile = self.thumb[i]
 925 
 926             thumbf = os.path.join(self.static_path, this_thumbfile)
 927             webf = os.path.join(self.static_path, this_webnail)
 928 
 929             if self.renew == '1':
 930                 if os.path.exists(thumbf):
 931                    os.unlink(thumbf)
 932                 if os.path.exists(webf):
 933                    os.unlink(webf)
 934 
 935             if not os.path.exists(webf) or not os.path.exists(thumbf):
 936                 infile = os.path.join(attachment_path, attfile)
 937                 im = Image.open(infile)
 938 
 939                 if not os.path.exists(webf):
 940                     im.thumbnail((int(self.webnail_width), int(self.webnail_width)), Image.ANTIALIAS)
 941                     if self.image_for_webnail == '1':
 942                        os.link(os.path.join(attachment_path, attfile), webf)
 943                     else:
 944                        im.save(webf, this_imgtype)
 945                 if not os.path.exists(thumbf):
 946                     im.thumbnail(((int(self.thumbnail_width)), ((int(self.thumbnail_width)))),
 947                                    Image.ANTIALIAS)
 948                     im.save(thumbf, this_imgtype)
 949 
 950             if self.image_for_webnail == '1':
 951                  this_webnailimg = attfile
 952                  self.webimg = self.full
 953             else:
 954                  this_webnailimg = this_webnail
 955                  self.webimg = self.web
 956 
 957             if self.mode == '1':
 958                 text = self.mode1_html(i)
 959                 self.request.write(''.join(text))
 960 
 961             if self.mode == '2':
 962                 text = self.mode2_html(i)
 963                 if cols > 1: self.request.write('<table valign="bottom">')
 964                 self.request.write(''.join(text))
 965                 if cols > 1: self.request.write('</table>')
 966 
 967             if self.mode == '1' or cols > 1:
 968                 if self.album == '0':
 969                     if  z < cols:
 970                         self.request.write('</TD>')
 971                         if z < n and  i < n - 1:
 972                             self.request.write('<TD%s>' % self.td_style)
 973                         if i == n - 1:
 974                             self.request.write('</TR>')
 975                     else:
 976                         self.request.write('</TD>')
 977                         self.request.write('</TR>')
 978                         if i < n - 1:
 979                             self.request.write('<TR valign="top">')
 980                             self.request.write('<TD%s>' % self.td_style)
 981 
 982             i += 1
 983             z += 1
 984             if z > cols:
 985                 z = 1
 986 
 987             if self.album == '1':
 988                 self.request.write("%(n)s images (%(album_name)s)" % {"n": str(n), "album_name": self.album_name})
 989                 break
 990 
 991         if self.album == '0':
 992             if i < n:
 993                 self.request.write('</TD>')
 994                 self.request.write('</TR>')
 995             self.request.write('</table>')
 996 
 997 
 998         if self.sequence_name != '':
 999             video_file = "%(file)s.%(ext)s" % {
1000                  "file": os.path.join(attachment_path, self.sequence_name),
1001                  "ext": 'swf'}
1002             if self.renew == '1':
1003                if os.path.exists(video_file):
1004                   os.unlink(video_file)
1005 
1006             cmd = ''
1007             if float(self.sequence_fps) < 1:
1008                 fps = 1
1009             else:
1010                 fps = round(float(self.sequence_fps))
1011 
1012             f_list = []
1013             for attfile in self.web:
1014                 file = os.path.join(self.static_path, attfile)
1015                 if os.path.exists(file):
1016                    f_list.append(file)
1017 
1018             if not os.path.exists(video_file):
1019                 width, height = self.images2swf(f_list, video_file, fps, self.description, self.exif_date)
1020             else:
1021                 swf = SWF.load(video_file)
1022                 for tag in swf.tags:
1023                     if tag.isImage():
1024                        width, height = tag.image.size
1025                        break
1026 
1027             if os.path.exists(video_file):
1028                   dict = {}
1029                   dict['src'] = AttachFile.getAttachUrl(current_pagename, '%(file)s.%(videotype)s'  % {
1030                      'file': self.sequence_name,
1031                      'videotype': 'swf',
1032                      }, self.request)
1033 
1034                   image_link = '%(file)s.%(videotype)s' % {'file':self.sequence_name, 'videotype': 'swf'}
1035                   if  self.eo_info == '1':
1036                       eo = "Or embed it into your wiki page by [[EmbedObject(%(file)s,width=%(width)s,height=%(height)s)]]." % {
1037                            'file': image_link,
1038                            'width': str(width),
1039                            'height': str(height)}
1040                   else:
1041                       eo = ''
1042 
1043                   self.request.write('<P>')
1044                   text = formatter.url(1, dict['src'] ) + image_link + formatter.url(0)
1045                   self.request.write('Download this image sequence %(text)s for your archive. %(EO)s' % {
1046                        'text': text,
1047                        'EO': eo
1048                        })
1049                   self.request.write('</P>')

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.
  • [get | view] (2006-08-06 08:57:54, 41.8 KB) [[attachment:EXIF.py]]
  • [get | view] (2005-03-24 20:14:37, 10.6 KB) [[attachment:Gallery2-1.3.3-1.py]]
  • [get | view] (2005-03-26 08:39:13, 11.6 KB) [[attachment:Gallery2-1.3.3-2.py]]
  • [get | view] (2005-03-26 12:41:49, 13.1 KB) [[attachment:Gallery2-1.3.3-3.py]]
  • [get | view] (2005-03-27 20:23:01, 19.0 KB) [[attachment:Gallery2-1.3.3-4.py]]
  • [get | view] (2005-08-03 19:30:10, 23.2 KB) [[attachment:Gallery2-1.3.3-5.py]]
  • [get | view] (2005-08-18 07:58:38, 31.9 KB) [[attachment:Gallery2-1.3.5-10.py]]
  • [get | view] (2005-09-02 19:55:13, 34.1 KB) [[attachment:Gallery2-1.3.5-11.py]]
  • [get | view] (2005-11-13 18:09:11, 35.4 KB) [[attachment:Gallery2-1.3.5-12.py]]
  • [get | view] (2005-11-18 20:13:04, 46.2 KB) [[attachment:Gallery2-1.3.5-13.py]]
  • [get | view] (2005-12-03 15:33:06, 46.6 KB) [[attachment:Gallery2-1.3.5-14.py]]
  • [get | view] (2006-01-01 09:20:19, 43.3 KB) [[attachment:Gallery2-1.3.5-15.py]]
  • [get | view] (2005-08-07 15:46:28, 26.9 KB) [[attachment:Gallery2-1.3.5-6.py]]
  • [get | view] (2005-08-13 15:13:59, 28.7 KB) [[attachment:Gallery2-1.3.5-7.py]]
  • [get | view] (2005-08-14 13:02:00, 27.5 KB) [[attachment:Gallery2-1.3.5-8.py]]
  • [get | view] (2005-08-14 14:38:32, 28.7 KB) [[attachment:Gallery2-1.3.5-9.py]]
  • [get | view] (2006-08-06 08:45:47, 41.8 KB) [[attachment:Gallery2-1.5.4-16.py]]
  • [get | view] (2006-08-22 20:29:39, 42.0 KB) [[attachment:Gallery2-1.5.4-18.py]]
  • [get | view] (2006-08-06 08:57:36, 514.8 KB) [[attachment:example.swf]]
  • [get | view] (2005-08-17 18:10:27, 11.3 KB) [[attachment:gallery2image_test.py]]
  • [get | view] (2005-08-10 16:49:16, 1.3 KB) [[attachment:patchpullfromdir.diff]]
  • [get | view] (2006-08-17 16:32:50, 41.9 KB) [[attachment:text_x_gallery2-1.6.0-17.py]]
  • [get | view] (2006-08-22 20:23:06, 42.1 KB) [[attachment:text_x_gallery2-1.6.0-18.py]]
  • [get | view] (2008-02-06 10:08:05, 42.2 KB) [[attachment:text_x_gallery2-1.6.0-19.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.