--- /dev/null
+*.pyc
\ No newline at end of file
--- /dev/null
+import os, sys
+
+MIMETYPES_FILE_NAME = os.path.realpath(sys.path[0]) + '/mimetypes.xml'
+PAGE_TEMPLATE_FILE_NAME = os.path.realpath(sys.path[0]) + '/default_page_template.html'
+STYLESHEET_FILE_NAME = os.path.realpath(sys.path[0]) + '/default_stylesheet.css'
+BROWSER_COMMAND = '/usr/bin/firefox'
+
+ITEM_WIDTH = 800
+ITEM_HEIGHT = 600
--- /dev/null
+import os
+import sys
+import time
+import md5
+import tempfile
+import Defaults
+
+
+def GetPictarDir():
+ rel_script_path = sys.argv[0]
+ abs_script_path = os.path.abspath(rel_script_path)
+ abs_script_dir = os.path.dirname(abs_script_path)
+
+ return abs_script_dir
+
+
+def GetBrowserCommand():
+ # Get the command used to execute the user's browser.
+ return Defaults.BROWSER_COMMAND
+
+
+def GetAbsTargetDir():
+ rel_target_dir = os.getcwd()
+ argc = len(sys.argv)
+
+ if (argc > 1):
+ # If no directory was passed to the program,
+ # use the current working directory as the target.
+ # Otherwise, use the passed directory.
+ rel_target_dir = sys.argv[1]
+
+ # Convert a relative path into an absolute one.
+ # It will be important to have an absolute path
+ # later when we are constructing URLs.
+ __abs_target_dir = os.path.abspath(rel_target_dir)
+
+ return __abs_target_dir
+
+
+
+
+def GetPageTemplatePath():
+ script_dir = GetPictarDir()
+ page_template_path = os.path.join(script_dir, Defaults.PAGE_TEMPLATE_FILE_NAME)
+
+ return page_template_path
+
+
+
+def GetRecursive():
+ __recursive = False
+ return __recursive
+
+
+
+def GetOutfilePath():
+ unique_string = str(time.time())
+ md5hash = md5.new(unique_string)
+ outfile_name = md5hash.hexdigest()
+ outfile_path = os.path.join(tempfile.gettempdir(), outfile_name)
+
+ return outfile_path
+
+
+
+
+
+
+def GetItemTemplatePath():
+ script_dir = GetPictarDir()
+ item_template_path = os.path.join(script_dir, Defaults.ITEM_TEMPLATE_FILE_NAME)
+
+ return item_template_path
+
+
+
+def GetStyleSheetPath():
+ script_dir = GetPictarDir()
+ stylesheet_path = os.path.join(script_dir, Defaults.STYLESHEET_FILE_NAME)
+
+ return stylesheet_path
+
+
+
+def GetVerbose():
+ return True
+
+
+def GetMimetypesFilePath():
+ script_dir = GetPictarDir()
+ mimetypes_file_path = os.path.join(script_dir, Defaults.MIMETYPES_FILE_NAME)
+
+ return mimetypes_file_path
+
--- /dev/null
+
+"""
+Wrapper class for the 'filetype' elements in the config file. Nothing
+tricky here, except that the accessor for the template should
+intelligently determine which of the two fields (template_file,
+template_data) is used as the template source.
+"""
+
+class SupportedType:
+
+ def __init__(self,
+ name = "",
+ description = "",
+ extensions = [],
+ template_file = "",
+ template_data = ""):
+
+ self.__name = name
+ self.__description = description
+ self.__extensions = extensions
+ self.__template_file = template_file
+ self.__template_data = template_data
+
+ return
+
+
+
+ def GetName(self):
+ return self.__name
+
+
+ def GetDescription(self):
+ return self.__description
+
+
+ def GetExtensions(self):
+ return self.__extensions
+
+
+ def GetTemplate(self):
+ if (self.__template_data == None or self.__template_data == ""):
+ # The data is not given explicitly, so rely on the
+ # template file to provide it.
+ template_file = open(self.__template_file, "r")
+ template = template_file.read()
+ template_file.close()
+ return template
+ else:
+ return self.__template_data
+
+
+
+ def SetName(self, name):
+ self.__name = name
+ return
+
+
+ def SetDescription(self, description):
+ self.__description = description
+ return
+
+
+ def SetExtensions(self, extensions):
+ self.__extensions = extensions
+ return
+
+
+ def SetTemplateData(self, template_data):
+ self.__template_data = template_data
+ return
+
+
+ def SetTemplateFile(self, template_file):
+ self.__template_file = template_file
+ return
+
--- /dev/null
+import os
+from SupportedType import SupportedType
+from xml.dom import Node
+from xml.dom.ext.reader.Sax import FromXmlFile
+
+"""
+This class parses all of the information in the config file, and makes
+it available through various methods.
+"""
+
+class XmlDataParser:
+
+ def __init__(self, xml_file_path):
+ self.__supported_types = []
+
+ xml_doc = FromXmlFile(xml_file_path)
+
+ supported_type_elements = xml_doc.getElementsByTagName('supported_type')
+
+ for current_node in supported_type_elements:
+ name = self.GetChildrenText(current_node, 'name')[0]
+ descriptions = self.GetChildrenText(current_node, 'description')
+ extensions = self.GetChildrenText(current_node, 'extension')
+ template_files = self.GetChildrenText(current_node, 'template_file')
+ template_data = self.GetChildrenText(current_node, 'template_data')
+
+ current_type = SupportedType()
+ current_type.SetName(name)
+ current_type.SetExtensions(extensions)
+
+ if (len(descriptions) > 0):
+ current_type.SetDescription(descriptions[0])
+
+
+ if (len(template_files) > 0):
+ # Allow for relative paths in the template field
+ root_dir = os.path.dirname(xml_file_path)
+ template_file_path = os.path.join(root_dir, template_files[0])
+ current_type.SetTemplateFile(template_file_path)
+
+
+ if (len(template_data) > 0):
+ current_type.SetTemplateData(template_data[0])
+
+ self.__supported_types.append(current_type)
+
+ return
+
+
+
+ def GetAllExtensions(self):
+ all_extensions = []
+
+ for current_type in self.__supported_types:
+ current_type_extensions = current_type.GetExtensions()
+ for extension in current_type_extensions:
+ all_extensions.append(extension)
+
+ return all_extensions
+
+
+
+ def GetTemplateByExtension(self, extension):
+ # Get the (x)html template which corresponds to a mimetype
+ # having the supplied extension.
+ for current_type in self.__supported_types:
+ current_type_extensions = current_type.GetExtensions()
+
+ for current_extension in current_type_extensions:
+ if (current_extension.lower() == extension.lower()):
+ return current_type.GetTemplate()
+
+ return None
+
+
+
+ def GetNameByExtension(self, extension):
+ # Get the name of the mimetype that a particular extension
+ # belongs to.
+ for current_type in self.__supported_types:
+ current_type_extensions = current_type.GetExtensions()
+
+ for current_extension in current_type_extensions:
+ if (current_extension.lower() == extension.lower()):
+ return current_type.GetName()
+
+ return None
+
+
+
+ def GetChildNodesByTagName(self, node, tag_name):
+ found_children = []
+
+ for child in node.childNodes:
+ if (child.nodeName == tag_name):
+ found_children.append(child)
+
+ return found_children
+
+
+
+
+ def GetChildrenText(self, node, child_tag_name):
+ children_text = []
+
+ children = self.GetChildNodesByTagName(node, child_tag_name)
+
+ for child_node in children:
+ for sub_child in child_node.childNodes:
+ if (sub_child.nodeType == Node.TEXT_NODE):
+ children_text.append(sub_child.nodeValue)
+ break
+
+
+ return children_text
+
+
+
+
--- /dev/null
+import re
+import os
+import sys
+import urllib
+
+import Configuration
+
+from string import Template
+from TemplateParser import *
+from Mime.XmlDataParser import XmlDataParser
+
+
+class Pictar:
+
+ def __init__(self):
+ self.template_parser = TemplateParser()
+ self.__data_parser = XmlDataParser(Configuration.GetMimetypesFilePath())
+
+
+ # Compile the regular expressions only once
+ self.item_regexes = []
+
+ extensions = self.__data_parser.GetAllExtensions()
+
+ for extension in extensions:
+ pattern = '\\' + extension + '$'
+ self.item_regexes.append(re.compile(pattern, re.IGNORECASE))
+
+ return
+
+
+
+ def GetItemPaths(self):
+ # Create a list of the item paths based on which
+ # of the files in the target directory match at least
+ # one of the item regular expressions.
+ target_dir = Configuration.GetAbsTargetDir()
+
+ item_paths = []
+
+ dir_contents = os.listdir(target_dir)
+
+ for file_name in dir_contents:
+ for regex_obj in self.item_regexes:
+ if (regex_obj.search(file_name) != None):
+ absolute_item_path = os.path.join(target_dir, file_name)
+ encoded_path = urllib.quote(absolute_item_path)
+ item_paths.append(encoded_path)
+
+ return item_paths
+
+
+
+ def GetItemData(self, item_paths):
+ # Build the pictar markup
+ item_data = ""
+ current_item_number = 0
+
+ for item_path in item_paths:
+ current_item_number += 1
+ item_extension = os.path.splitext(item_path)[1]
+ item_template = Template(self.__data_parser.GetTemplateByExtension(item_extension))
+ item_mimetype = self.__data_parser.GetNameByExtension(item_extension)
+
+ current_item_data = item_template.substitute(header=item_path,
+ image_path=item_path,
+ item_number=current_item_number,
+ height=Configuration.Defaults.ITEM_HEIGHT,
+ width=Configuration.Defaults.ITEM_WIDTH,
+ mimetype=item_mimetype);
+
+ item_data += current_item_data
+
+ return item_data
+
+
+
+ def GetPageData(self, item_data):
+ # Fill in the template with our markup
+ stylesheet_file_name = Configuration.GetStyleSheetPath()
+ page_template = self.template_parser.GetPageTemplate()
+ page_data = page_template.substitute(stylesheet=stylesheet_file_name,
+ pictar_markup=item_data)
+
+ return page_data
+
+
+
+ def LaunchBrowser(self, url='about:blank'):
+ launch_result = os.spawnl(os.P_WAIT, Configuration.GetBrowserCommand(), Configuration.GetBrowserCommand(), url)
+ return launch_result
+
+
+
+ def WritePage(self, page_data):
+ # Write the output file
+ outfile_path = Configuration.GetOutfilePath()
+
+ outfile = open(outfile_path, "w")
+ outfile.write(page_data)
+ outfile.close()
+
+ return outfile_path
--- /dev/null
+import Configuration
+from string import Template
+
+
+class TemplateParser:
+
+ def GetPageTemplate(self):
+ # Read the page template file into a string
+ page_template_path = Configuration.GetPageTemplatePath()
+ page_template_file = open(page_template_path, "r")
+ page_template = Template(page_template_file.read())
+ page_template_file.close()
+
+ return page_template
+
+
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <title>PICTAR</title>
+
+ <link rel="stylesheet" type="text/css" href="${stylesheet}" />
+
+</head>
+
+<body>
+
+ ${pictar_markup}
+
+</body>
+
+</html>
--- /dev/null
+/************/
+/* ELEMENTS */
+/************/
+
+body {
+ margin: 0em;
+ padding: 0em;
+ background-color: #ebebae;
+}
+
+
+img {
+ border: 0em;
+ border-top: 1px #000000 dashed;
+ padding: 20px;
+}
+
+
+/***********/
+/* CLASSES */
+/***********/
+
+.image_container {
+ display: table;
+ background-color: #f0ead8;
+ border: 1px #000000 dashed;
+ margin-left: 5px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+
+.image_header {
+ background-color: #bf3e18;
+ color: #ffffff;
+ font-weight: bold;
+ text-align: center;
+ padding: .2em;
+ font-family: fixed, monospace;
+}
+
+
--- /dev/null
+<?xml version="1.0"?>
+
+<!-- PICTARRRRRRRR!!! -->
+
+<mimetypes>
+
+ <supported_type>
+ <name>image/gif</name>
+ <description>Graphics Interchange Format (GIF) Image</description>
+ <extension>.gif</extension>
+ <template_file>templates/img.html</template_file>
+ </supported_type>
+
+ <supported_type>
+ <name>image/jpeg</name>
+ <description>Joint Photographic Experts Group (JPEG) Image</description>
+ <extension>.jpg</extension>
+ <extension>.jpe</extension>
+ <extension>.jpeg</extension>
+ <template_file>templates/img.html</template_file>
+ </supported_type>
+
+ <supported_type>
+ <name>image/png</name>
+ <description>Portable Network Graphic</description>
+ <extension>.png</extension>
+ <template_file>templates/img.html</template_file>
+ </supported_type>
+
+ <supported_type>
+ <name>image/svg+xml</name>
+ <description>Scalable Vector Graphic</description>
+ <extension>.svg</extension>
+ <template_file>templates/object.html</template_file>
+ </supported_type>
+
+</mimetypes>
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python
+
+from Pictar import *
+
+the_pictar = Pictar()
+
+
+"""
+if (os.path.isdir(target_dir) == False):
+ print "Error: The given directory, \"" + target_dir + "\", is invalid.\n"
+ sys.exit(FAILURE)
+"""
+
+
+
+image_paths = the_pictar.GetItemPaths()
+
+image_data = the_pictar.GetItemData(image_paths)
+
+page_data = the_pictar.GetPageData(image_data)
+
+outfile = the_pictar.WritePage(page_data)
+
+the_pictar.LaunchBrowser(outfile)
+
--- /dev/null
+<div class="image_container">
+ <div class="image_header">
+ ${header}
+ </div>
+
+ <img src="${image_path}"
+ alt="Pictar Image ${item_number}" />
+</div>
--- /dev/null
+<div class="image_container">
+ <div class="image_header">
+ ${header}
+ </div>
+
+ <object data="${image_path}"
+ height="${height}"
+ width="${width}"
+ type="${mimetype}" />
+
+</div>
\ No newline at end of file