| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | #======================================================================= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __version__ = '''0.0.01''' | 
					
						
							| 
									
										
										
										
											2013-05-22 03:00:38 +04:00
										 |  |  | __sub_version__ = '''20130522020247''' | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | __copyright__ = '''(c) Alex A. Naanou 2011''' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import Image | 
					
						
							|  |  |  | import json | 
					
						
							|  |  |  | import sha | 
					
						
							|  |  |  | import urllib2 | 
					
						
							| 
									
										
										
										
											2013-05-22 03:00:38 +04:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | from pli.logictypes import OR | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import gid | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | CONFIG = { | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	'absolute-path': False, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	'cache-image-name': '%(guid)s - %(name)s', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	'images': '.ImageGridCache/images.json', | 
					
						
							|  |  |  | 	'data': '.ImageGridCache/data.json', | 
					
						
							|  |  |  | 	'marked': '.ImageGridCache/marked.json', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	'error': '.ImageGridCache/error.log', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	'cache-structure': { | 
					
						
							|  |  |  | 		# make these as close to standard as possible and keep sane  | 
					
						
							|  |  |  | 		# distances... | 
					
						
							|  |  |  | 		'150px': '.ImageGridCache/150px/', | 
					
						
							|  |  |  | 		'350px': '.ImageGridCache/350px/', | 
					
						
							|  |  |  | 		'900px': '.ImageGridCache/900px/', | 
					
						
							|  |  |  | 		'1080px': '.ImageGridCache/1080px/', | 
					
						
							|  |  |  | 		'1920px': '.ImageGridCache/1920px/', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	'sizes': { | 
					
						
							|  |  |  | 		'150px': 150, | 
					
						
							|  |  |  | 		'350px': 350, | 
					
						
							|  |  |  | 		'900px': 900, | 
					
						
							|  |  |  | 		'1080px': 1080, | 
					
						
							|  |  |  | 		'1920px': 1920, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | DATA = { | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	'version': '2.0', | 
					
						
							|  |  |  | 	'current': None, | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 	'ribbons': (), | 
					
						
							|  |  |  | 	'order': (), | 
					
						
							|  |  |  | 	'image_file': None, | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IMAGE_EXT = OR(*( | 
					
						
							|  |  |  | 		'.jpg', '.jpeg', '.JPG', '.JPEG', | 
					
						
							|  |  |  | )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ERR_LOG = '''\
 | 
					
						
							|  |  |  | ERROR: %(error)s | 
					
						
							|  |  |  | SOURCE: %(source-file)s | 
					
						
							|  |  |  | TARGET: %(target-file)s | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | # Helpers... | 
					
						
							|  |  |  | #------------------------------------------------------------pathjoin--- | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | def pathjoin(*p): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	return ('/'.join(p)).replace('//', '/') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | #-------------------------------------------------------------getpath--- | 
					
						
							|  |  |  | def getpath(root, path, absolute=False): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	if absolute == True: | 
					
						
							|  |  |  | 		return 'file:///' + urllib2.quote(pathjoin(root, path), safe='/:') | 
					
						
							|  |  |  | 	else: | 
					
						
							| 
									
										
										
										
											2013-05-22 03:00:38 +04:00
										 |  |  | 		return urllib2.quote(pathjoin(path), safe='/:') | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #-------------------------------------------------------------log_err--- | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | def log_err(path, e, source_file, target_file): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	'''
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 	err_file = pathjoin(path, CONFIG['error']) | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	if not os.path.exists(err_file): | 
					
						
							|  |  |  | 		err = open(err_file, 'w') | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		err = open(err_file, 'a') | 
					
						
							|  |  |  | 	with err: | 
					
						
							|  |  |  | 		err.write(ERR_LOG % { | 
					
						
							|  |  |  | 				'source-file': source_file, | 
					
						
							|  |  |  | 				'target-file': target_file, | 
					
						
							|  |  |  | 				'error': e, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | #------------------------------------------------------------hash_gid--- | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | def hash_gid(img, force=False): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	Generate gid based on preview file content. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NOTE: img can be either a path or an Image. | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	if type(img) in (str, unicode): | 
					
						
							|  |  |  | 		img = Image.open(img) | 
					
						
							|  |  |  | 	return sha.sha(img.tostring()).hexdigest() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | #-----------------------------------------------------report_progress--- | 
					
						
							|  |  |  | def report_progress(img, status): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	# created all previews... | 
					
						
							|  |  |  | 	if False not in status: | 
					
						
							|  |  |  | 		print '.', | 
					
						
							|  |  |  | 	# created no previews... | 
					
						
							|  |  |  | 	elif True not in status: | 
					
						
							|  |  |  | 		print '-', | 
					
						
							|  |  |  | 	# created some previews... | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		print 'p', | 
					
						
							|  |  |  | 	return img | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #-----------------------------------------make_inline_report_progress--- | 
					
						
							|  |  |  | def make_inline_report_progress(state=None): | 
					
						
							|  |  |  | 	if state == None: | 
					
						
							|  |  |  | 		state = {} | 
					
						
							| 
									
										
										
										
											2013-05-22 03:00:38 +04:00
										 |  |  | 	if 'started at' not in state: | 
					
						
							|  |  |  | 		state['started at'] = time.time() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 	def _inline_report_progress(img, status): | 
					
						
							|  |  |  | 		created = state.get('created', 0) | 
					
						
							|  |  |  | 		skipped = state.get('skipped', 0) | 
					
						
							|  |  |  | 		partial = state.get('partial', 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 03:00:38 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 		# created all previews... | 
					
						
							|  |  |  | 		if False not in status: | 
					
						
							|  |  |  | 			created += 1 | 
					
						
							|  |  |  | 			state['created'] = created | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# created no previews... | 
					
						
							|  |  |  | 		elif True not in status: | 
					
						
							|  |  |  | 			skipped += 1 | 
					
						
							|  |  |  | 			state['skipped'] = skipped | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# created some previews... | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			partial += 1 | 
					
						
							|  |  |  | 			state['partial'] = partial | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 03:00:38 +04:00
										 |  |  | 		state['done at'] = time.time() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 		print 'Previews created: %s partial: %s skipped: %s...\r' % (created, partial, skipped), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return img | 
					
						
							|  |  |  | 	return _inline_report_progress | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------- | 
					
						
							|  |  |  | # API... | 
					
						
							|  |  |  | #----------------------------------------------------build_cache_dirs--- | 
					
						
							|  |  |  | def build_cache_dirs(path, config=CONFIG): | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	'''
 | 
					
						
							|  |  |  | 	Build cache directory tree. | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	dirs = config['cache-structure'] | 
					
						
							|  |  |  | 	for _, k in dirs.items(): | 
					
						
							|  |  |  | 		p = pathjoin(path, k) | 
					
						
							|  |  |  | 		if not os.path.exists(p): | 
					
						
							|  |  |  | 			os.makedirs(p) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | #--------------------------------------------------------build_images--- | 
					
						
							|  |  |  | def build_images(path, config=CONFIG, gid_generator=hash_gid): | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	'''
 | 
					
						
							|  |  |  | 	Build image structures update images.json in cache. | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	absolute_path = config['absolute-path'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for name in os.listdir(path): | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 		fname, ext = os.path.splitext(name) | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if ext != IMAGE_EXT: | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		source_path = pathjoin(path, name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		img =  { | 
					
						
							|  |  |  | 			'id': gid_generator(source_path), | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 			'name': name, | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 			'type': 'image', | 
					
						
							|  |  |  | 			'state': 'single', | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 			'path': getpath(path, name, absolute_path), | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 			'ctime': os.path.getctime(source_path), | 
					
						
							|  |  |  | 			'preview': {}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		yield img | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | #------------------------------------------------------build_previews--- | 
					
						
							|  |  |  | # NOTE: this will create images in the file system. | 
					
						
							|  |  |  | def build_previews(image, path=None, config=CONFIG, dry_run=True): | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	'''
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	NOTE: this needs the cache directory structure present. | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 	'''
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 	status = [] | 
					
						
							|  |  |  | 	# config... | 
					
						
							|  |  |  | 	absolute_path = config['absolute-path'] | 
					
						
							|  |  |  | 	dirs = config['cache-structure'] | 
					
						
							|  |  |  | 	sizes = config['sizes']  | 
					
						
							|  |  |  | 	cache_name = config['cache-image-name'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# data... | 
					
						
							|  |  |  | 	gid = image['id'] | 
					
						
							|  |  |  | 	img_name = image['name'] | 
					
						
							|  |  |  | 	name = os.path.splitext(img_name)[0] | 
					
						
							|  |  |  | 	img_path = image['path'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if absolute_path == False: | 
					
						
							|  |  |  | 		source_path = os.path.join(path, img_path) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		# XXX is this the best way??? | 
					
						
							|  |  |  | 		o = urllib2.urlopen(img_path) | 
					
						
							|  |  |  | 		source_path = o.fp.name | 
					
						
							|  |  |  | 		o.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	img = Image.open(source_path, 'r') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# biggest preview is the original image... | 
					
						
							|  |  |  | 	image['preview'][str(max(*img.size)) + 'px'] = img_path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# previews... | 
					
						
							|  |  |  | 	for k, spec in sizes.items(): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if k in image['preview'].keys(): | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# build the two paths: relative and full... | 
					
						
							|  |  |  | 		n = pathjoin(dirs[k], cache_name % {'guid': gid, 'name': img_name}) | 
					
						
							|  |  |  | 		p = pathjoin(path, n) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# do not upscale images... | 
					
						
							|  |  |  | 		if max(*img.size) <= spec: | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# add image to index... | 
					
						
							|  |  |  | 		if not os.path.exists(p): | 
					
						
							|  |  |  | 			scale = spec/float(max(*img.size)) | 
					
						
							|  |  |  | 			preview = img.resize((int(img.size[0]*scale), int(img.size[1]*scale)), Image.ANTIALIAS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if not dry_run: | 
					
						
							|  |  |  | 				preview.save(p) | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				preview.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			##!!! metadata??? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			status += [True]  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		# image exists... | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			status += [False]  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		image['preview'][str(spec) + 'px'] = getpath(path, n, absolute_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return image, status | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------build_data--- | 
					
						
							|  |  |  | def build_data(images, path, config=CONFIG): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	images_index = {} | 
					
						
							|  |  |  | 	marked = [] | 
					
						
							|  |  |  | 	data = DATA.copy() | 
					
						
							|  |  |  | 	ribbon = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for image in images: | 
					
						
							|  |  |  | 		gid = image['id']  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		images_index[gid] = image | 
					
						
							|  |  |  | 		ribbon += [gid] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ribbon.sort(lambda a, b: cmp(images_index[b]['ctime'], images_index[a]['ctime'])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data['ribbons'] = [ribbon] | 
					
						
							|  |  |  | 	data['order'] = ribbon[:] | 
					
						
							|  |  |  | 	data['current'] = ribbon[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data, images_index, marked | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | # High-level API... | 
					
						
							|  |  |  | #---------------------------------------------------------build_cache--- | 
					
						
							|  |  |  | ##!!! DO NOT OVERWRITE EXISTING DATA... | 
					
						
							|  |  |  | def build_cache(path, config=CONFIG, gid_generator=hash_gid,  | 
					
						
							|  |  |  | 		report_progress=report_progress, dry_run=False): | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	'''
 | 
					
						
							|  |  |  | 	absolute_path = config['absolute-path'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	build_cache_dirs(path, config) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, images, marked = build_data( | 
					
						
							|  |  |  | 			(report_progress(*build_previews(img, path, config, dry_run=dry_run)) | 
					
						
							|  |  |  | 				for img in build_images(path, config, gid_generator)),  | 
					
						
							|  |  |  | 			path, config) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	images_file = config['images'] | 
					
						
							|  |  |  | 	data_file = config['data'] | 
					
						
							|  |  |  | 	marked_file = config['marked'] | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 	data['image_file'] = getpath(path, images_file, absolute_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if not dry_run: | 
					
						
							|  |  |  | 		##!!! DO NOT OVERWRITE EXISTING DATA... | 
					
						
							|  |  |  | 		with open(os.path.join(path, images_file), 'w') as f: | 
					
						
							|  |  |  | 			json.dump(images, f, indent=4) | 
					
						
							|  |  |  | 		with open(os.path.join(path, data_file), 'w') as f: | 
					
						
							|  |  |  | 			json.dump(data, f, indent=4) | 
					
						
							|  |  |  | 		with open(os.path.join(path, marked_file), 'w') as f: | 
					
						
							|  |  |  | 			json.dump(marked, f, indent=4) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------- | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  | 	pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-22 01:44:27 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-21 23:25:55 +04:00
										 |  |  | #======================================================================= | 
					
						
							|  |  |  | #                                            vim:set ts=4 sw=4 nowrap : |