diff -r 373392025533 -r 3b1579a7bffb lib/folder.py --- a/lib/folder.py Wed Jun 03 18:59:46 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,329 +0,0 @@ -# DeGAL - A pretty simple web image gallery -# Copyright (C) 2007 Tero Marttila -# http://marttila.de/~terom/degal/ -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# - -import os, os.path - -import settings, image, utils, helpers, log -from template import gallery as gallery_tpl -from helpers import url_for_page - -def dirUp (count=1) : - """ - Returns a relative path to the directly count levels above the current one - """ - - if not count : - return '.' - - return os.path.join(*(['..']*count)) - -class Folder (object) : - def __init__ (self, name='.', parent=None) : - # the directory name, no trailing / - self.name = unicode(name.rstrip(os.sep)) - - # our parent Folder, or None - self.parent = parent - - # the path to this dir, as a relative path to the root of the image gallery, always starts with . - if parent and name : - self.path = parent.pathFor(self.name) - else : - self.path = self.name - - # the url-path to the index.html file - self.html_path = self.path - - # dict of fname -> Folder - self.subdirs = {} - - # dict of fname -> Image - self.images = {} - - # our human-friendly title - self.title = None - - # our long-winded description - self.descr = '' - - # is this folder non-empty? - self.alive = None - - # self.images.values(), but sorted by filename - self.sorted_images = [] - - # the ShortURL key to this dir - self.shorturl_code = None - - # were we filtered out? - self.filtered = False - - def pathFor (self, *fnames) : - """ - Return a root-relative path to the given path inside this dir - """ - return os.path.join(self.path, *fnames) - - def index (self, filters=None) : - """ - Look for other dirs and images inside this dir. Filters must be either None, - whereupon all files will be included, or a dict of {filename -> next_filter}. - If given, only filenames that are present in the dict will be indexed, and in - the case of dirs, the next_filter will be passed on to that Folder's index - method. - """ - - if filters : - self.filtered = True - - # iterate through listdir - for fname in os.listdir(self.path) : - # the full filesystem path to it - fpath = self.pathFor(fname) - - # ignore dotfiles - if fname.startswith('.') : - log.debug("Skipping dotfile %s", fname) - continue - - # apply filters - if filters : - if fname in filters : - next_filter = filters[fname] - else : - log.debug("Skip `%s' as we have a filter", fname) - continue - else : - next_filter = None - - # recurse into subdirs, but not thumbs/previews - if (os.path.isdir(fpath) - and (fname not in (settings.THUMB_DIR, settings.PREVIEW_DIR)) - and (self.parent or fname not in settings.ROOT_IGNORE) - ) : - log.down(fname) - - f = Folder(fname, self) - - try : - if f.index(next_filter) : # recursion - # if a subdir is alive, we are alive as well - self.subdirs[fname] = f - self.alive = True - except Exception, e : - log.warning("skip - %s: %s" % (type(e), e)) - - log.up() - - # handle images - elif os.path.isfile(fpath) and utils.isImage(fname) : - log.next(fname) - self.images[fname] = image.Image(self, fname) - - # ignore everything else - else : - log.debug("Ignoring file %s", fname) - - # sort and link the images - if self.images : - self.alive = True - - # sort the images - fnames = self.images.keys() - fnames.sort() - - prev = None - - # link - for fname in fnames : - img = self.images[fname] - - img.prev = prev - - if prev : - prev.next = img - - prev = img - - # add to the sorted images list - self.sorted_images.append(img) - - # figure out our title/ descr. Must be done before our parent dir is rendered (self.title) - title_path = self.pathFor(settings.TITLE_FILE) - - self.title, self.descr = utils.readTitleDescr(title_path) - - # default title for the root dir - if self.title or self.descr : - self.alive = True - pass # use what was in the title file - - elif not self.parent : - self.title = 'Index' - - else : - self.title = self.name - - if not self.alive : - log.debug("Dir %s isn't alive" % self.path) - - return self.alive - - def getObjInfo (self) : - """ - Metadata for shorturls2.db - """ - return 'dir', self.path, '' - - def breadcrumb (self, forImg=None) : - """ - Returns a [(fname, title)] list of this dir's parent dirs - """ - - f = self - b = [] - d = 0 - - while f : - # functionality of the slightly-hacked-in variety - if f is self and forImg is not None : - url = helpers.url_for_page(self.getPageNumber(forImg)) - else : - url = dirUp(d) - - b.insert(0, (url, f.title)) - - d += 1 - f = f.parent - - return b - - def getPageNumber (self, img) : - """ - Get the page number that the given image is on - """ - - return self.sorted_images.index(img) // settings.IMAGE_COUNT - - def countParents (self, acc=0) : - if self.parent : - return self.parent.countParents(acc+1) - else : - return acc - - def inRoot (self, *fnames) : - """ - Return a relative URL from this dir to the given path in the root dir - """ - - c = self.countParents() - - return utils.url_join(*((['..']*c) + list(fnames))) - - def render (self) : - """ - Render the index.html, Images, and recurse into subdirs - """ - - # ded folders are skipped - if not self.alive : - # dead, skip, no output - return - - index_mtime = utils.mtime(self.pathFor("index.html")) - dir_mtime = utils.mtime(self.path) - - # if this dir's contents were filtered out, then we can't render the index.html, as we aren't aware of all the images in here - if self.filtered : - log.warning("Dir `%s' contents were filtered, so we won't render the gallery index again", self.path) - - elif index_mtime > dir_mtime : - # no changes, pass, ignored - pass - - else : - # create the thumb/preview dirs if needed - for dir in (settings.THUMB_DIR, settings.PREVIEW_DIR) : - path = self.pathFor(dir) - - if not os.path.isdir(path) : - log.info("mkdir %s", dir) - os.mkdir(path) - - # sort the subdirs - subdirs = self.subdirs.values() - subdirs.sort(key=lambda d: d.name) - - # paginate! - images = self.sorted_images - image_count = len(images) - pages = [] - - while images : - pages.append(images[:settings.IMAGE_COUNT]) - images = images[settings.IMAGE_COUNT:] - - pagination_required = len(pages) > 1 - - if pagination_required : - log.info("%d pages @ %d images", len(pages), settings.IMAGE_COUNT) - elif not pages : - log.info("no images, render for subdirs") - pages = [[]] - - for cur_page, images in enumerate(pages) : - if pagination_required and cur_page > 0 : - shorturl = "%s/%s" % (self.shorturl_code, cur_page+1) - else : - shorturl = self.shorturl_code - - # render to index.html - gallery_tpl.render_to(self.pathFor(url_for_page(cur_page)), - stylesheet_url = self.inRoot('style.css'), - title = self.title, - breadcrumb = self.breadcrumb(), - - dirs = subdirs, - images = images, - - num_pages = len(pages), - cur_page = cur_page, - - description = self.descr, - - shorturl = self.inRoot('s', shorturl), - shorturl_code = shorturl, - ) - - # render images - image_count = len(self.sorted_images) - for i, img in enumerate(self.images.itervalues()) : - log.next("[%-4d/%4d] %s", i + 1, image_count, img.name) - - img.render() - - # recurse into subdirs - for dir in self.subdirs.itervalues() : - log.down(dir.name) - - dir.render() - - log.up() -