589 lines
23 KiB
Python
Executable File
589 lines
23 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2014 Ville Rantanen
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Lesser General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import sys,os
|
|
import re
|
|
import urllib
|
|
import shutil
|
|
import csv
|
|
import subprocess
|
|
import string
|
|
from math import ceil
|
|
from datetime import datetime
|
|
|
|
# (c) ville.rantanen@helsinki.fi
|
|
|
|
__version__='2.6'
|
|
|
|
FILECONFIG=".config"
|
|
FILEDESC="descriptions.csv"
|
|
FILEINFO="info.txt"
|
|
SAVEDCONFIG="""attachments=boolean
|
|
gallery=string
|
|
infofile=string
|
|
parent=string
|
|
reverse=boolean
|
|
timesort=boolean
|
|
clean=boolean
|
|
force=boolean
|
|
gravity=string
|
|
link=boolean
|
|
thumbs=boolean
|
|
width=string""".split('\n')
|
|
CONFIGCOMMENTS="""
|
|
config values:
|
|
gallery: Name of the gallery
|
|
infofile: Name of the infofile, inserted in beginning of the main page
|
|
parent: String URL pointing to parent folder
|
|
reverse: Sort reverse
|
|
timesort: Sort by timestamp
|
|
clean: Delete unused thumbnails
|
|
force: Force recreate thumbnails
|
|
gravity: ImageMagick option for creating thumbnails, e.g. North,East,Center
|
|
link: Medium sized images are symbolic links to original
|
|
thumbs: Build medium sized and thumbnail images.
|
|
width: Medium images longer axis in pixels
|
|
""".split('\n')
|
|
webfilesearch=re.compile('.*index.html$|gallerystyle.css$|galleryscript.js$|'+FILEDESC+'$|^'+FILEINFO+'$|\..*',re.I)
|
|
imagesearch=re.compile('.*\.jpg$|.*\.jpeg$|.*\.gif$|.*\.png$|.*\.svg$|.*\.pdf$',re.I)
|
|
vectorsearch=re.compile('.*\.svg$|.*\.pdf$',re.I)
|
|
nonconvertiblesearch=re.compile('.*\.html$|.*\.htm$|.*\.php$',re.I)
|
|
#gifsearch=re.compile('.*gif$',re.I)
|
|
excludepaths=re.compile('_med|_tn|\..*')
|
|
doublequotes=re.compile('"')
|
|
singlequotes=re.compile("'")
|
|
stripquotes=re.compile('^"|"$')
|
|
|
|
def getheader(path,parent,title=""):
|
|
if title=="":
|
|
title=unicode(os.path.basename(path),encoding="utf8").encode('ascii', 'xmlcharrefreplace')
|
|
return '''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>'''+title+'''</TITLE>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<link rel="stylesheet" type="text/css" href="'''+parent+'''gallerystyle.css">
|
|
<script language="javascript" src="'''+parent+'''galleryscript.js"></script>
|
|
</HEAD>
|
|
<BODY>
|
|
'''
|
|
def getfooter():
|
|
return '''
|
|
<div id="footer">Generated with Qalbum '''+__version__+''' ('''+datetime.today().strftime("%y-%m-%d %H:%M")+''') <a href="http://code.google.com/p/qalbum/wiki/Usage" target="_TOP">Need help?</a></div>
|
|
<script language="javascript">setup();</script>
|
|
</BODY>
|
|
</HTML>
|
|
'''
|
|
|
|
def getimagelist(path,options=False):
|
|
''' Returns a list of images matching the regex '''
|
|
list=os.listdir(path)
|
|
imgs=[]
|
|
for f in list:
|
|
if (imagesearch.match(f)) and (os.path.isfile(os.path.join(path,f))):
|
|
imgs.append(f)
|
|
if options:
|
|
if options.timesort:
|
|
imgs.sort(key=lambda f: os.path.getmtime(os.path.join(path, f)),reverse=options.reverse)
|
|
else:
|
|
imgs.sort(reverse=options.reverse)
|
|
else:
|
|
imgs.sort()
|
|
return imgs
|
|
|
|
def getnonconvertiblelist(path,options=False):
|
|
''' Returns a list of files matching the nonconvertible regex '''
|
|
list=os.listdir(path)
|
|
files=[]
|
|
for f in list:
|
|
if (nonconvertiblesearch.match(f)) and (os.path.isfile(os.path.join(path,f))) and not (webfilesearch.match(f)):
|
|
files.append(f)
|
|
if options:
|
|
if options.timesort:
|
|
files.sort(key=lambda f: os.path.getmtime(os.path.join(path, f)),reverse=options.reverse)
|
|
else:
|
|
files.sort(reverse=options.reverse)
|
|
else:
|
|
files.sort()
|
|
return files
|
|
|
|
def getfiletimes(path,list):
|
|
''' Returns a list of modification times '''
|
|
times=[]
|
|
for p in list:
|
|
times.append(int(os.path.getmtime(os.path.join(path,p))))
|
|
return times
|
|
|
|
def getfilesizes(path,list):
|
|
''' Returns a list of sizes '''
|
|
sizes=[]
|
|
for p in list:
|
|
sizes.append(int(os.path.getsize(os.path.join(path,p))))
|
|
return sizes
|
|
|
|
def getnonimagelist(path,options):
|
|
''' Returns a list of files not matching the image match regex '''
|
|
list=os.listdir(path)
|
|
files=[]
|
|
if not options.attachments:
|
|
return files
|
|
for f in list:
|
|
if (not webfilesearch.match(f)) and (not imagesearch.match(f)) and (os.path.isfile(os.path.join(path,f))):
|
|
files.append(f)
|
|
if options.timesort:
|
|
files.sort(key=lambda f: os.path.getmtime(os.path.join(path, f)),reverse=options.reverse)
|
|
else:
|
|
files.sort(reverse=options.reverse)
|
|
return files
|
|
|
|
def getpathlist(path,options=False):
|
|
''' Returns a list of subfolders not matching the exclusion regex '''
|
|
list=os.listdir(path)
|
|
paths=[]
|
|
for d in list:
|
|
if (not excludepaths.match(d)) and (os.path.isdir(os.path.join(path,d))):
|
|
paths.append(d)
|
|
if options:
|
|
if options.timesort:
|
|
paths.sort(key=lambda f: os.path.getmtime(f),reverse=options.reverse)
|
|
else:
|
|
paths.sort(reverse=options.reverse)
|
|
else:
|
|
paths.sort()
|
|
return paths
|
|
|
|
def pathscript(path,list):
|
|
''' Returns the javascript string of pathlist and pathimage arrays '''
|
|
scrstr='<script language="javascript">var pathlist=['
|
|
elements=[]
|
|
for p in list:
|
|
imglist=getimagelist(os.path.join(path,p))
|
|
pathlist=getpathlist(os.path.join(path,p))
|
|
this_str='{ name:"'+unicode(p,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'", '
|
|
this_str+='size:'+str(len(imglist)+len(pathlist))+', '
|
|
if len(imglist)>0:
|
|
this_str+='image:"'+unicode(p,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'/_tn/tn_'+unicode(imglist[0],encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'.jpg"}'
|
|
else:
|
|
this_str+='image:"" }'
|
|
elements.append(this_str)
|
|
scrstr+=','.join(elements)+'];</script>'
|
|
return scrstr
|
|
|
|
def pathlinks(path,list):
|
|
''' Returns the HTML string of subfolders '''
|
|
if len(list)==0:
|
|
return '<div id="pathcontainer"></div>'
|
|
pathstr='<div id="pathcontainer">'
|
|
pathstr+='<h1>Subfolders</h1>'
|
|
for p in list:
|
|
nice=nicestring(p)
|
|
imglist=getimagelist(os.path.join(path,p))
|
|
nsum=str(len(imglist))
|
|
imgstr=""
|
|
if len(imglist)>0:
|
|
imgstr='<span class="pathbox" style="background-image:url(\''+urllib.quote(p)+'/_tn/tn_'+urllib.quote(imglist[0])+'.jpg\');">'
|
|
else:
|
|
imgstr='<span class="pathbox">'
|
|
pathstr+='<a title="'+unicode(p,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'" href="'+urllib.quote(p)+'/index.html">'+imgstr+'<span class="pathlink"><span class="pathlinktext">'+unicode(nice,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+' ('+nsum+')</span></span></span></a>';
|
|
pathstr+='</script>'
|
|
pathstr+='</div>'
|
|
return pathstr
|
|
|
|
def imagescript(path,list):
|
|
''' Returns the javascript string of imagelist and imagedesc '''
|
|
strout='<script language="javascript">var imagelist=['
|
|
descriptions=getdescriptions(path,list)
|
|
times=getfiletimes(path,list)
|
|
sizes=getfilesizes(path,list)
|
|
n=0
|
|
elements=[]
|
|
for i in list:
|
|
try:
|
|
desc=singlequotes.sub("\\'",unicode(descriptions[n],encoding="utf8").encode('ascii', 'xmlcharrefreplace'))
|
|
except:
|
|
desc=singlequotes.sub("\\'",filter(lambda x: x in string.printable, descriptions[n]).encode('ascii', 'xmlcharrefreplace'))
|
|
this_str='\n{name:"'+unicode(i,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'", '
|
|
this_str+='desc:\''+desc+'\', '
|
|
this_str+='size:\''+str(sizes[n])+'\', '
|
|
this_str+='time:'+str(times[n])+'}'
|
|
elements.append(this_str)
|
|
n+=1
|
|
strout+=','.join(elements)+'];</script>'
|
|
return strout
|
|
|
|
def imagelinks(path,list):
|
|
''' Returns the HTML string of images '''
|
|
if len(list)==0:
|
|
return '<div id="thumbcontainer"></div>'
|
|
strout='<div id="thumbcontainer"><noscript>'
|
|
strout+='<h1>Images</h1>'
|
|
descriptions=getdescriptions(path,list)
|
|
n=0
|
|
for i in list:
|
|
nice=nicestring(i)
|
|
try:
|
|
desc=doublequotes.sub('',unicode(descriptions[n],encoding="utf8").encode('ascii', 'xmlcharrefreplace'))
|
|
except:
|
|
desc=doublequotes.sub('',filter(lambda x: x in string.printable, descriptions[n]).encode('ascii', 'xmlcharrefreplace'))
|
|
|
|
strout+='<span class="imagebox thumbbox" id="n'+str(n)+'"><a href="'+urllib.quote(i)+'"><img class="thumbimage" "title="'+desc+'" src="_tn/tn_'+urllib.quote(i)+'.jpg"><br/>'+unicode(nice,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'</a></span>'
|
|
n+=1
|
|
strout+='</noscript></div>'
|
|
return strout
|
|
|
|
def filescript(path,list):
|
|
''' Returns the javascript string of filelist '''
|
|
strout='<script language="javascript">var filelist=['
|
|
elements=[];
|
|
for i in list:
|
|
elements.append('"'+unicode(i,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'"')
|
|
strout+=','.join(elements)+'];</script>'
|
|
return strout
|
|
|
|
def filelinks(path,list):
|
|
''' Returns the HTML string of non image files '''
|
|
strout='<div id="attachmentcontainer">'
|
|
if len(list)>0:
|
|
strout+='<h2>Attachments</h1>'
|
|
n=0
|
|
for i in list:
|
|
size=sizestring(os.path.getsize(os.path.join(path,i)))
|
|
strout+='<span class="attachmentbox" id="a'+str(n)+'"><a href="'+urllib.quote(i)+'">'+unicode(i,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+' ['+size+']</a></span>'
|
|
n+=1
|
|
strout+='</div>'
|
|
return strout
|
|
|
|
def cleanthumbs(path):
|
|
''' clears _med and _tn for unused thumbs '''
|
|
print('clearing unused thumbs...')
|
|
if os.path.exists(os.path.join(path,'_tn')):
|
|
clearfolder(path,os.path.join(path,'_tn'),re.compile("(^tn_)(.*)(.jpg)"))
|
|
if os.path.exists(os.path.join(path,'_med')):
|
|
clearfolder(path,os.path.join(path,'_med'),re.compile("(^med_)(.*)(.jpg)"))
|
|
return
|
|
|
|
def clearfolder(path,tnpath,regex):
|
|
''' clears given folder '''
|
|
list=getimagelist(tnpath)
|
|
for i in list:
|
|
f=regex.match(i)
|
|
try:
|
|
if not os.path.exists(os.path.join(path,f.group(2))):
|
|
print('removing '+i)
|
|
os.remove(os.path.join(tnpath,i))
|
|
except:
|
|
continue
|
|
return
|
|
|
|
def createthumbs(path,list,options):
|
|
''' Runs imagemagick Convert to create medium sized and thumbnail images '''
|
|
if len(list)==0:
|
|
return
|
|
if not os.path.exists(os.path.join(path,'_tn')):
|
|
os.mkdir(os.path.join(path,'_tn'))
|
|
if not os.path.exists(os.path.join(path,'_med')):
|
|
os.mkdir(os.path.join(path,'_med'))
|
|
n=1
|
|
nsum=len(list)
|
|
r=str(options.width)
|
|
res=r+'x'+r+'>'
|
|
for i in list:
|
|
outmedium=os.path.join(path,'_med','med_'+i+'.jpg')
|
|
outthumb=os.path.join(path,'_tn','tn_'+i+'.jpg')
|
|
inpath=os.path.join(path,i)
|
|
if (options.force) and os.path.exists(outmedium):
|
|
os.unlink(outmedium)
|
|
if (options.force) and os.path.exists(outthumb):
|
|
os.unlink(outthumb)
|
|
if (not os.path.exists(outmedium)):
|
|
print('Medium.. '+i+' '+str(n)+'/'+str(nsum))
|
|
create_medium_bitmap(inpath,outmedium,r,link=options.link,vector=vectorsearch.match(i))
|
|
if (not os.path.exists(outthumb)):
|
|
print('Thumbnail.. '+i+' '+str(n)+'/'+str(nsum))
|
|
create_thumb_bitmap(outmedium,outthumb,vector=vectorsearch.match(i),gravity=options.gravity)
|
|
n+=1
|
|
return
|
|
|
|
def create_medium_bitmap(infile,outfile,r,link=False,vector=False):
|
|
if link:
|
|
os.symlink('../'+os.path.basename(infile),outfile)
|
|
return
|
|
res=r+'x'+r+'>'
|
|
if vector:
|
|
convargs=['convert','-density','300x300',infile+'[0]','-background','white','-flatten','-resize',res,'-quality','97',outfile]
|
|
else:
|
|
convargs=['convert','-define','jpeg:size='+r+'x'+r,infile+'[0]','-background','white','-flatten','-resize',res,'-quality','85',outfile]
|
|
convp=subprocess.call(convargs)
|
|
return
|
|
|
|
def create_thumb_bitmap(infile,outfile,vector=False,gravity='Center'):
|
|
if vector:
|
|
convargs=['convert','-density','300x300',infile,'-background','white','-flatten','-thumbnail','90x90^','-gravity',gravity,'-crop','90x90+0+0','+repage','-quality','75',outfile]
|
|
else:
|
|
convargs=['convert','-define','jpeg:size=300x300',infile,'-background','white','-flatten','-thumbnail','90x90^','-gravity',gravity,'-crop','90x90+0+0','+repage','-quality','75',outfile]
|
|
convp=subprocess.call(convargs)
|
|
return
|
|
|
|
def getdescriptions(path,list):
|
|
''' Read descriptions.csv file and returns a list of descriptions.
|
|
Missing descriptions are replaced with the file name. '''
|
|
if not os.path.exists(os.path.join(path,FILEDESC)):
|
|
return list
|
|
desc=[i for i in list]
|
|
reader = csv.reader(open(os.path.join(path,FILEDESC),'rb'),
|
|
delimiter='\t',
|
|
doublequote=False,
|
|
escapechar='\\',
|
|
quoting=csv.QUOTE_NONE)
|
|
for row in reader:
|
|
if len(row)>1:
|
|
if row[0] in list:
|
|
i=list.index(stripquotes.sub('',row[0]))
|
|
desc[i]=stripquotes.sub('',row[1])
|
|
return desc
|
|
|
|
def getinfo(path,options):
|
|
''' Read info.txt file and returns the content.
|
|
Missing info file returns empty string. '''
|
|
if not os.path.exists(os.path.join(path,options.infofile)):
|
|
return ''
|
|
reader = open(os.path.join(path,options.infofile),'r')
|
|
return unicode(reader.read(),encoding="utf8",errors="ignore").encode('ascii','xmlcharrefreplace')
|
|
|
|
def crumblinks(crumbs,title,parent):
|
|
''' Create the HTML string for crumb trails '''
|
|
|
|
strout='<div id="crumbcontainer">'
|
|
if parent:
|
|
if not parent.startswith('http://'):
|
|
parent="../"*(len(crumbs))+parent
|
|
strout+='<a href="'+parent+'">'+'Home'.encode('ascii', 'xmlcharrefreplace')+'</a>: '
|
|
i=1
|
|
for c in crumbs:
|
|
cname=os.path.basename(c)
|
|
if i==1:
|
|
cname=title
|
|
cdepth=len(crumbs)-i
|
|
clink="../"*cdepth
|
|
strout+='<a href="'+clink+'index.html">'+unicode(cname,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'</a>: '
|
|
i+=1
|
|
strout+='</div>'
|
|
return strout
|
|
|
|
def nicestring(s):
|
|
''' Returns a nice version of a long string '''
|
|
if len(s)<20:
|
|
return s
|
|
s=s.replace("_"," ")
|
|
s=s.replace("-"," ")
|
|
if len(s)>30:
|
|
s=s[0:26]+".."+s[-3:]
|
|
return s
|
|
|
|
def sizestring(size):
|
|
''' Returns human readable file size string '''
|
|
for x in ['b','kb','Mb','Gb','Tb']:
|
|
if size < 1024.0:
|
|
if (x=='b') | (x=='kb'):
|
|
return "%d%s" % (size, x)
|
|
else:
|
|
return "%3.1f%s" % (size, x)
|
|
size /= 1024.0
|
|
|
|
def traverse(path,crumbs,inputs,options):
|
|
''' The recursive main function to create the index.html and seek sub folders '''
|
|
|
|
print(path)
|
|
if (not options.recurselink) and (os.path.islink(path)):
|
|
print('Not recursing, is a link')
|
|
return
|
|
if len(crumbs)==1:
|
|
header=getheader(path,'../'*(len(crumbs)-1),inputs[0][1])
|
|
else:
|
|
header=getheader(path,'../'*(len(crumbs)-1))
|
|
if not os.path.exists(os.path.join(path,'../'*(len(crumbs)-1),'galleryscript.js')):
|
|
print('Warning, no (relative path) galleryscript! '+os.path.join(path,'../'*(len(crumbs)-1),'galleryscript.js'))
|
|
#depth=0
|
|
#while not os.path.exists(os.path.join(path,'../'*(depth),'galleryscript.js')):
|
|
# print(os.path.join(path,'../'*(depth)))
|
|
# depth+=1
|
|
#header=getheader(path,'../'*(depth))
|
|
|
|
#print('Depth: '+str(len(crumbs)))
|
|
pathlist=getpathlist(path,options)
|
|
imagelist=getimagelist(path,options)
|
|
if options.clean:
|
|
cleanthumbs(path)
|
|
if options.thumbs:
|
|
createthumbs(path,imagelist,options)
|
|
imagelist.extend(getnonconvertiblelist(path,options))
|
|
filelist=getnonimagelist(path,options)
|
|
print(str(len(pathlist))+' paths, '+str(len(imagelist))+' images, '+str(len(filelist))+' other files')
|
|
crumbstring=crumblinks(crumbs,options.gallery,options.parent)
|
|
pathjs=pathscript(path,pathlist)
|
|
pathstring=pathlinks(path,pathlist)
|
|
filestring=filelinks(path,filelist)
|
|
#filejs=filescript(path,filelist) # Filelist is not currently used in javascript
|
|
imagestring=imagelinks(path,imagelist)
|
|
imagejs=imagescript(path,imagelist)
|
|
|
|
f=open(os.path.join(path,"index.html"),"w")
|
|
f.write(header)
|
|
f.write('<div id="preloadcontainer"></div>')
|
|
f.write(pathjs)
|
|
f.write(imagejs)
|
|
#f.write(filejs)
|
|
f.write(crumbstring)
|
|
f.write(pathstring)
|
|
f.write('<div id="imagecontainer">'+getinfo(path,options)+'</div>')
|
|
f.write('<div id="desccontainer"></div>')
|
|
f.write(imagestring)
|
|
f.write(filestring)
|
|
f.write('<div id="listcontainer"></div>')
|
|
f.write(getfooter())
|
|
f.close()
|
|
|
|
for p in pathlist:
|
|
nextcrumbs=[i for i in crumbs]
|
|
nextcrumbs.append(os.path.join(path,p))
|
|
traverse(os.path.join(path,p),nextcrumbs,inputs,options)
|
|
return
|
|
|
|
def setupoptions():
|
|
''' Setup the command line options '''
|
|
from argparse import ArgumentParser
|
|
parser=ArgumentParser()
|
|
parser.add_argument("-v",action='version', version=__version__)
|
|
parser.add_argument("--version",action='version', version=__version__)
|
|
parser.add_argument("-c",action="store_true",dest="writeconfig",default=False,
|
|
help="Write current configuration to file "+FILECONFIG+
|
|
". If file exists, Qalbum and thumbnail handling read from the file, "+
|
|
"overriding switches.")
|
|
parser.add_argument("-r",action="store_true",dest="reverse",default=False,
|
|
help="Reverse sort orded")
|
|
parser.add_argument("-L",action="store_false",dest="recurselink",default=True,
|
|
help="List, but do not recurse in to symbolic link folders")
|
|
parser.add_argument("-s",type=str,dest="style",
|
|
help="User defined CSS style file.")
|
|
parser.add_argument("-t",action="store_true",dest="timesort",default=False,
|
|
help="Sort by file modification time")
|
|
parser.add_argument("-a",action="store_false",dest="attachments",default=True,
|
|
help="Disable attachments")
|
|
parser.add_argument("-i",type=str,dest="infofile",default=FILEINFO,
|
|
help="File name for info files in all folders. (Default: %(default)s)")
|
|
parser.add_argument("-g",type=str,dest="gallery",default="Gallery",
|
|
help="Name for the root gallery (Default: %(default)s)")
|
|
parser.add_argument("--gravity",type=str,dest="gravity",default="Center",
|
|
help="ImageMagick gravity for cropping. (Default: %(default)s)")
|
|
parser.add_argument("-w",type=int,dest="width",default=850,
|
|
help="Medium image size (Default: %(default)s)")
|
|
parser.add_argument("--no-thumbs",action="store_false",dest="thumbs",default=True,
|
|
help="Disable thumbnail and medium generation. Build the indexes only.")
|
|
parser.add_argument("-p",type=str,dest="parent",
|
|
help="Add a ../[PARENT] link to point out from the gallery. If the string starts with http:// it is considered as a static URL, otherwise the relative parent path is assumed.")
|
|
parser.add_argument("startpath",type=str,action="store",default=os.path.abspath('.'),nargs='?',
|
|
help="Root path of the gallery")
|
|
options=parser.parse_args()
|
|
options.startpath=os.path.abspath(options.startpath)
|
|
options=setupdefaultoptions(options)
|
|
return options
|
|
|
|
def setupdefaultoptions(options):
|
|
''' Adds the missing options for the options object '''
|
|
if 'attachments' not in options:
|
|
options.attachments=True
|
|
if 'clean' not in options:
|
|
options.clean=False
|
|
if 'force' not in options:
|
|
options.force=False
|
|
if 'infofile' not in options:
|
|
options.infofile=FILEINFO
|
|
if 'gallery' not in options:
|
|
options.gallery="Gallery"
|
|
if 'gravity' not in options:
|
|
options.gravity="Center"
|
|
if 'link' not in options:
|
|
options.link=False
|
|
if 'recursive' not in options:
|
|
options.recursive=True
|
|
if 'recurselink' not in options:
|
|
options.recurselink=True
|
|
if 'reverse' not in options:
|
|
options.reverse=False
|
|
if 'style' not in options or options.style is None:
|
|
options.style=os.path.join(os.path.abspath(os.path.dirname(os.path.realpath(sys.argv[0]))),'gallerystyle.css')
|
|
if 'timesort' not in options:
|
|
options.timesort=False
|
|
if 'thumbs' not in options:
|
|
options.thumbs=True
|
|
if 'width' not in options:
|
|
options.width=850
|
|
return options
|
|
|
|
def readconfig(options):
|
|
""" Set up the options via config file """
|
|
if os.path.exists(FILECONFIG):
|
|
import configobj
|
|
try:
|
|
cfg=configobj.ConfigObj(FILECONFIG, configspec=SAVEDCONFIG, unrepr=True)
|
|
except configobj.UnreprError as err:
|
|
print("Config file "+FILECONFIG+" syntax error!")
|
|
print(err)
|
|
sys.exit(1)
|
|
for opt in cfg.keys():
|
|
setattr(options,opt,cfg[opt])
|
|
print("Read config from file")
|
|
|
|
return options
|
|
|
|
def writeconfig(options):
|
|
""" Write the options to config file """
|
|
import configobj
|
|
cfg=configobj.ConfigObj(configspec=SAVEDCONFIG, unrepr=True)
|
|
cfg.initial_comment=CONFIGCOMMENTS
|
|
cfg.filename=FILECONFIG
|
|
for opt in SAVEDCONFIG:
|
|
optname=opt.split("=")[0]
|
|
cfg[optname]=getattr(options,optname)
|
|
cfg.write()
|
|
print('Wrote '+FILECONFIG)
|
|
|
|
def execute_plain():
|
|
''' Main execution function '''
|
|
options=setupoptions()
|
|
options=readconfig(options)
|
|
options=setupdefaultoptions(options)
|
|
if options.writeconfig:
|
|
writeconfig(options)
|
|
# Copy all resources to target folder
|
|
pathname=os.path.dirname(os.path.realpath(sys.argv[0]))
|
|
fullpath=os.path.abspath(pathname)
|
|
if not os.path.exists(options.style):
|
|
raise IOError('File not found: "'+options.style+'"')
|
|
shutil.copyfile(options.style,os.path.join(options.startpath,'gallerystyle.css'))
|
|
shutil.copyfile(os.path.join(fullpath,'galleryscript.js'),os.path.join(options.startpath,'galleryscript.js'))
|
|
|
|
inputs=[]
|
|
inputs.append((None,options.gallery,None))
|
|
|
|
traverse(options.startpath,[options.startpath],inputs,options)
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
execute_plain()
|