summaryrefslogtreecommitdiff
path: root/rapid/renamesubfolderprefs.py
diff options
context:
space:
mode:
Diffstat (limited to 'rapid/renamesubfolderprefs.py')
-rw-r--r--rapid/renamesubfolderprefs.py1695
1 files changed, 0 insertions, 1695 deletions
diff --git a/rapid/renamesubfolderprefs.py b/rapid/renamesubfolderprefs.py
deleted file mode 100644
index d538030..0000000
--- a/rapid/renamesubfolderprefs.py
+++ /dev/null
@@ -1,1695 +0,0 @@
-#!/usr/bin/python
-# -*- coding: latin1 -*-
-
-### Copyright (C) 2007, 2008, 2009, 2010 Damon Lynch <damonlynch@gmail.com>
-
-### 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
-
-""" Define and test preferences for use in PlusMinus tables.
-
-These are displayed to the user as a series of rows in the user
-preferences dialog window.
-
-Preferences for subfolders and image renaming are defined below
-in dictionaries and lists. This makes it easier for checking validity and
-creating combo boxes.
-
-There are 3 levels: 0, 1 and 2, which specify the depth of the pref value.
-Level 0 is the topmost level, and corresponds to the first entry in the
-row of preferences the user sees in the preferences dialog window.
-
-Custom exceptions are defined to handle invalid preferences.
-
-The user's actual preferences, on the other hand, are stored in flat lists.
-Each list has members which are a multiple of 3 in length.
-Each group of 3 members is equal to one line of preferences in the plus minus
-table.
-"""
-#needed for python 2.5, unneeded for python 2.6
-from __future__ import with_statement
-
-import string
-
-import os
-import re
-import sys
-
-import gtk.gdk as gdk
-
-try:
- import pygtk
- pygtk.require("2.0")
-except:
- pass
-try:
- import gtk
-except:
- sys.exit(1)
-
-from common import Configi18n
-global _
-_ = Configi18n._
-
-import datetime
-
-import config
-
-from common import pythonifyVersion
-import problemnotification as pn
-
-
-# Special key in each dictionary which specifies the order of elements.
-# It is very important to have a consistent and rational order when displaying
-# these prefs to the user, and dictionaries are unsorted.
-
-ORDER_KEY = "__order__"
-
-# PLEASE NOTE: these values are duplicated in a dummy class whose function
-# is to have them put into the translation template. If you change the values below
-# then you MUST change the value in class i18TranslateMeThanks as well!!
-
-# *** Level 0
-DATE_TIME = 'Date time'
-TEXT = 'Text'
-FILENAME = 'Filename'
-METADATA = 'Metadata'
-SEQUENCES = 'Sequences'
-JOB_CODE = 'Job code'
-
-SEPARATOR = os.sep
-
-# *** Level 1
-
-# Date time
-IMAGE_DATE = 'Image date'
-TODAY = 'Today'
-YESTERDAY = 'Yesterday'
-VIDEO_DATE = 'Video date'
-DOWNLOAD_TIME = 'Download time'
-
-# File name
-NAME_EXTENSION = 'Name + extension'
-NAME = 'Name'
-EXTENSION = 'Extension'
-IMAGE_NUMBER = 'Image number'
-VIDEO_NUMBER = 'Video number'
-
-# Metadata
-APERTURE = 'Aperture'
-ISO = 'ISO'
-EXPOSURE_TIME = 'Exposure time'
-FOCAL_LENGTH = 'Focal length'
-CAMERA_MAKE = 'Camera make'
-CAMERA_MODEL = 'Camera model'
-SHORT_CAMERA_MODEL = 'Short camera model'
-SHORT_CAMERA_MODEL_HYPHEN = 'Hyphenated short camera model'
-SERIAL_NUMBER = 'Serial number'
-SHUTTER_COUNT = 'Shutter count'
-OWNER_NAME = 'Owner name'
-
-# Video metadata
-CODEC = 'Codec'
-WIDTH = 'Width'
-HEIGHT = 'Height'
-FPS = 'Frames Per Second'
-LENGTH = 'Length'
-
-#Image sequences
-DOWNLOAD_SEQ_NUMBER = 'Downloads today'
-SESSION_SEQ_NUMBER = 'Session number'
-SUBFOLDER_SEQ_NUMBER = 'Subfolder number'
-STORED_SEQ_NUMBER = 'Stored number'
-
-SEQUENCE_LETTER = 'Sequence letter'
-
-
-
-# *** Level 2
-
-# Image number
-IMAGE_NUMBER_ALL = 'All digits'
-IMAGE_NUMBER_1 = 'Last digit'
-IMAGE_NUMBER_2 = 'Last 2 digits'
-IMAGE_NUMBER_3 = 'Last 3 digits'
-IMAGE_NUMBER_4 = 'Last 4 digits'
-
-
-# Case
-ORIGINAL_CASE = "Original Case"
-UPPERCASE = "UPPERCASE"
-LOWERCASE = "lowercase"
-
-# Sequence number
-SEQUENCE_NUMBER_1 = "One digit"
-SEQUENCE_NUMBER_2 = "Two digits"
-SEQUENCE_NUMBER_3 = "Three digits"
-SEQUENCE_NUMBER_4 = "Four digits"
-SEQUENCE_NUMBER_5 = "Five digits"
-SEQUENCE_NUMBER_6 = "Six digits"
-SEQUENCE_NUMBER_7 = "Seven digits"
-
-
-# Now, define dictionaries and lists of valid combinations of preferences.
-
-# Level 2
-
-# Date
-
-SUBSECONDS = 'Subseconds'
-
-# ****** NOTE 1: if changing LIST_DATE_TIME_L2, you MUST update the default subfolder preference below *****
-# ****** NOTE 2: if changing LIST_DATE_TIME_L2, you MUST update DATE_TIME_CONVERT below *****
-LIST_DATE_TIME_L2 = ['YYYYMMDD', 'YYYY-MM-DD','YYMMDD', 'YY-MM-DD',
- 'MMDDYYYY', 'MMDDYY', 'MMDD',
- 'DDMMYYYY', 'DDMMYY', 'YYYY', 'YY',
- 'MM', 'DD',
- 'HHMMSS', 'HHMM', 'HH-MM-SS', 'HH-MM', 'HH', 'MM (minutes)', 'SS']
-
-
-LIST_IMAGE_DATE_TIME_L2 = LIST_DATE_TIME_L2 + [SUBSECONDS]
-
-DEFAULT_SUBFOLDER_PREFS = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[9], '/', '', '', DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]]
-DEFAULT_VIDEO_SUBFOLDER_PREFS = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[9], '/', '', '', DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[0]]
-
-class i18TranslateMeThanks:
- """ this class is never used in actual running code
- It's purpose is to have these values inserted into the program's i18n template file
-
- """
- def __init__(self):
- _('Date time')
- _('Text')
- _('Filename')
- _('Metadata')
- _('Sequences')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode
- _('Job code')
- _('Image date')
- _('Video date')
- _('Today')
- _('Yesterday')
- # Translators: Download time is the time and date that the download started (when the user clicked the Download button)
- _('Download time')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Name + extension')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Name')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Extension')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Image number')
- _('Video number')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Aperture')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('ISO')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Exposure time')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Focal length')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Camera make')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Camera model')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Short camera model')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Hyphenated short camera model')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Serial number')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Shutter count')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
- _('Owner name')
- _('Codec')
- _('Width')
- _('Height')
- _('Length')
- _('Frames Per Second')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
- _('Downloads today')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
- _('Session number')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
- _('Subfolder number')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
- _('Stored number')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
- _('Sequence letter')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('All digits')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Last digit')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Last 2 digits')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Last 3 digits')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
- _('Last 4 digits')
- # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
- _("Original Case")
- # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
- _("UPPERCASE")
- # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
- _("lowercase")
- _("One digit")
- _("Two digits")
- _("Three digits")
- _("Four digits")
- _("Five digits")
- _("Six digits")
- _("Seven digits")
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('Subseconds')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('YYYYMMDD')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('YYYY-MM-DD')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('YYMMDD')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('YY-MM-DD')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('MMDDYYYY')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('MMDDYY')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('MMDD')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('DDMMYYYY')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('DDMMYY')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('YYYY')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('YY')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('MM')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('DD')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('HHMMSS')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('HHMM')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('HH-MM-SS')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('HH-MM')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('HH')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('MM (minutes)')
- # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
- _('SS')
-
-
-# Convenience values for python datetime conversion using values in
-# LIST_DATE_TIME_L2. Obviously the two must remain synchronized.
-
-DATE_TIME_CONVERT = ['%Y%m%d', '%Y-%m-%d','%y%m%d', '%y-%m-%d',
- '%m%d%Y', '%m%d%y', '%m%d',
- '%d%m%Y', '%d%m%y', '%Y', '%y',
- '%m', '%d',
- '%H%M%S', '%H%M', '%H-%M-%S', '%H-%M',
- '%H', '%M', '%S']
-
-
-LIST_IMAGE_NUMBER_L2 = [IMAGE_NUMBER_ALL, IMAGE_NUMBER_1, IMAGE_NUMBER_2,
- IMAGE_NUMBER_3, IMAGE_NUMBER_4]
-
-
-LIST_CASE_L2 = [ORIGINAL_CASE, UPPERCASE, LOWERCASE]
-
-LIST_SEQUENCE_LETTER_L2 = [
- UPPERCASE,
- LOWERCASE
- ]
-
-
-
-LIST_SEQUENCE_NUMBERS_L2 = [
- SEQUENCE_NUMBER_1,
- SEQUENCE_NUMBER_2,
- SEQUENCE_NUMBER_3,
- SEQUENCE_NUMBER_4,
- SEQUENCE_NUMBER_5,
- SEQUENCE_NUMBER_6,
- SEQUENCE_NUMBER_7,
- ]
-
-
-
-LIST_SHUTTER_COUNT_L2 = [
- SEQUENCE_NUMBER_3,
- SEQUENCE_NUMBER_4,
- SEQUENCE_NUMBER_5,
- SEQUENCE_NUMBER_6,
- ]
-
-# Level 1
-LIST_DATE_TIME_L1 = [IMAGE_DATE, TODAY, YESTERDAY, DOWNLOAD_TIME]
-LIST_VIDEO_DATE_TIME_L1 = [VIDEO_DATE, TODAY, YESTERDAY, DOWNLOAD_TIME]
-
-DICT_DATE_TIME_L1 = {
- IMAGE_DATE: LIST_IMAGE_DATE_TIME_L2,
- TODAY: LIST_DATE_TIME_L2,
- YESTERDAY: LIST_DATE_TIME_L2,
- DOWNLOAD_TIME: LIST_DATE_TIME_L2,
- ORDER_KEY: LIST_DATE_TIME_L1
- }
-
-VIDEO_DICT_DATE_TIME_L1 = {
- VIDEO_DATE: LIST_IMAGE_DATE_TIME_L2,
- TODAY: LIST_DATE_TIME_L2,
- YESTERDAY: LIST_DATE_TIME_L2,
- DOWNLOAD_TIME: LIST_DATE_TIME_L2,
- ORDER_KEY: LIST_VIDEO_DATE_TIME_L1
- }
-
-
-LIST_FILENAME_L1 = [NAME_EXTENSION, NAME, EXTENSION, IMAGE_NUMBER]
-
-DICT_FILENAME_L1 = {
- NAME_EXTENSION: LIST_CASE_L2,
- NAME: LIST_CASE_L2,
- EXTENSION: LIST_CASE_L2,
- IMAGE_NUMBER: LIST_IMAGE_NUMBER_L2,
- ORDER_KEY: LIST_FILENAME_L1
- }
-
-LIST_VIDEO_FILENAME_L1 = [NAME_EXTENSION, NAME, EXTENSION, VIDEO_NUMBER]
-
-DICT_VIDEO_FILENAME_L1 = {
- NAME_EXTENSION: LIST_CASE_L2,
- NAME: LIST_CASE_L2,
- EXTENSION: LIST_CASE_L2,
- VIDEO_NUMBER: LIST_IMAGE_NUMBER_L2,
- ORDER_KEY: LIST_VIDEO_FILENAME_L1
- }
-
-
-LIST_SUBFOLDER_FILENAME_L1 = [EXTENSION]
-
-DICT_SUBFOLDER_FILENAME_L1 = {
- EXTENSION: LIST_CASE_L2,
- ORDER_KEY: LIST_SUBFOLDER_FILENAME_L1
-}
-
-LIST_METADATA_L1 = [APERTURE, ISO, EXPOSURE_TIME, FOCAL_LENGTH,
- CAMERA_MAKE, CAMERA_MODEL,
- SHORT_CAMERA_MODEL,
- SHORT_CAMERA_MODEL_HYPHEN,
- SERIAL_NUMBER,
- SHUTTER_COUNT,
- OWNER_NAME]
-
-LIST_VIDEO_METADATA_L1 = [CODEC, WIDTH, HEIGHT, LENGTH, FPS]
-
-DICT_METADATA_L1 = {
- APERTURE: None,
- ISO: None,
- EXPOSURE_TIME: None,
- FOCAL_LENGTH: None,
- CAMERA_MAKE: LIST_CASE_L2,
- CAMERA_MODEL: LIST_CASE_L2,
- SHORT_CAMERA_MODEL: LIST_CASE_L2,
- SHORT_CAMERA_MODEL_HYPHEN: LIST_CASE_L2,
- SERIAL_NUMBER: None,
- SHUTTER_COUNT: LIST_SHUTTER_COUNT_L2,
- OWNER_NAME: LIST_CASE_L2,
- ORDER_KEY: LIST_METADATA_L1
- }
-
-DICT_VIDEO_METADATA_L1 = {
- CODEC: LIST_CASE_L2,
- WIDTH: None,
- HEIGHT: None,
- LENGTH: None,
- FPS: None,
- ORDER_KEY: LIST_VIDEO_METADATA_L1
- }
-
-LIST_SEQUENCE_L1 = [
- DOWNLOAD_SEQ_NUMBER,
- STORED_SEQ_NUMBER,
- SESSION_SEQ_NUMBER,
- SEQUENCE_LETTER
- ]
-
-DICT_SEQUENCE_L1 = {
- DOWNLOAD_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2,
- STORED_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2,
- SESSION_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2,
- SEQUENCE_LETTER: LIST_SEQUENCE_LETTER_L2,
- ORDER_KEY: LIST_SEQUENCE_L1
- }
-
-
-# Level 0
-
-
-LIST_IMAGE_RENAME_L0 = [DATE_TIME, TEXT, FILENAME, METADATA,
- SEQUENCES, JOB_CODE]
-
-LIST_VIDEO_RENAME_L0 = LIST_IMAGE_RENAME_L0
-
-
-DICT_IMAGE_RENAME_L0 = {
- DATE_TIME: DICT_DATE_TIME_L1,
- TEXT: None,
- FILENAME: DICT_FILENAME_L1,
- METADATA: DICT_METADATA_L1,
- SEQUENCES: DICT_SEQUENCE_L1,
- JOB_CODE: None,
- ORDER_KEY: LIST_IMAGE_RENAME_L0
- }
-
-DICT_VIDEO_RENAME_L0 = {
- DATE_TIME: VIDEO_DICT_DATE_TIME_L1,
- TEXT: None,
- FILENAME: DICT_VIDEO_FILENAME_L1,
- METADATA: DICT_VIDEO_METADATA_L1,
- SEQUENCES: DICT_SEQUENCE_L1,
- JOB_CODE: None,
- ORDER_KEY: LIST_VIDEO_RENAME_L0
- }
-
-LIST_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, JOB_CODE, SEPARATOR]
-
-DICT_SUBFOLDER_L0 = {
- DATE_TIME: DICT_DATE_TIME_L1,
- TEXT: None,
- FILENAME: DICT_SUBFOLDER_FILENAME_L1,
- METADATA: DICT_METADATA_L1,
- JOB_CODE: None,
- SEPARATOR: None,
- ORDER_KEY: LIST_SUBFOLDER_L0
- }
-
-LIST_VIDEO_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, JOB_CODE, SEPARATOR]
-
-DICT_VIDEO_SUBFOLDER_L0 = {
- DATE_TIME: VIDEO_DICT_DATE_TIME_L1,
- TEXT: None,
- FILENAME: DICT_SUBFOLDER_FILENAME_L1,
- METADATA: DICT_VIDEO_METADATA_L1,
- JOB_CODE: None,
- SEPARATOR: None,
- ORDER_KEY: LIST_VIDEO_SUBFOLDER_L0
- }
-
-# preference elements that require metadata
-# note there is no need to specify lower level elements if a higher level
-# element is necessary for them to be present to begin with
-METADATA_ELEMENTS = [METADATA, IMAGE_DATE]
-
-# preference elements that are sequence numbers or letters
-SEQUENCE_ELEMENTS = [
- DOWNLOAD_SEQ_NUMBER,
- SESSION_SEQ_NUMBER,
- SUBFOLDER_SEQ_NUMBER,
- STORED_SEQ_NUMBER,
- SEQUENCE_LETTER]
-
-# preference elements that do not require metadata and are not fixed
-# as above, there is no need to specify lower level elements if a higher level
-# element is necessary for them to be present to begin with
-DYNAMIC_NON_METADATA_ELEMENTS = [
- TODAY, YESTERDAY,
- FILENAME] + SEQUENCE_ELEMENTS
-
-
-
-#the following is what the preferences looked in older versions of the program
-#they are here for reference, and for checking the validity of preferences
-
-USER_INPUT = 'User'
-
-DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7 = 'Downloads today'
-SESSION_SEQ_NUMBER_V_0_0_8_B7 = 'Session sequence number'
-SUBFOLDER_SEQ_NUMBER_V_0_0_8_B7 = 'Subfolder sequence number'
-STORED_SEQ_NUMBER_V_0_0_8_B7 = 'Stored sequence number'
-SEQUENCE_LETTER_V_0_0_8_B7 = 'Sequence letter'
-
-LIST_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 = [
- SEQUENCE_NUMBER_1,
- SEQUENCE_NUMBER_2,
- SEQUENCE_NUMBER_3,
- SEQUENCE_NUMBER_4,
- SEQUENCE_NUMBER_5,
- SEQUENCE_NUMBER_6,
- ]
-
-DICT_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 = {
- SEQUENCE_NUMBER_1: None,
- SEQUENCE_NUMBER_2: None,
- SEQUENCE_NUMBER_3: None,
- SEQUENCE_NUMBER_4: None,
- SEQUENCE_NUMBER_5: None,
- SEQUENCE_NUMBER_6: None,
- ORDER_KEY: LIST_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7
- }
-
-LIST_SEQUENCE_L1_V_0_0_8_B7 = [USER_INPUT]
-
-DICT_SEQUENCE_L1_V_0_0_8_B7 = {
- USER_INPUT: DICT_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7,
- ORDER_KEY: LIST_SEQUENCE_L1_V_0_0_8_B7
- }
-
-LIST_SEQUENCE_LETTER_L1_L1_V_0_0_8_B7 = [
- UPPERCASE,
- LOWERCASE
- ]
-
-DICT_SEQUENCE_LETTER_L1_V_0_0_8_B7 = {
- UPPERCASE: None,
- LOWERCASE: None,
- ORDER_KEY: LIST_SEQUENCE_LETTER_L1_L1_V_0_0_8_B7
- }
-
-LIST_IMAGE_RENAME_L0_V_0_0_8_B7 = [DATE_TIME, TEXT, FILENAME, METADATA,
- DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7,
- SESSION_SEQ_NUMBER_V_0_0_8_B7,
- SEQUENCE_LETTER_V_0_0_8_B7]
-
-DICT_IMAGE_RENAME_L0_V_0_0_8_B7 = {
- DATE_TIME: DICT_DATE_TIME_L1,
- TEXT: None,
- FILENAME: DICT_FILENAME_L1,
- METADATA: DICT_METADATA_L1,
- DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7: None,
- SESSION_SEQ_NUMBER_V_0_0_8_B7: None,
- SEQUENCE_LETTER_V_0_0_8_B7: DICT_SEQUENCE_LETTER_L1_V_0_0_8_B7,
- ORDER_KEY: LIST_IMAGE_RENAME_L0_V_0_0_8_B7
- }
-
-PREVIOUS_IMAGE_RENAME= {
- '0.0.8~b7': DICT_IMAGE_RENAME_L0_V_0_0_8_B7,
- }
-
-
-# Functions to work with above data
-
-def _getPrevPrefs(oldDefs, currentDefs, previousVersion):
- k = oldDefs.keys()
- # if there were other defns, we'd need to figure out which one
- # but currently, there are no others
- # there will be in future, and this code wil be updated then
- version_change = pythonifyVersion(k[0])
- if pythonifyVersion(previousVersion) <= version_change:
- return oldDefs[k[0]]
- else:
- return currentDefs
-
-def _upgradePreferencesToCurrent(prefs, previousVersion):
- """ checks to see if preferences should be upgraded
-
- returns True if they were upgraded, and the new prefs
-
- VERY IMPORTANT: the new prefs will be a new list, not an inplace
- modification of the existing preferences! Otherwise, the check on
- assignment in the prefs.py __setattr__ will not work as expected!!
- """
- upgraded = False
- # code to upgrade from <= 0.0.8~b7 to >= 0.0.8~b8
- p = []
- for i in range(0, len(prefs), 3):
- if prefs[i] in [SEQUENCE_LETTER_V_0_0_8_B7, SESSION_SEQ_NUMBER_V_0_0_8_B7]:
- upgraded = True
- p.append(SEQUENCES)
- if prefs[i] == SEQUENCE_LETTER_V_0_0_8_B7:
- p.append(SEQUENCE_LETTER)
- p.append(prefs[i+1])
- else:
- p.append(SESSION_SEQ_NUMBER)
- p.append(prefs[i+2])
- else:
- p += prefs[i:i+3]
-
- assert(len(prefs)==len(p))
- return (upgraded, p)
-
-
-def upgradePreferencesToCurrent(imageRenamePrefs, subfolderPrefs, previousVersion):
- """Upgrades user preferences to current version
-
- returns True if the preferences were upgraded"""
-
- # only check image rename, for now....
- upgraded, imageRenamePrefs = _upgradePreferencesToCurrent(imageRenamePrefs, previousVersion)
- return (upgraded, imageRenamePrefs , subfolderPrefs)
-
-
-def usesJobCode(prefs):
- """ Returns True if the preferences contain a job code, else returns False"""
- for i in range(0, len(prefs), 3):
- if prefs[i] == JOB_CODE:
- return True
- return False
-
-def checkPreferencesForValidity(imageRenamePrefs, subfolderPrefs, videoRenamePrefs, videoSubfolderPrefs, version=config.version):
- """
- Checks preferences for validity (called at program startup)
-
- Returns true if the passed in preferences are valid, else returns False
- """
-
- if version == config.version:
- try:
- tests = ((imageRenamePrefs, ImageRenamePreferences),
- (subfolderPrefs, SubfolderPreferences),
- (videoRenamePrefs, VideoRenamePreferences),
- (videoSubfolderPrefs, VideoSubfolderPreferences))
- for i, Prefs in tests:
- p = Prefs(i, None)
- p.checkPrefsForValidity()
- except:
- return False
- return True
- else:
- defn = _getPrevPrefs(PREVIOUS_IMAGE_RENAME, DICT_IMAGE_RENAME_L0, version)
- try:
- checkPreferenceValid(defn, imageRenamePrefs)
- checkPreferenceValid(DICT_SUBFOLDER_L0, subfolderPrefs)
- checkPreferenceValid(DICT_VIDEO_SUBFOLDER_L0, videoSubfolderPrefs)
- checkPreferenceValid(DICT_VIDEO_RENAME_L0, videoRenamePrefs)
- except:
- return False
- return True
-
-def checkPreferenceValid(prefDefinition, prefs, modulo=3):
- """
- Checks to see if prefs are valid according to definition.
-
- prefs is a list of preferences.
- prefDefinition is a Dict specifying what is valid.
- modulo is how many list elements are equivalent to one line of preferences.
-
- Returns True if prefs match with prefDefinition,
- else raises appropriate error.
- """
-
- if (len(prefs) % modulo <> 0) or not prefs:
- raise PrefLengthError(prefs)
- else:
- for i in range(0, len(prefs), modulo):
- _checkPreferenceValid(prefDefinition, prefs[i:i+modulo])
-
- return True
-
-def _checkPreferenceValid(prefDefinition, prefs):
-
- key = prefs[0]
- value = prefs[1]
-
-
- if prefDefinition.has_key(key):
-
- nextPrefDefinition = prefDefinition[key]
-
- if value == None:
- # value should never be None, at any time
- raise PrefValueInvalidError((None, nextPrefDefinition))
-
- if nextPrefDefinition and not value:
- raise PrefValueInvalidError((value, nextPrefDefinition))
-
- if type(nextPrefDefinition) == type({}):
- return _checkPreferenceValid(nextPrefDefinition, prefs[1:])
- else:
- if type(nextPrefDefinition) == type([]):
- result = value in nextPrefDefinition
- if not result:
- raise PrefValueInvalidError((value, nextPrefDefinition))
- return True
- elif not nextPrefDefinition:
- return True
- else:
- result = nextPrefDefinition == value
- if not result:
- raise PrefKeyValue((value, nextPrefDefinition))
- return True
- else:
- raise PrefKeyError((key, prefDefinition[ORDER_KEY]))
-
-def filterSubfolderPreferences(prefList):
- """
- Filters out extraneous preference choices
- """
- prefs_changed = False
- continueCheck = True
- while continueCheck and prefList:
- continueCheck = False
- if prefList[0] == SEPARATOR:
- # Subfolder preferences should not start with a /
- prefList = prefList[3:]
- prefs_changed = True
- continueCheck = True
- elif prefList[-3] == SEPARATOR:
- # Subfolder preferences should not end with a /
- prefList = prefList[:-3]
- continueCheck = True
- prefs_changed = True
- else:
- for i in range(0, len(prefList) - 3, 3):
- if prefList[i] == SEPARATOR and prefList[i+3] == SEPARATOR:
- # Subfolder preferences should not contain two /s side by side
- continueCheck = True
- prefs_changed = True
- # note we are messing with the contents of the pref list,
- # must exit loop and try again
- prefList = prefList[:i] + prefList[i+3:]
- break
-
- return (prefs_changed, prefList)
-
-
-class PrefError(Exception):
- """ base class """
- def unpackList(self, l):
- """
- Make the preferences presentable to the user
- """
-
- s = ''
- for i in l:
- if i <> ORDER_KEY:
- s += "'" + i + "', "
- return s[:-2]
-
- def __str__(self):
- return self.msg
-
-class PrefKeyError(PrefError):
- def __init__(self, error):
- value = error[0]
- expectedValues = self.unpackList(error[1])
- self.msg = _("Preference key '%(key)s' is invalid.\nExpected one of %(value)s") % {
- 'key': value, 'value': expectedValues}
-
-
-class PrefValueInvalidError(PrefKeyError):
- def __init__(self, error):
- value = error[0]
- self.msg = _("Preference value '%(value)s' is invalid") % {'value': value}
-
-class PrefLengthError(PrefError):
- def __init__(self, error):
- self.msg = _("These preferences are not well formed:") + "\n %s" % self.unpackList(error)
-
-class PrefValueKeyComboError(PrefError):
- def __init__(self, error):
- self.msg = error
-
-
-def convertDateForStrftime(dateTimeUserChoice):
- try:
- return DATE_TIME_CONVERT[LIST_DATE_TIME_L2.index(dateTimeUserChoice)]
- except:
- raise PrefValueInvalidError(dateTimeUserChoice)
-
-
-class Comboi18n(gtk.ComboBox):
- """ very simple i18n version of the venerable combo box
- with one column displayed to the user.
-
- This combo box has two columns:
- 1. the first contains the actual value and is invisible
- 2. the second contains the translation of the first column, and this is what
- the users sees
- """
- def __init__(self):
- liststore = gtk.ListStore(str, str)
- gtk.ComboBox.__init__(self, liststore)
- cell = gtk.CellRendererText()
- self.pack_start(cell, True)
- self.add_attribute(cell, 'text', 1)
- # must name the combo box on pygtk used in Ubuntu 11.04, Fedora 15, etc.
- self.set_name('GtkComboBox')
-
- def append_text(self, text):
- model = self.get_model()
- model.append((text, _(text)))
-
- def get_active_text(self):
- model = self.get_model()
- active = self.get_active()
- if active < 0:
- return None
- return model[active][0]
-
-class ImageRenamePreferences:
- def __init__(self, prefList, parent, fileSequenceLock=None, sequences=None):
- """
- Exception raised if preferences are invalid.
-
- This should be caught by calling class."""
-
- self.parent = parent
- self.prefList = prefList
-
- # use variables for determining sequence numbers
- # there are two possibilities:
- # 1. this code is being called while being run from within a copy photos process
- # 2. it's being called from within the preferences dialog window
-
- self.fileSequenceLock = fileSequenceLock
- self.sequences = sequences
-
- self.job_code = ''
-
- # derived classes will have their own definitions, do not overwrite
- if not hasattr(self, "prefsDefnL0"):
- self.prefsDefnL0 = DICT_IMAGE_RENAME_L0
- self.defaultPrefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE]
- self.defaultRow = self.defaultPrefs
- self.stripForwardSlash = True
- self.L1DateCheck = IMAGE_DATE #used in _getDateComponent()
- self.component = pn.FILENAME_COMPONENT
-
-
- def initializeProblem(self, problem):
- """
- Set the problem tracker used in name generation
- """
- self.problem = problem
-
- def getProblems(self):
- """
- Returns Problem class if there were problems, else returns None.
- """
- if self.problem.has_problem():
- return self.problem
- else:
- return None
-
- def checkPrefsForValidity(self):
- """
- Checks image preferences validity
- """
-
- return checkPreferenceValid(self.prefsDefnL0, self.prefList)
-
- def formatPreferencesForPrettyPrint(self):
- """ returns a string useful for printing the preferences"""
-
- v = ''
-
- for i in range(0, len(self.prefList), 3):
- if (self.prefList[i+1] or self.prefList[i+2]):
- c = ':'
- else:
- c = ''
- s = "%s%s " % (self.prefList[i], c)
-
- if self.prefList[i+1]:
- s = "%s%s" % (s, self.prefList[i+1])
- if self.prefList[i+2]:
- s = "%s (%s)" % (s, self.prefList[i+2])
-
- v += s + "\n"
- return v
-
-
- def setJobCode(self, job_code):
- self.job_code = job_code
-
- def setDownloadStartTime(self, download_start_time):
- self.download_start_time = download_start_time
-
- def _getDateComponent(self):
- """
- Returns portion of new image / subfolder name based on date time.
- If the date is missing, will attempt to use the fallback date.
- """
-
- # step 1: get the correct value from metadata
- if self.L1 == self.L1DateCheck:
- if self.L2 == SUBSECONDS:
- d = self.metadata.subSeconds()
- if d == '00':
- self.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L2))
- return ''
- else:
- return d
- else:
- d = self.metadata.dateTime(missing=None)
-
- elif self.L1 == TODAY:
- d = datetime.datetime.now()
- elif self.L1 == YESTERDAY:
- delta = datetime.timedelta(days = 1)
- d = datetime.datetime.now() - delta
- elif self.L1 == DOWNLOAD_TIME:
- d = self.download_start_time
- else:
- raise("Date options invalid")
-
- # step 2: handle a missing value
- if not d:
- if self.fallback_date:
- try:
- d = datetime.datetime.fromtimestamp(self.fallback_date)
- except:
- self.problem.add_problem(self.component, pn.INVALID_DATE_TIME, '')
- return ''
- else:
- self.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L1))
- return ''
-
- try:
- return d.strftime(convertDateForStrftime(self.L2))
- except:
- self.problem.add_problem(self.component, pn.INVALID_DATE_TIME, d)
- return ''
-
- def _getFilenameComponent(self):
- """
- Returns portion of new image / subfolder name based on the file name
- """
-
- name, extension = os.path.splitext(self.existingFilename)
-
- if self.L1 == NAME_EXTENSION:
- filename = self.existingFilename
- elif self.L1 == NAME:
- filename = name
- elif self.L1 == EXTENSION:
- if extension:
- if not self.stripInitialPeriodFromExtension:
- # keep the period / dot of the extension, so the user does not
- # need to manually specify it
- filename = extension
- else:
- # having the period when this is used as a part of a subfolder name
- # is a bad idea!
- filename = extension[1:]
- else:
- self.problem.add_problem(self.component, pn.MISSING_FILE_EXTENSION)
- return ""
- elif self.L1 == IMAGE_NUMBER or self.L1 == VIDEO_NUMBER:
- n = re.search("(?P<image_number>[0-9]+$)", name)
- if not n:
- self.problem.add_problem(self.component, pn.MISSING_IMAGE_NUMBER)
- return ''
- else:
- image_number = n.group("image_number")
-
- if self.L2 == IMAGE_NUMBER_ALL:
- filename = image_number
- elif self.L2 == IMAGE_NUMBER_1:
- filename = image_number[-1]
- elif self.L2 == IMAGE_NUMBER_2:
- filename = image_number[-2:]
- elif self.L2 == IMAGE_NUMBER_3:
- filename = image_number[-3:]
- elif self.L2 == IMAGE_NUMBER_4:
- filename = image_number[-4:]
- else:
- raise TypeError("Incorrect filename option")
-
- if self.L2 == UPPERCASE:
- filename = filename.upper()
- elif self.L2 == LOWERCASE:
- filename = filename.lower()
-
- return filename
-
- def _getMetadataComponent(self):
- """
- Returns portion of new image / subfolder name based on the metadata
-
- Note: date time metadata found in _getDateComponent()
- """
-
- if self.L1 == APERTURE:
- v = self.metadata.aperture()
- elif self.L1 == ISO:
- v = self.metadata.iso()
- elif self.L1 == EXPOSURE_TIME:
- v = self.metadata.exposureTime(alternativeFormat=True)
- elif self.L1 == FOCAL_LENGTH:
- v = self.metadata.focalLength()
- elif self.L1 == CAMERA_MAKE:
- v = self.metadata.cameraMake()
- elif self.L1 == CAMERA_MODEL:
- v = self.metadata.cameraModel()
- elif self.L1 == SHORT_CAMERA_MODEL:
- v = self.metadata.shortCameraModel()
- elif self.L1 == SHORT_CAMERA_MODEL_HYPHEN:
- v = self.metadata.shortCameraModel(includeCharacters = "\-")
- elif self.L1 == SERIAL_NUMBER:
- v = self.metadata.cameraSerial()
- elif self.L1 == SHUTTER_COUNT:
- v = self.metadata.shutterCount()
- if v:
- v = int(v)
- padding = LIST_SHUTTER_COUNT_L2.index(self.L2) + 3
- formatter = '%0' + str(padding) + "i"
- v = formatter % v
-
- elif self.L1 == OWNER_NAME:
- v = self.metadata.ownerName()
- else:
- raise TypeError("Invalid metadata option specified")
- if self.L1 in [CAMERA_MAKE, CAMERA_MODEL, SHORT_CAMERA_MODEL,
- SHORT_CAMERA_MODEL_HYPHEN, OWNER_NAME]:
- if self.L2 == UPPERCASE:
- v = v.upper()
- elif self.L2 == LOWERCASE:
- v = v.lower()
- if not v:
- self.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L1))
- return v
-
-
- def _formatSequenceNo(self, value, amountToPad):
- padding = LIST_SEQUENCE_NUMBERS_L2.index(amountToPad) + 1
- formatter = '%0' + str(padding) + "i"
- return formatter % value
-
-
- def _calculateLetterSequence(self, sequence):
-
- def _letters(x):
- """
- Adapted from algorithm at http://en.wikipedia.org/wiki/Hexavigesimal
- """
- v = ''
- while x > 25:
- r = x % 26
- x= x / 26 - 1
- v = string.lowercase[r] + v
- v = string.lowercase[x] + v
-
- return v
-
-
- v = _letters(sequence)
- if self.L2 == UPPERCASE:
- v = v.upper()
-
- return v
-
- def _getSubfolderSequenceNo(self):
- """
- Add a sequence number to the filename
-
- * Sequence numbering is per subfolder
- * Assume the user might actually have a (perhaps odd) reason to have more
- than one subfolder sequence number in the same file name
- """
-
- self.subfolderSeqNoInstanceInFilename += 1
-
- if self.downloadSubfolder:
- subfolder = self.downloadSubfolder + str(self.subfolderSeqNoInstanceInFilename)
- else:
- subfolder = "__subfolder__" + str(self.subfolderSeqNoInstanceInFilename)
-
- if self.fileSequenceLock:
- with self.fileSequenceLock:
- v = self.sequenceNos.calculate(subfolder)
- v = self.formatSequenceNo(v, self.L1)
- else:
- v = self.sequenceNos.calculate(subfolder)
- v = self.formatSequenceNo(v, self.L1)
-
- return v
-
- def _getSessionSequenceNo(self):
- return self._formatSequenceNo(self.sequences.getSessionSequenceNoUsingCounter(self.sequenceCounter), self.L2)
-
- def _getDownloadsTodaySequenceNo(self):
- return self._formatSequenceNo(self.sequences.getDownloadsTodayUsingCounter(self.sequenceCounter), self.L2)
-
-
- def _getStoredSequenceNo(self):
- return self._formatSequenceNo(self.sequences.getStoredSequenceNoUsingCounter(self.sequenceCounter), self.L2)
-
- def _getSequenceLetter(self):
- return self._calculateLetterSequence(self.sequences.getSequenceLetterUsingCounter(self.sequenceCounter))
-
-
- def _getSequencesComponent(self):
- if self.L1 == DOWNLOAD_SEQ_NUMBER:
- return self._getDownloadsTodaySequenceNo()
- elif self.L1 == SESSION_SEQ_NUMBER:
- return self._getSessionSequenceNo()
- elif self.L1 == SUBFOLDER_SEQ_NUMBER:
- return self._getSubfolderSequenceNo()
- elif self.L1 == STORED_SEQ_NUMBER:
- return self._getStoredSequenceNo()
- elif self.L1 == SEQUENCE_LETTER:
- return self._getSequenceLetter()
-
- def _getComponent(self):
- try:
- if self.L0 == DATE_TIME:
- return self._getDateComponent()
- elif self.L0 == TEXT:
- return self.L1
- elif self.L0 == FILENAME:
- return self._getFilenameComponent()
- elif self.L0 == METADATA:
- return self._getMetadataComponent()
- elif self.L0 == SEQUENCES:
- return self._getSequencesComponent()
- elif self.L0 == JOB_CODE:
- return self.job_code
- elif self.L0 == SEPARATOR:
- return os.sep
- except:
- self.problem.add_problem(self.component, pn.ERROR_IN_GENERATION, _(self.L0))
- return ''
-
- def _getValuesFromList(self):
- for i in range(0, len(self.prefList), 3):
- yield (self.prefList[i], self.prefList[i+1], self.prefList[i+2])
-
-
- def _generateName(self, metadata, existingFilename, stripCharacters, subfolder, stripInitialPeriodFromExtension, sequence, fallback_date):
- self.metadata = metadata
- self.existingFilename = existingFilename
- self.stripInitialPeriodFromExtension = stripInitialPeriodFromExtension
- self.fallback_date = fallback_date
-
- name = ''
-
- #the subfolder in which the image will be downloaded to
- self.downloadSubfolder = subfolder
-
- self.sequenceCounter = sequence
-
- for self.L0, self.L1, self.L2 in self._getValuesFromList():
- v = self._getComponent()
- if v:
- name += v
-
- if stripCharacters:
- for c in r'\:*?"<>|':
- name = name.replace(c, '')
-
- if self.stripForwardSlash:
- name = name.replace('/', '')
-
- name = name.strip()
-
- return name
-
- def generateNameUsingPreferences(self, metadata, existingFilename=None,
- stripCharacters = False, subfolder=None,
- stripInitialPeriodFromExtension=False,
- sequencesPreliminary = True,
- sequence_to_use = None,
- fallback_date = None):
- """
- Generate a filename for the photo or video in string format based on user preferences.
-
- Returns the name in string format
-
- Any problems encountered during the generation of the name can be accessed
- through the method getProblems()
- """
-
- if self.sequences:
- if sequence_to_use is not None:
- sequence = sequence_to_use
- elif sequencesPreliminary:
- sequence = self.sequences.getPrelimSequence()
- else:
- sequence = self.sequences.getFinalSequence()
- else:
- sequence = 0
-
- return self._generateName(metadata, existingFilename, stripCharacters, subfolder,
- stripInitialPeriodFromExtension, sequence, fallback_date)
-
- def generateNameSequencePossibilities(self, metadata, existingFilename,
- stripCharacters=False, subfolder=None,
- stripInitialPeriodFromExtension=False):
-
- """ Generates the possible image names using the sequence numbers / letter possibilities"""
-
- for sequence in self.sequences.getSequencePossibilities():
- yield self._generateName(metadata, existingFilename, stripCharacters, subfolder,
- stripInitialPeriodFromExtension, sequence)
-
- def filterPreferences(self):
- """
- Filters out extraneous preference choices
- Expected to be implemented in derived classes when needed
- """
- pass
-
- def needImageMetaDataToCreateUniqueName(self):
- """
- Returns True if an image's metadata is essential to properly generate a unique image name
-
- Image names should be unique. Some images may not have metadata. If
- only non-dynamic components make up the rest of an image name
- (e.g. text specified by the user), then relying on metadata will likely
- produce duplicate names.
-
- File extensions are not considered dynamic.
-
- This is NOT a general test to see if unique filenames can be generated. It is a test
- to see if an image's metadata is needed.
- """
- hasMD = hasDynamic = False
-
- for e in METADATA_ELEMENTS:
- if e in self.prefList:
- hasMD = True
- break
-
- if hasMD:
- for e in DYNAMIC_NON_METADATA_ELEMENTS:
- if e in self.prefList:
- if e == FILENAME and (NAME_EXTENSION in self.prefList or
- NAME in self.prefList or
- IMAGE_NUMBER in self.prefList):
- hasDynamic = True
- break
-
- if hasMD and not hasDynamic:
- return True
- else:
- return False
-
- def usesSequenceElements(self):
- """ Returns true if any sequence numbers or letters are used to generate the filename """
-
- for e in SEQUENCE_ELEMENTS:
- if e in self.prefList:
- return True
-
- return False
-
- def usesTheSequenceElement(self, e):
- """ Returns true if a stored sequence number is used to generate the filename """
- return e in self.prefList
-
-
- def _createCombo(self, choices):
- combobox = Comboi18n()
- for text in choices:
- combobox.append_text(text)
- return combobox
-
- def getDefaultRow(self):
- """
- returns a list of default widgets
- """
- return self.getWidgetsBasedOnUserSelection(self.defaultRow)
-
- def _getPreferenceWidgets(self, prefDefinition, prefs, widgets):
- key = prefs[0]
- value = prefs[1]
-
- # supply a default value if the user has not yet chosen a value!
- if not key:
- key = prefDefinition[ORDER_KEY][0]
-
- if not key in prefDefinition:
- raise PrefKeyError((key, prefDefinition.keys()))
-
-
- list0 = prefDefinition[ORDER_KEY]
-
- # the first widget will always be a combo box
- widget0 = self._createCombo(list0)
- widget0.set_active(list0.index(key))
-
- widgets.append(widget0)
-
- if key == TEXT:
- widget1 = gtk.Entry()
- widget1.set_text(value)
-
- widgets.append(widget1)
- widgets.append(None)
- return
- elif key in [SEPARATOR, JOB_CODE]:
- widgets.append(None)
- widgets.append(None)
- return
- else:
- nextPrefDefinition = prefDefinition[key]
- if type(nextPrefDefinition) == type({}):
- return self._getPreferenceWidgets(nextPrefDefinition,
- prefs[1:],
- widgets)
- else:
- if type(nextPrefDefinition) == type([]):
- widget1 = self._createCombo(nextPrefDefinition)
- if not value:
- value = nextPrefDefinition[0]
- try:
- widget1.set_active(nextPrefDefinition.index(value))
- except:
- raise PrefValueInvalidError((value, nextPrefDefinition))
-
- widgets.append(widget1)
- else:
- widgets.append(None)
-
- def getWidgetsBasedOnPreferences(self):
- """
- Yields a list of widgets and their callbacks based on the users preferences.
-
- This list is equivalent to one row of preferences when presented to the
- user in the Plus Minus Table.
- """
-
- for L0, L1, L2 in self._getValuesFromList():
- prefs = [L0, L1, L2]
- widgets = []
- self._getPreferenceWidgets(self.prefsDefnL0, prefs, widgets)
- yield widgets
-
-
- def getWidgetsBasedOnUserSelection(self, selection):
- """
- Returns a list of widgets and their callbacks based on what the user has selected.
-
- Selection is the values the user has chosen thus far in comboboxes.
- It determines the contents of the widgets returned.
- It should be a list of three values, with None for values not chosen.
- For values which are None, the first value in the preferences
- definition is chosen.
-
- """
- widgets = []
-
- self._getPreferenceWidgets(self.prefsDefnL0, selection, widgets)
- return widgets
-
-def getVideoMetadataComponent(video):
- """
- Returns portion of video / subfolder name based on the metadata
-
- This is outside of a class definition because of the inheritence
- hierarchy.
- """
-
- problem = None
- if video.L1 == CODEC:
- v = video.metadata.codec()
- elif video.L1 == WIDTH:
- v = video.metadata.width()
- elif video.L1 == HEIGHT:
- v = video.metadata.height()
- elif video.L1 == FPS:
- v = video.metadata.framesPerSecond()
- elif video.L1 == LENGTH:
- v = video.metadata.length()
- else:
- raise TypeError("Invalid metadata option specified")
- if video.L1 in [CODEC]:
- if video.L2 == UPPERCASE:
- v = v.upper()
- elif video.L2 == LOWERCASE:
- v = v.lower()
- if not v:
- video.problem.add_problem(video.component, pn.MISSING_METADATA, _(video.L1))
- return v
-
-class VideoRenamePreferences(ImageRenamePreferences):
- def __init__(self, prefList, parent, fileSequenceLock=None, sequences=None):
- self.prefsDefnL0 = DICT_VIDEO_RENAME_L0
- self.defaultPrefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE]
- self.defaultRow = self.defaultPrefs
- self.stripForwardSlash = True
- self.L1DateCheck = VIDEO_DATE
- self.component = pn.FILENAME_COMPONENT
- ImageRenamePreferences.__init__(self, prefList, parent, fileSequenceLock, sequences)
-
- def _getMetadataComponent(self):
- """
- Returns portion of video / subfolder name based on the metadata
-
- Note: date time metadata found in _getDateComponent()
- """
- return getVideoMetadataComponent(self)
-
-
-class SubfolderPreferences(ImageRenamePreferences):
- def __init__(self, prefList, parent):
- self.prefsDefnL0 = DICT_SUBFOLDER_L0
- self.defaultPrefs = DEFAULT_SUBFOLDER_PREFS
- self.defaultRow = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]]
- self.stripForwardSlash = False
- self.L1DateCheck = IMAGE_DATE
- self.component = pn.SUBFOLDER_COMPONENT
- ImageRenamePreferences.__init__(self, prefList, parent)
-
- self.stripExtraneousWhiteSpace = re.compile(r'\s*%s\s*' % os.sep)
-
- def generateNameUsingPreferences(self, photo, existingFilename=None,
- stripCharacters = False, fallback_date = None):
- """
- Generate a filename for the photo in string format based on user prefs.
-
- Returns a tuple of two strings:
- - the name
- - any problems generating the name. If blank, there were no problems
- """
-
- subfolders = ImageRenamePreferences.generateNameUsingPreferences(
- self, photo,
- existingFilename, stripCharacters,
- stripInitialPeriodFromExtension=True,
- fallback_date=fallback_date)
- # subfolder value must never start with a separator, or else any
- # os.path.join function call will fail to join a subfolder to its
- # parent folder
- if subfolders:
- if subfolders[0] == os.sep:
- subfolders = subfolders[1:]
-
- # remove any spaces before and after a directory name
- if subfolders and stripCharacters:
- subfolders = self.stripExtraneousWhiteSpace.sub(os.sep, subfolders)
-
- return subfolders
-
- def filterPreferences(self):
- filtered, prefList = filterSubfolderPreferences(self.prefList)
- if filtered:
- self.prefList = prefList
-
- def needMetaDataToCreateUniqueName(self):
- """
- Returns True if metadata is essential to properly generate subfolders
-
- This will be the case if the only components are metadata and separators
- """
-
- for e in self.prefList:
- if (not e) and ((e not in METADATA_ELEMENTS) or (e <> SEPARATOR)):
- return True
-
- return False
-
-
-
-
- def checkPrefsForValidity(self):
- """
- Checks subfolder preferences validity above and beyond image name checks.
-
- See parent method for full description.
-
- Subfolders have additional requirments to that of image names.
- """
- v = ImageRenamePreferences.checkPrefsForValidity(self)
- if v:
- # peform additional checks:
- # 1. do not start with a separator
- # 2. do not end with a separator
- # 3. do not have two separators in a row
- # these three rules will ensure something else other than a
- # separator is specified
- L1s = []
- for i in range(0, len(self.prefList), 3):
- L1s.append(self.prefList[i])
-
- if L1s[0] == SEPARATOR:
- raise PrefValueKeyComboError(_("Subfolder preferences should not start with a %s") % os.sep)
- elif L1s[-1] == SEPARATOR:
- raise PrefValueKeyComboError(_("Subfolder preferences should not end with a %s") % os.sep)
- else:
- for i in range(len(L1s) - 1):
- if L1s[i] == SEPARATOR and L1s[i+1] == SEPARATOR:
- raise PrefValueKeyComboError(_("Subfolder preferences should not contain two %s one after the other") % os.sep)
- return v
-
-
-
-class VideoSubfolderPreferences(SubfolderPreferences):
- def __init__(self, prefList, parent):
- SubfolderPreferences.__init__(self, prefList, parent)
- self.prefsDefnL0 = DICT_VIDEO_SUBFOLDER_L0
- self.defaultPrefs = DEFAULT_VIDEO_SUBFOLDER_PREFS
- self.defaultRow = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[0]]
- self.L1DateCheck = VIDEO_DATE
- self.component = pn.SUBFOLDER_COMPONENT
-
- def _getMetadataComponent(self):
- """
- Returns portion of video / subfolder name based on the metadata
-
- Note: date time metadata found in _getDateComponent()
- """
- return getVideoMetadataComponent(self)
-
-class Sequences:
- """
- Holds sequence numbers and letters used in generating filenames.
- The same instance of this class is shared among all threads.
- """
- def __init__(self, downloadsToday, storedSequenceNo):
- self.subfolderSequenceNo = {}
- self.sessionSequenceNo = 1
- self.sequenceLetter = 0
-
- self.setUseOfSequenceElements(False, False)
-
- self.assignedSequenceCounter = 1
- self.reset(downloadsToday, storedSequenceNo)
-
- def setUseOfSequenceElements(self, usesSessionSequenceNo, usesSequenceLetter):
- self.usesSessionSequenceNo = usesSessionSequenceNo
- self.usesSequenceLetter = usesSequenceLetter
-
- def reset(self, downloadsToday, storedSequenceNo):
- self.downloadsToday = downloadsToday
- self.downloadsTodayOffset = 0
- self.storedSequenceNo = storedSequenceNo
- if self.usesSessionSequenceNo:
- self.sessionSequenceNo = self.sessionSequenceNo + self.assignedSequenceCounter - 1
- if self.usesSequenceLetter:
- self.sequenceLetter = self.sequenceLetter + self.assignedSequenceCounter - 1
- self.doNotAddToPool = False
- self.pool = []
- self.poolSequenceCounter = 0
- self.assignedSequenceCounter = 1
-
- def getPrelimSequence(self):
- if self.doNotAddToPool:
- self.doNotAddToPool = False
- else:
- # increment pool sequence number
- self.poolSequenceCounter += 1
- self.pool.append(self.poolSequenceCounter)
-
- return self.poolSequenceCounter
-
- def getFinalSequence(self):
- # get oldest queue value
- # remove from queue or flag it should be removed
-
- return self.assignedSequenceCounter
-
- def getSequencePossibilities(self):
- for i in self.pool:
- yield i
-
- def getSessionSequenceNo(self):
- return self.sessionSequenceNo + self.assignedSequenceCounter - 1
-
- def getSessionSequenceNoUsingCounter(self, counter):
- return self.sessionSequenceNo + counter - 1
-
- def setSessionSequenceNo(self, value):
- self.sessionSequenceNo = value
-
- def setStoredSequenceNo(self, value):
- self.storedSequenceNo = value
-
- def getDownloadsTodayUsingCounter(self, counter):
- return self.downloadsToday + counter - self.downloadsTodayOffset
-
- def setDownloadsToday(self, value):
- self.downloadsToday = value
- self.downloadsTodayOffset = self.assignedSequenceCounter - 1
-
- def getStoredSequenceNoUsingCounter(self, counter):
- return self.storedSequenceNo + counter
-
- def getSequenceLetterUsingCounter(self, counter):
- return self.sequenceLetter + counter - 1
-
- def imageCopyFailed(self):
- self.doNotAddToPool = True
-
- def imageCopySucceeded(self):
- self.increment()
-
- def increment(self):
- assert(self.assignedSequenceCounter == self.pool[0])
- self.assignedSequenceCounter += 1
- self.pool = self.pool[1:]
- #assert(len(self.pool) > 0)
-
-
-
-
-if __name__ == '__main__':
- import sys
- import os.path
- from metadata import MetaData
-
- if False:
- if (len(sys.argv) != 2):
- print 'Usage: ' + sys.argv[0] + ' path/to/photo/containing/metadata'
- sys.exit(1)
- else:
- p0 = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE]
- p1 = [FILENAME, NAME_EXTENSION, LOWERCASE]
- p2 = [METADATA, APERTURE, None]
- p3 = [FILENAME, IMAGE_NUMBER, IMAGE_NUMBER_ALL]
- p4 = [METADATA, CAMERA_MODEL, ORIGINAL_CASE]
- p5 = [TEXT, '-', None]
- p6 = [TEXT, 'Job', None]
-
- p = [p0, p1, p2, p3, p4]
- p = [p6 + p5 + p2 + p5 + p3]
-
- d0 = [DATE_TIME, IMAGE_DATE, 'YYYYMMDD']
- d1 = [DATE_TIME, IMAGE_DATE, 'HHMMSS']
- d2 = [DATE_TIME, IMAGE_DATE, SUBSECONDS]
-
- d = [d0 + d1 + d2]
-
- fullpath = sys.argv[1]
- path, filename = os.path.split(fullpath)
-
- m = MetaData(fullpath)
- m.readMetadata()
-
- for pref in p:
- i = ImageRenamePreferences(pref, None)
- print i.generateNameUsingPreferences(m, filename)
-
- for pref in d:
- i = ImageRenamePreferences(pref, None)
- print i.generateNameUsingPreferences(m, filename)
- else:
- prefs = [SEQUENCES, SESSION_SEQ_NUMBER, SEQUENCE_NUMBER_3]
-# prefs = ['Filename2', NAME_EXTENSION, UPPERCASE]
- print checkPreferenceValid(DICT_IMAGE_RENAME_L0, prefs)