Attachment 'text_x_gallery2-1.6.0-17.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     2006-08-11 1.6.0-17 RB ported to 1.6.0 dev alpha version
 338                                        
 339                                    
 340 """
 341 Dependencies = ['time'] # do not cache
 342 
 343 from MoinMoin.action import AttachFile
 344 from MoinMoin import wikiutil, config
 345 from MoinMoin.Page import Page
 346 
 347 import os, re, sys, Image, StringIO, codecs
 348 from random import randint
 349 
 350 try:
 351     import EXIF
 352 except ImportError:
 353     EXIF = None
 354 
 355 try:
 356     import SWF
 357 except ImportError:
 358     SWF = None
 359 
 360 
 361 from MoinMoin.parser import text_moin_wiki
 362 
 363 class Parser:
 364     extensions = '*'
 365     def __init__(self, raw, request, **kw):
 366         self.sort_by_date = '0'
 367         self.sort_by_name = '1'
 368         self.sort_by_alias = '0'
 369         self.album = '0'
 370         self.album_name = 'album'
 371         self.front_image = ''
 372         self.template_itemlist = '0'
 373         self.reverse_sort = '0'
 374         self.border_thick = '1'
 375         self.columns = '4'
 376         self.filter = '.'
 377         self.mode = '1'
 378         self.help = '0'
 379         self.show_text = '1'
 380         self.show_date = '1'
 381         self.show_tools = '1'
 382         self.only_items = '0'
 383         self.image_for_webnail = '0'
 384         self.renew = '0'
 385         self.thumbnail_width = '128'
 386         self.webnail_width = '640'
 387         self.text_width = '140'
 388         self.sequence_name = ''
 389         self.sequence_fps = '1'
 390         self.eo_info = '0'
 391 
 392         for arg in kw.get('format_args', '').split(','):
 393 
 394             if arg.find('=') > -1:
 395                 key, value = arg.split('=')
 396                 setattr(self, key, wikiutil.escape(value.strip(), quote=1))
 397 
 398         self.width = str(int(self.thumbnail_width) +
 399                          int(self.text_width))
 400 
 401         self.raw = raw
 402         self.request = request
 403         self.form = request.form
 404         self._ = request.getText
 405 
 406         self.outer_table_style = ' border="%s"' % self.border_thick
 407         self.inner_table_style = ' style="border-style:none; margin:10px;"'
 408         self.td_style = ' align="center" style="padding:0; margin:2px 2px; border-style:none"'
 409 
 410     def images2swf(request, images, swf_filename, swf_fps, description, exif_date):
 411     ## this code is based on
 412     ## http://www.quiss.org/swftools/python/jpeg2swf_exif.py
 413     ## by Matthias Kramm
 414     ##
 415     ## Thanks Matthias
 416 
 417         xmax, ymax = 0, 0
 418         depth = 1
 419         SWF.verbose(0)
 420         # verbose is not used everybody
 421         swf = SWF.create(version=6, bbox=(0, 0, 0, 0), fps=float(swf_fps))
 422 
 423         i = 0
 424         for filename in images:
 425             pic = Image.open(filename)
 426             pic.load()
 427 
 428             width, height = pic.size
 429             if width > xmax: xmax = width
 430             if height > ymax: ymax = height
 431 
 432             pic = pic.convert("RGBA")
 433             image = SWF.Image(pic.im)
 434 
 435             swf.tags += image
 436             shape = SWF.ImageShape(image)
 437             swf.tags += shape
 438             swf.tags += SWF.PlaceObject(shape, depth=depth)
 439             depth += 1
 440             swf.tags += SWF.ShowFrame()
 441 
 442             i += 1
 443 
 444         swf.bbox = (0, 0, xmax, ymax)
 445         swf.save(swf_filename)
 446 
 447         return xmax, ymax
 448 
 449     def show_tools_restricted(self, this_target):
 450         if not self.request.user.may.delete(self.pagename):
 451             return ''
 452 
 453         return '''
 454         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 455           <td%(style)s>
 456             <input type="hidden" name="action" value="gallery2image">
 457             <input type="hidden" name="do" value="RL">
 458             <input type="hidden" name="target" value="%(this_target)s">
 459             <input type="image" value="submit" src="%(htdocs)s/img/to_right.png" title="rotate to left">
 460           </td>
 461         </form>
 462         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 463           <td%(style)s>
 464             <input type="hidden" name="action" value="gallery2image">
 465             <input type="hidden" name="do" value="RR">
 466             <input type="hidden" name="target" value="%(this_target)s">
 467             <input type="image"  value="submit" src="%(htdocs)s/img/to_left.png" title="rotate to right" >
 468           </td>
 469         </form>
 470         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 471           <td%(style)s>
 472             <input type="hidden" name="action" value="gallery2image">
 473             <input type="hidden" name="do" value="RM">
 474             <input type="hidden" name="target" value="%(this_target)s">
 475             <input type="image" value="submit" src="%(htdocs)s/img/to_bak.png" title="move to bak" >
 476            </td>
 477         </form>''' % {
 478             'baseurl': self.request.getBaseURL(),
 479             'style': self.td_style,
 480             'htdocs': self.request.cfg.url_prefix,
 481             "pagename": self.quoted_pagename,
 482             "this_target": this_target}
 483 
 484     def tools_html(self, idx):
 485         this_image = self.full[idx]
 486 
 487         text = '''
 488             <TABLE align="center" width="%(thumbnail_width)s"%(tablestyle)s>
 489                 <TR>
 490                     <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 491                         <td%(style)s>
 492                             <input type="hidden" name="action" value="AttachFile">
 493                             <input type="hidden" name="do" value="get">
 494                             <input type="hidden" name="target" value='%(this_target)s'>
 495                             <input type="image" value="submit" src="%(htdocs)s/img/to_full.png" title="load image">
 496                         </td>
 497                     </form>
 498                     <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 499                         <td%(style)s>
 500                             <input type="hidden" name="action" value="gallery2image">
 501                             <input type="hidden" name="do" value="VS">
 502                             <input type="hidden" name="full" value='%(full)s'>
 503                             <input type="hidden" name="alias" value='%(description)s'>
 504                             <input type="hidden" name="target" value='%(target)s'>
 505                             <input type="hidden" name="exif_date" value='%(exif_date)s'>
 506                             <input type="image" value="submit" src="%(htdocs)s/img/to_slide.png" title="slide_show" >
 507                        </td>
 508                     </form>
 509                     %(show_tools_restricted)s
 510                 </TR>
 511             </TABLE>'''   % {
 512             "baseurl": self.request.getScriptname(),
 513             "pagename": self.quoted_pagename,
 514             "htdocs": self.request.cfg.url_prefix,
 515             "tablestyle": self.inner_table_style,
 516             "style": self.td_style,
 517             "thumbnail_width": self.thumbnail_width,
 518             "full": self.full[idx] + ',' + ','.join(self.full),
 519             "description": self.description[idx] + '!,!' + '!,!'.join(self.description),
 520             "exif_date": self.to_htmltext(self.exif_date[idx] + ',' +
 521                                          ','.join(self.exif_date)),
 522             "target": self.webimg[idx] + ',' + ','.join(self.webimg),
 523             "this_target": self.full[idx],
 524             "thumbnail": "%s%s" % (self.static_url, self.thumb[idx]),
 525             "show_tools_restricted":self.show_tools_restricted(this_image)
 526             }
 527 
 528         return text
 529 
 530     def show_alias_mode2(self, idx):
 531        if self.show_text == '1':
 532            return '''
 533             <td valign="top" width="%(text_width)s" %(style)s>
 534            %(this_alias)s
 535         </td>''' % {
 536         "this_alias":self.description[idx],
 537         "text_width":self.text_width,
 538         "style": ' align="left" style="padding:0px; margin:2px 2px; border-style:none"'}
 539        else:
 540           return ''
 541 
 542     def show_date_mode2(self, idx):
 543        if self.show_date == '1':
 544            return '''
 545                   <td%(style)s><p>%(this_exif_date)s</p></td>''' % {
 546                   "style": self.td_style,
 547                   "this_exif_date": self.to_htmltext(self.exif_date[idx]) }
 548        else:
 549             return ''
 550 
 551     def show_tools_mode2(self, idx):
 552         if self.show_tools == '1':
 553             return "<td align=""center""%(style)s> %(tools)s </td>" % {
 554                 "style":self.td_style,
 555                 "tools":self.tools_html(idx)}
 556         else:
 557             return ''
 558 
 559     def mode2_html(self, idx):
 560         text = '''
 561         <tr valign="center">
 562         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 563             <td align="center" valign="center" width="%(thumbnail_width)s"
 564             %(tdstyle)s>
 565                 <input type="hidden" name="action" value="gallery2image">
 566                 <input type="hidden" name="do" value="VS">
 567                 <input type="hidden" name="full" value='%(full)s'>
 568                 <input type="hidden" name="alias" value='%(description)s'>
 569                 <input type="hidden" name="exif_date" value='%(exif_date)s'>
 570                 <input type="hidden" name="target" value='%(target)s'>
 571                 <input type="image" value="submit" src="%(thumbnail)s">
 572             </td>
 573         </form>
 574             %(alias_html)s 
 575     </tr>
 576     <tr>%(tools_html)s%(date_html)s</tr>''' % {
 577      "tdstyle": self.td_style,
 578      "baseurl": self.request.getScriptname(),
 579      "pagename": self.quoted_pagename,
 580      "thumbnail_width": self.thumbnail_width,
 581      "full": self.full[idx] + ',' + ','.join(self.full),
 582      "description": self.description[idx] + '!,!' + '!,!'.join(self.description),
 583      "exif_date": self.to_htmltext(self.exif_date[idx] + ',' +
 584                                   ','.join(self.exif_date)),
 585      "target": self.webimg[idx] + ',' + ','.join(self.webimg),
 586      "thumbnail": "%s%s" % (self.static_url, self.thumb[idx]),
 587      "tools_html": self.show_tools_mode2(idx),
 588      "date_html": self.show_date_mode2(idx),
 589      "alias_html": self.show_alias_mode2(idx)
 590      }
 591 
 592         return text
 593 
 594     def show_tools_mode1(self, idx):
 595         if self.show_tools == '1':
 596             text = "<tr><td align=""center""%(style)s>%(tools)s </td></tr>" % {
 597                 "style":self.td_style,
 598                 "tools":self.tools_html(idx)}
 599         else:
 600             text = ''
 601         return text
 602 
 603     def show_date_mode1(self, idx):
 604        if self.show_date == '1':
 605            return '''
 606         <TR>
 607         <td%(style)s>%(this_exif_date)s</td>
 608     </TR>''' % {
 609     "style":self.td_style,
 610     "this_exif_date": self.to_htmltext(self.exif_date[idx])}
 611        else:
 612            return ''
 613 
 614     def show_alias_mode1(self, idx):
 615        if self.show_text == '1':
 616            return '''
 617         <TR>
 618         <td width="%(thumbnail_width)s" %(style)s> %(this_alias)s</td>
 619     </TR>''' % {
 620     "thumbnail_width": self.thumbnail_width,
 621     "style": ' align="left" style="padding:0em; margin:2px 2px; border-style:none"',
 622     "this_alias": self.description[idx]}
 623        else:
 624            return ''
 625 
 626     def mode1_html(self, idx):
 627         text = '''
 628     <table width="%(thumbnail_width)s" align="center" valign="center"%(style)s>
 629     <TR align="center" valign="center">
 630         <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 631             <td align="center" valign="middle" width="%(thumbnail_width)s"
 632             %(tdstyle)s>
 633                 <input type="hidden" name="action" value="gallery2image">
 634                 <input type="hidden" name="do" value="VS">
 635                 <input type="hidden" name="full" value='%(full)s'>
 636                 <input type="hidden" name="alias" value='%(description)s'>
 637                 <input type="hidden" name="exif_date" value='%(exif_date)s'>
 638                 <input type="hidden" name="target" value='%(target)s'>
 639                 <input type="image" value="submit" src="%(thumbnail)s" >
 640             </td>
 641         </form>
 642     </TR>
 643       %(alias_html)s
 644       %(date_html)s
 645       %(tools_html)s
 646 </table>'''%       {
 647      "tdstyle": self.td_style,
 648      "style": self.inner_table_style,
 649      "baseurl": self.request.getScriptname(),
 650      "pagename": self.quoted_pagename,
 651      "full": self.full[idx] + ',' + ','.join(self.full),
 652      "description": self.description[idx] + '!,!' + '!,!'.join(self.description),
 653      "exif_date": self.to_htmltext(self.exif_date[idx] + ',' +
 654                                   ','.join(self.exif_date)),
 655      "target": self.webimg[idx] + ',' + ','.join(self.webimg),
 656      "thumbnail": "%s%s" % (self.static_url, self.thumb[idx]),
 657      "thumbnail_width": self.thumbnail_width,
 658      "tools_html": self.show_tools_mode1(idx),
 659      "date_html": self.show_date_mode1(idx),
 660      "alias_html": self.show_alias_mode1(idx)
 661      }
 662 
 663         return text
 664 
 665     def get_files(self, path, files, quotes):
 666         self.web = []
 667         self.full = []
 668         self.thumb = []
 669         self.exif_date = []
 670         self.imgtype = []
 671         self.description = []
 672 
 673         ddict = {}
 674         n = len(quotes['image'])
 675         if n > 0:
 676             i = 0
 677             for txt in quotes['image']:
 678                 ddict[txt] = quotes['alias'][i]
 679                 i += 1
 680 
 681         self.video_type = 'swf'
 682         self.source_type = ''
 683         for attfile in files:
 684             # only files not thumb or webnails
 685             if not attfile.startswith('tmp.') and attfile.find('thumbnail_') == -1 and attfile.find('webnail_') == -1:
 686             #previous naming left for compatibility
 687                 # only images
 688                 if wikiutil.isPicture(attfile):
 689                     self.description.append(ddict.get(attfile, attfile))
 690                     self.full.append(attfile)
 691 
 692                     fname, ext = os.path.splitext(attfile)
 693                     if ext in ('.gif', '.png'):
 694                         self.imgtype.append('PNG')
 695                         webnail = 'tmp.webnail_%s.png' % fname
 696                         thumbfile = 'tmp.thumbnail_%s.png' % fname
 697                         video_type = 'swf'
 698                         source_type = ext[1:]
 699                     else:
 700                         self.imgtype.append("JPEG")
 701                         webnail = 'tmp.webnail_%s.jpg' % fname
 702                         thumbfile = 'tmp.thumbnail_%s.jpg' % fname
 703                         video_type = 'swf'
 704                         source_type = 'jpg'
 705 
 706                     infile = os.path.join(path, attfile)
 707                     if os.path.exists(infile):
 708                          self.web.append(webnail)
 709                          self.thumb.append(thumbfile)
 710 
 711 
 712                     f = open(infile, 'rb')
 713                     tags = EXIF.process_file(f, 'DateTimeOriginal')
 714                     f.close()
 715                     if tags.has_key('EXIF DateTimeOriginal'):
 716                         date = str(tags['EXIF DateTimeOriginal'])
 717                         date = date.replace(':', '-', 2)
 718                     else:
 719                         date = '--'
 720 
 721                     self.exif_date.append(date)
 722 
 723 
 724     def to_htmltext(self, text):
 725         if text.find ("'"):
 726             text = text.split("'")
 727             text = '&#39;'.join(text)
 728         return text
 729 
 730     def to_wikiname(self, formatter, text):
 731         ##taken from MiniPage
 732         out = StringIO.StringIO()
 733         self.request.redirect(out)
 734         wikiizer = text_moin_wiki.Parser(text.strip(), self.request)
 735         wikiizer.format(formatter)
 736         result = out.getvalue()
 737         self.request.redirect()
 738         del out
 739 
 740         result = result.replace('<a id="line-1"></a>', '')
 741         result = result.replace('<p>', '')
 742         result = result.replace('</p>', '')
 743         result = result.strip()
 744         return result
 745 
 746 
 747     def get_quotes(self, formatter):
 748         quotes = self.raw.split('\n')
 749         quotes = [quote.strip() for quote in quotes]
 750         quotes = [quote[2:] for quote in quotes if quote.startswith('* ')]
 751 
 752         image = []
 753         text = []
 754 
 755         for line in quotes:
 756             im, na = line[1:-1].split(' ', 1)
 757             na = na.strip()
 758             na = self.to_htmltext(na)
 759             na = self.to_wikiname(formatter, na)
 760             text.append(na)
 761             image.append(im.strip())
 762 
 763         return {
 764             'alias': text,
 765             'image': image,
 766         }
 767 
 768     def print_help(self):
 769         self.request.write('''
 770 <br>
 771 {{{<br>
 772 #!Gallery2 [columns=columns],[filter=filter],[mode=mode],<br>
 773            [show_text=show_text],[show_date=show_date], [show_tools=show_tools],<br>
 774            [sort_by_name=sort_by_name],[sort_by_date=sort_by_date],[sort_by_alias=sort_by_alias]<br>
 775            [reverse_sort=reverse_sort],<br>
 776            [only_items=only_items],[template_itemlist=template_itemlist],<br>
 777            [album=album],[album_name=album_name],[front_image=front_image],<br>
 778            [thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],<br>
 779            [image_for_webnail=image_for_webnail],<br>
 780            [sequence_name=sequence_name],[sequence_fps=sequence_fps]<br>
 781            [border_thick=border_thick],[renew=renew],[help=help]<br>
 782  * [image1.jpg alias]<br>
 783  * [image2.jpg alias]<br>
 784 }}}<br>''')
 785 
 786     def format(self, formatter):
 787         if self.help == '1':
 788             self.print_help()
 789             return
 790         Dict = {}
 791         quotes = self.get_quotes(formatter)
 792         current_pagename = formatter.page.page_name
 793         self.pagename = current_pagename
 794         self.quoted_pagename = wikiutil.quoteWikinameURL(self.pagename)
 795         attachment_path = AttachFile.getAttachDir(self.request, current_pagename, create=1)
 796 
 797         if hasattr(self.request.cfg, 'document_root'):
 798 
 799             self.static_path = "%(dir)s/tmp/Gallery2%(wiki_name)s/%(pagename)s" % {
 800                  "wiki_name": self.request.getScriptname(),
 801                  "pagename": self.pagename,
 802                  "dir": self.request.cfg.document_root,
 803                  }
 804             if os.path.exists(self.static_path) == 0:
 805                  os.makedirs(self.static_path)
 806 
 807             self.static_url = "%(prefix)s/tmp/Gallery2%(wiki_name)s/%(pagename)s/" % {
 808                  "prefix": self.request.cfg.url_prefix,
 809                  "wiki_name": self.request.getScriptname(),
 810                  "pagename": self.pagename,
 811                  }
 812         else:
 813             self.static_path = attachment_path
 814             self.static_url = AttachFile.getAttachUrl(self.pagename, '', self.request)
 815 
 816 
 817         if self.only_items == '1':
 818             all_files = quotes['image']
 819             result = []
 820             for attfile in all_files:
 821                 infile = os.path.join(attachment_path, attfile)
 822                 if os.path.exists(infile):
 823                    result.append(attfile)
 824             all_files = result
 825 
 826             if self.sort_by_alias == '1':
 827                 new_ordered_files = []
 828                 alias_text = quotes['alias']
 829 
 830                 i = 0
 831                 for attfile in all_files:
 832                     infile = os.path.join(attachment_path, attfile)
 833                     Dict[alias_text[i]] = attfile
 834                     i += 1
 835 
 836                 keys = Dict.keys()
 837                 keys.sort()
 838                 for txt in keys:
 839                     new_ordered_files.append(Dict[txt])
 840 
 841                 all_files = new_ordered_files
 842                 Dict.clear()
 843 
 844         else:
 845             all_files = os.listdir(attachment_path)
 846 
 847 
 848         if self.filter != '.':
 849             result = []
 850             for test in all_files:
 851                 if re.match(self.filter, test):
 852                   result.append(test)
 853 
 854             all_files = result
 855 
 856         if not all_files:
 857             self.request.write("<br><br><h1>No matching image file found!</h1>")
 858             return
 859 
 860         if self.sort_by_name == '1' and self.only_items == '0':
 861             all_files.sort()
 862 
 863         if self.sort_by_date == '1':
 864            for attfile in all_files:
 865                infile = os.path.join(attachment_path, attfile)
 866                ft_file = "%s%s" % (str(os.path.getmtime(infile)), str(randint(0, 65535)))
 867                Dict[ft_file] = attfile
 868 
 869            keys = Dict.keys()
 870            keys.sort()
 871            file_mdate = []
 872            for txt in keys:
 873                file_mdate.append(Dict[txt])
 874            all_files = file_mdate
 875            Dict.clear()
 876 
 877         if self.reverse_sort == '1':
 878              all_files.reverse()
 879 
 880         cells = []
 881         cell_name = []
 882         img = []
 883 
 884         self.get_files(attachment_path, all_files, quotes)
 885 
 886         if self.template_itemlist == '1':
 887             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>')
 888             for attfile in self.full:
 889                 self.request.write(' * [%(attfile)s %(date)s]<br>\n' % {
 890                                    'attfile': attfile,
 891                                    'date': 'alias'
 892                                     })
 893 
 894         i = 0
 895         z = 1
 896         cols = int(self.columns)
 897 
 898         n = len(self.full)
 899         if  self.album == '0':
 900             self.request.write("<table%s>" % self.outer_table_style)
 901             if self.mode == '1' or cols > 1:
 902                 self.request.write('<TR valign="top">')
 903                 self.request.write('<TD%s>' % self.td_style)
 904 
 905 
 906         if self.album == '1':
 907             if self.front_image == '':
 908                 front_image = self.full[0]
 909             else:
 910                 front_image = self.front_image
 911             ii = 0
 912             for tst in self.full:
 913                 if tst == front_image:
 914                     break
 915                 ii += 1
 916 
 917         for attfile in self.full:
 918             if  self.album == '1':
 919                 if tst == front_image:
 920                    i = ii
 921 
 922             this_description = self.description[i]
 923             this_exif_date = self.exif_date[i]
 924             this_webnail = self.web[i]
 925             this_imgtype = self.imgtype[i]
 926             this_thumbfile = self.thumb[i]
 927 
 928             thumbf = os.path.join(self.static_path, this_thumbfile)
 929             webf = os.path.join(self.static_path, this_webnail)
 930 
 931             if self.renew == '1':
 932                 if os.path.exists(thumbf):
 933                    os.unlink(thumbf)
 934                 if os.path.exists(webf):
 935                    os.unlink(webf)
 936 
 937             if not os.path.exists(webf) or not os.path.exists(thumbf):
 938                 infile = os.path.join(attachment_path, attfile)
 939                 im = Image.open(infile)
 940 
 941                 if not os.path.exists(webf):
 942                     im.thumbnail((int(self.webnail_width), int(self.webnail_width)), Image.ANTIALIAS)
 943                     if self.image_for_webnail == '1':
 944                        os.link(os.path.join(attachment_path, attfile), webf)
 945                     else:
 946                        im.save(webf, this_imgtype)
 947                 if not os.path.exists(thumbf):
 948                     im.thumbnail(((int(self.thumbnail_width)), ((int(self.thumbnail_width)))),
 949                                    Image.ANTIALIAS)
 950                     im.save(thumbf, this_imgtype)
 951 
 952             if self.image_for_webnail == '1':
 953                  this_webnailimg = attfile
 954                  self.webimg = self.full
 955             else:
 956                  this_webnailimg = this_webnail
 957                  self.webimg = self.web
 958 
 959             if self.mode == '1':
 960                 text = self.mode1_html(i)
 961                 self.request.write(''.join(text))
 962 
 963             if self.mode == '2':
 964                 text = self.mode2_html(i)
 965                 if cols > 1: self.request.write('<table valign="bottom">')
 966                 self.request.write(''.join(text))
 967                 if cols > 1: self.request.write('</table>')
 968 
 969             if self.mode == '1' or cols > 1:
 970                 if self.album == '0':
 971                     if  z < cols:
 972                         self.request.write('</TD>')
 973                         if z < n and  i < n - 1:
 974                             self.request.write('<TD%s>' % self.td_style)
 975                         if i == n - 1:
 976                             self.request.write('</TR>')
 977                     else:
 978                         self.request.write('</TD>')
 979                         self.request.write('</TR>')
 980                         if i < n - 1:
 981                             self.request.write('<TR valign="top">')
 982                             self.request.write('<TD%s>' % self.td_style)
 983 
 984             i += 1
 985             z += 1
 986             if z > cols:
 987                 z = 1
 988 
 989             if self.album == '1':
 990                 self.request.write("%(n)s images (%(album_name)s)" % {"n": str(n), "album_name": self.album_name})
 991                 break
 992 
 993         if self.album == '0':
 994             if i < n:
 995                 self.request.write('</TD>')
 996                 self.request.write('</TR>')
 997             self.request.write('</table>')
 998 
 999 
1000         if self.sequence_name != '':
1001             video_file = "%(file)s.%(ext)s" % {
1002                  "file": os.path.join(attachment_path, self.sequence_name),
1003                  "ext": 'swf'}
1004             if self.renew == '1':
1005                if os.path.exists(video_file):
1006                   os.unlink(video_file)
1007 
1008             cmd = ''
1009             if float(self.sequence_fps) < 1:
1010                 fps = 1
1011             else:
1012                 fps = round(float(self.sequence_fps))
1013 
1014             f_list = []
1015             for attfile in self.web:
1016                 file = os.path.join(self.static_path, attfile)
1017                 if os.path.exists(file):
1018                    f_list.append(file)
1019 
1020             if not os.path.exists(video_file):
1021                 width, height = self.images2swf(f_list, video_file, fps, self.description, self.exif_date)
1022             else:
1023                 swf = SWF.load(video_file)
1024                 for tag in swf.tags:
1025                     if tag.isImage():
1026                        width, height = tag.image.size
1027                        break
1028 
1029             if os.path.exists(video_file):
1030                   dict = {}
1031                   dict['src'] = AttachFile.getAttachUrl(current_pagename, '%(file)s.%(videotype)s'  % {
1032                      'file': self.sequence_name,
1033                      'videotype': 'swf',
1034                      }, self.request)
1035 
1036                   image_link = '%(file)s.%(videotype)s' % {'file':self.sequence_name, 'videotype': 'swf'}
1037                   if  self.eo_info == '1':
1038                       eo = "Or embed it into your wiki page by [[EmbedObject(%(file)s,width=%(width)s,height=%(height)s)]]." % {
1039                            'file': image_link,
1040                            'width': str(width),
1041                            'height': str(height)}
1042                   else:
1043                       eo = ''
1044 
1045                   self.request.write('<P>')
1046                   text = formatter.url(1, dict['src'] ) + image_link + formatter.url(0)
1047                   self.request.write('Download this image sequence %(text)s for your archive. %(EO)s' % {
1048                        'text': text,
1049                        'EO': eo
1050                        })
1051                   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.