#!/usr/local/bin/pythono """ Python 2.4 version of Poser Compressor 9/17/05 This will not run fully in PoserPython. There seems to have been some change in the way tuples and strings are handled, somehow. It runs on Python 2.4/Tk 8.4, however. This script is an adaptation of the compression and decompression scripts which shipped with Poser 5. I have made use of Tromnek's altered version of the Poser 5 compression script, which can be found in the archives at the Renderosity Python forum. Other people have done the hard work (and the more effective coding, I'm sure). I have tried to implement the compression functions in ways that are more flexible and easier to use. Mainly that means I slapped a GUI on it. :) I have tried to annotate my changes to the scipts from which this is derived. You should assume that any errors are mine, not those of Tromnek or the original programmer of the script. I seem to understand enough to make it work, but not necessarily enough to have been careful and deliberate - or artful - about it. This script allows you to browse for single files or entire folders to process using PoserPython's Gzip compression. You can also select an option to process all subfolders, as with the default Poser 5 scripts. This script also allows control over the file types which will be processed, without the need to edit the script to change the file tables. Run the program and press "Help" to get basic instructions. This is untested on Macintosh. I have put code in place to update the Mac typeTables when new types are added by the user, but I can't test this to see if I've made the right assumptions about the needs of the Macintosh. I assume, here, that the typeTables don't need to be cleared at all, because they are accessed to subprocess the information, rather than being accessed in the basic processing of the files. So I add to the tables, but never clear them. My apologies if I've guessed incorrectly about the process. This program is set up to automatically close when a recursive search is completed. The original scripts did the same thing. I would prefer to let the program keep running, but something in os.walk seems to alter the value of initialdir. As a result, folder browsing after recursion always starts at C:, rather than the current working directory. I can't seem to alter that. Rather than risk having a cancelled folder browse send the program tearing through the whole C: drive, if I've made any as-yet-unnoticed errors in the coding, I removed the option to do further folder browsing after a recursive search is done. If anyone knows how to fix this, feel free to do so. And I'd love to know what you did. Once again, thanks to Tromnek. Cagedrei@aol.com """ # From Tromnek's edit. #------------------------------------------------------------------------------- # # CompressPoserFiles.py # Recursively Z-lib compresses all Poser-related files in the desired # directory. Optionally deletes original uncompressed files to save # disk space. # #------------------------------------------------------------------------------- # Modified 3/6/2005, # Kenneth R. Mort (aka TromNek, http://www.renderosity.com/members.ez) # changes: # compressFile() # File extension check made case insensitive, test that it was found at the end of the filename. # Store the original file name in the compressed file header. # Before deleting original file, check that the file size matches the size stored in the compressed file. # visit() # File extension check made case insensitive, test that it was found at the end of the filename. # main # NOTE: This has only been tested on Windows. Someone please check the logic for the Mac. # Enable running in both Poser and native Python. # Check path for 'Runtime', if found have compressed pathname header start there. # Make sure that the drive letter is not stored in the compressed pathname header. #------------------------------------------------------------------------------- from Tkinter import * import sys import tkFileDialog import gzip import string import os import tkMessageBox chunksize = 4096 fileToCompress = 0 fileToUncompress = 0 deleteOriginals = 0 onameC = 0 onameU = 0 proceed = 0 message = "." names = "NONE" dirname = "NONE" AddTo = " " AddTo2 = " " addElem = " " root = Tk() #-------------------------------------------------------------------------------- # Suffixes. #-------------------------------------------------------------------------------- suffixTableC = { '.pz3' : '.pzz', '.pz2' : '.p2z', '.cr2' : '.crz', '.cm2' : '.cmz', '.lt2' : '.ltz', '.hd2' : '.hdz', '.hr2' : '.hrz', '.pp2' : '.ppz', '.mt5' : '.mz5', '.fc2' : '.fcz', '.obj' : '.obz' } suffixTableU = { '.pzz' : '.pz3', '.p2z' : '.pz2', '.crz' : '.cr2', '.cmz' : '.cm2', '.ltz' : '.lt2', '.hdz' : '.hd2', '.hrz' : '.hr2', '.ppz' : '.pp2', '.mz5' : '.mt5', '.fcz' : '.fc2', '.obz' : '.obj' } openListC = '*.pz3 *.pz2 *.cr2 *.cm2 *.lt2 *.hd2 *.hr2 *.pp2 *.mt5 *.fc2 *.obj' openListU = '*.pzz *.p2z *.crz *.cmz *.ltz *.hdz *.ppz *.mz5 *.fcz *.obz' #-------------------------------------------------------------------------------- # Figure out which OS we're running #-------------------------------------------------------------------------------- macver = 0 winver = 0 if(os.name == 'mac'): macver = 1 separator = ':' elif(os.name == 'dos' or os.name == 'nt'): winver = 1 separator = '\\' else: raise 'unrecognized operating system\n' if(macver): #---------------------------------------------------------------------------- # Keep a table for type #---------------------------------------------------------------------------- typeTableC = { '.pzz' : 'PZZ ', '.p2z' : 'pz2Z', #Cage: I'm unable to test it, but I'm '.crz' : 'cr2Z', #assuming that these Mac tables don't need to be '.cmz' : 'cm2Z', #cleared and re-filled along with the others. '.ltz' : 'lt2Z', #New values need to be added for user-entered '.hdz' : 'hd2Z', ##file extensions. That takes place in the '.hrz' : 'fc2Z', #MyDialog class at the bottom of the script. '.ppz' : 'pp2Z', '.mz5' : 'mt5Z', '.fcz' : 'fc2Z', } typeTableU = { '.pz3':'PZ3 ', '.pz2':'pz2 ', '.cr2':'cr2 ', '.cm2':'cm2 ', '.lt2':'lt2 ', '.hd2':'hd2 ', '.hr2':'fc2 ', #Is this an error? It's consistent in both lists.... '.pp2':'pp2 ', '.mt5':'mt5 ', '.fc2':'fc2 ' } #----------------------------------------------------------------------------------------- def compressFile(fileToCompress, suffix, newSuffix, deleteOriginals): #P5 and Tromnek #if(string.find(fileToCompress, 'Default Guy.cr2') != -1): if(string.find(string.lower(fileToCompress), 'default guy.cr2') != -1): #TromNek case insensitive test return 0 newFileName = fileToCompress #extIndex = string.find(fileToCompress, suffix) extIndex = string.rfind(string.lower(fileToCompress), suffix) #TromNek, a more exact file extension search #if (extIndex == -1): if ( (extIndex + len(suffix)) != len(fileToCompress)): #TromNek, is it really the extension return -1 else: newFileName = newFileName[:extIndex] + newSuffix # change .*z3 to .*zz try: pz3 = open(fileToCompress, 'rb') except: return -2 try: #TromNek open a file object first pzzfo = open(newFileName, 'w+b') pzzfo.truncate(0) except: return -2 #pzz = gzip.GzipFile(newFileName, 'wb') pzz = gzip.GzipFile(fileobj=pzzfo, mode='wb') #TromNek pass gzip the file object instead of the name while 1: chunk = pz3.read(chunksize) # do the compression if(chunk == ""): break pzz.write(chunk) pz3.close() pzz.close() #TromNek next 13 lines hdrNameOffset = 10 # If there's a file name, where is is pzzfo.seek(hdrNameOffset + extIndex,0) # Seek the beginning of the file extension chunk = pzzfo.read( len(suffix) ) if chunk == newSuffix: # Make extra sure we want to do this pzzfo.seek(hdrNameOffset + extIndex,0) # Seek the beginning of the file extension, again pzzfo.write( suffix ) else: print "!!! Couldn't find file extension in header !!!" import struct pzzfo.seek( -4, 2 ) # original file size stored by GzipFile origfsize = struct.unpack("', newFileName if(deleteOriginals == 1): import os if os.stat(fileToCompress)[6] != origfsize: #TromNek minimum sanity check before deletion print '!!!Original file size does not equal value stored in gzip file!!! NOT DELETING ORIGINAL !!! ', os.stat(fileToCompress)[6], " != ",origfsize else: try: os.remove(fileToCompress) print ' (', fileToCompress, 'deleted)' except: print ' (Could not delete', fileToCompress print ' Permissions set to Read-Only?' #------------------------------------------------------------------------------------------------------ def uncompressFile(fileToUnCompress, suffix, newSuffix, deleteOriginals): #P5 and Tromnek if(string.find(fileToUnCompress, 'Default Guy.cr2') != -1): #if(string.find(string.lower(fileToCompress), 'default guy.cr2') != -1): #TromNek case insensitive test return 0 newFileName = fileToUnCompress extIndex = string.find(fileToUnCompress, suffix) #extIndex = string.rfind(string.lower(fileToCompress), suffix) #TromNek, a more exact file extension search if (extIndex == -1): #if ( (extIndex + len(suffix)) != len(fileToCompress)): #TromNek, is it really the extension return -1 else: newFileName = newFileName[:extIndex] + newSuffix # change .*z3 to .*zz try: pzz = gzip.GzipFile(fileToUnCompress, 'rb') except: return -2 pz3 = open(newFileName, 'wb') while 1: chunk = pzz.read(chunksize) # do the uncompression if(chunk == ""): break pz3.write(chunk) pz3.close() pzz.close() if(macver): # for mac version, we need to change file's import macfs # type and creator fs = macfs.FSSpec(newFileName) fs.SetCreatorType('PZ3A', typeTableU[newSuffix]) print ' *** ', fileToUnCompress, ' ***' print ' -->', newFileName if(deleteOriginals == 1): import os try: os.remove(fileToUnCompress) print ' (', fileToUnCompress, 'deleted)' except: print ' (Could not delete', fileToUnCompress print ' Permissions set to Read-Only?' #------------------------------------------------------------------------------------------------ def visitC(something, dirname, names): #P5, Tromnek, and "but it's my only line!" if (recursive == 1): if fileToUncompress == 0: print 'Looking under directory:', dirname, '------' for name in names: for key in suffixTableC.keys(): #if (string.find(name, key) != -1): extIndex = string.rfind(string.lower(name), key ) #TromNek make sure it really is the extension. if ( (extIndex + len(key)) == len(name)): compressFile(dirname + separator + name, key, suffixTableC[key], deleteOriginals) break print from Tkinter import * #------------------------------------------------------------------------------------------ def visitU(something, dirname, names): #P5 and Tromnek w/ one line added by Cage if (recursive == 1): if fileToCompress == 0: print 'Looking under directory:', dirname, '------' for name in names: for key in suffixTableU.keys(): #if (string.find(name, key) != -1): extIndex = string.rfind(string.lower(name), key ) #TromNek make sure it really is the extension. if ( (extIndex + len(key)) == len(name)): uncompressFile(dirname + separator + name, key, suffixTableU[key], deleteOriginals) break print from Tkinter import * #----------------------------------------------------------------------------------------------- #Ockham likes to point out that this part is Tkinter, so: this part is Tkinter. Except for the middle. Well, some. A bit. class App: def __init__(self, master, textMessage): global recurse, recursive, deleteOriginals, custUse recurse = IntVar() recurse.set(0) recursive = IntVar() recursive.set(0) custUse = IntVar() custUse.set(0) self.safety = 1 #To prevent "custom file list" checkbutton from looping at start self.refresh = 0 self.master = master master.title("Poser Compressor") self.ButtonFrame = Frame(self.master,borderwidth=2,relief=RIDGE) self.ButtonFrame.grid(row=0,column=2) self.ListFrame = Frame(self.master,borderwidth=2,relief=RIDGE) self.ListFrame.grid(row = 0, column = 0) self.Label = Label(self.ListFrame,text="File Types:").grid(row=1, column=1) #Listbox self.ListScroll = Scrollbar(self.ListFrame, orient=VERTICAL) self.ListScroll.grid( row=2, column=0,sticky=N+S+E) self.List = Listbox(self.ListFrame, height=20, width=10,selectmode=MULTIPLE,yscrollcommand = self.ListScroll.set) self.List.grid( row=2, column=1) self.ListScroll["command"] = self.List.yview TypeList = dict.items(suffixTableC) #Fill the listbox from the compress table for i in TypeList: self.List.insert(END,i) #Buttons self.Label = Label(self.ButtonFrame,text="Browse For Files:").grid(row=0, column=0) self.Label = Label(self.ButtonFrame,text="Browse for one or more files,").grid(row=2,column=0) self.Label = Label(self.ButtonFrame,text="or select checkbuttons to process").grid(row=3,column=0) self.Label = Label(self.ButtonFrame,text="entire folders and subfolders.").grid(row=4,column=0) self.buttonCompress = Button(self.ButtonFrame, text="Compress", command=self.openfileC) self.buttonCompress.grid(row = 10, column = 0) self.buttonUncompress = Button(self.ButtonFrame, text="Uncompress", command=self.openfileU) self.buttonUncompress.grid(row = 20, column = 0) self.buttonAddFile = Button(self.ButtonFrame, text="Add File Type", command=self.AddFile) self.buttonAddFile.grid(row = 30, column = 0) self.buttonClose = Button(self.ButtonFrame, text="Close", command=self.die) self.buttonClose.grid(row = 70, column = 0) self.buttonHelp = Button(self.ButtonFrame, text="Help", command=self.HelpMe) self.buttonHelp.grid(row=60, column=0) self.List.bind("",self.handleSelect) #Checkboxes self.deleteOrig = Checkbutton(self.ButtonFrame,text="Delete original files after compressing", variable=deleteOriginals, command=self.delFiles) self.deleteOrig.grid(row = 35, column = 0) self.EntireFolder = Checkbutton(self.ButtonFrame,text="Process Entire Folder", variable=recurse, command=self.openfileR) self.EntireFolder.grid(row = 40, column = 0) self.Subfolders = Checkbutton(self.ButtonFrame, text="Include Subfolders", variable=recursive, command=self.openfileS) self.Subfolders.grid(row=45, column = 0) self.UseCustom = Checkbutton(self.ButtonFrame,text="Use Only Selected File Types", variable=custUse, command=self.handleCustom) self.UseCustom.grid(row=50, column = 0) self.Label = Label(self.master,text="Double-click to remove file types").grid(row = 2, column = 0) #--------------------------------------------------------------------------------------------------- self.openfileR() #Priming the system to fend off IntVar value problems self.openfileS() #Emulate first clicks of checkbuttons self.handleCustom() #Okay, so it's a kludgy workaround.... def handleSelect(self,event): #self.handleGo() self.List.delete(ACTIVE) #Delete listbox entries w/ double-click def HelpMe(self): tkMessageBox.showinfo("Instructions:","-->Browse for one or more files by pressing 'Compress' or 'Uncompress'.\012" "-->Browse for a folder by selecting 'Process Entire Folder' before pressing 'Compress'\012" " or 'Uncompress'.\012" "-->Select 'Include Subfolders' together with 'Process Entire Folder' to include all subfolders.\012" "-->Toggle 'Delete Original Files After Compressing' to delete or retain originals.\012" "-->Highlight file types in the 'File Types' list and select 'Use Only Selected File Types' to\012" " specify file types to compress or uncompress.\012" "-->Press 'Add File Type' to add a custom file type to the list.\012" "-->Double click on a file type to remove it from the list.\012" "\012" "-->Special thanks to Tromnek, whose edited Python scripts are implemented herein.\012" "NOTE: This program will automatically close after a recursive search of subfolders has\012" "been completed.") def handleGo(self): #handleGo converts listbox info to file table info global openListC, openListU q = " " p = " " Selecteds = self.List.curselection() #You can see, here, that I have been learning from Ockham's code.... #Sels = self.List.get(ACTIVE) #Hopefully you can't copyright variable names.... :) NumSel = len(Selecteds) print "number selected:" print NumSel if NumSel != 0: for i in Selecteds: Name = self.List.get(i) #q,p = Name #Unpack the tuples or... q = Name[0] #Index the tuples p = Name[1] suffixTableC[q] = p #Re-fill the suffix tables suffixTableU[p] = q openListC = (openListC + " " + "*" + q) #Re-fill the file open lists openListU = (openListU + " " + "*" + p) print suffixTableC print openListC print suffixTableU #Testing verification print openListU def die(self): self.master.destroy() self.master.quit() def handleCustom(self): #handleCustom handles user interaction w/ listbox global custUse, openListC, openListU, backupC, backupU, openCback, openUback if self.refresh == 0: if custUse ==0: custUse = 1 else: custUse = 0 print custUse if self.refresh == 1: self.refresh = 0 if (custUse == 0) and (self.safety ==0): #When custom file types checkbox is unchecked dict.clear(suffixTableC) suffixTableC.update(backupC) #Restore old file tables from backup dict.clear(suffixTableU) suffixTableU.update(backupU) openListC = openCback #Restore old file open lists from backup openListU = openUback print suffixTableC #Testing verification print openListC print suffixTableU print openListU if custUse == 1: NumSel = 0 if self.safety == 1: backupC = dict.copy(suffixTableC) #Back up original file tables only at start backupU = dict.copy(suffixTableU) openCback = openListC openUback = openListU Selecteds = self.List.curselection() NumSel = len(Selecteds) #Don't empty the file tables when there's nothing selected to replace them. if NumSel != 0: dict.clear(suffixTableC) #Empty the file tables each time dict.clear(suffixTableU) openListC = " " #Clear the open file lists each time openListU = " " self.safety = 0 #A switch to prevent zero looping and to create backups only at start self.handleGo() def openfileR(self): #Switch for "entire folder" handling. Bad variable name. global recurse if recurse == 0: recurse = 1 else: recurse = 0 print recurse def openfileS(self): #Switch for recursive folder handling. global recursive if recursive == 0: recursive = 1 else: recursive = 0 print recursive def delFiles(self): #Switch for file delete option. global deleteOriginals if deleteOriginals == 0: deleteOriginals = 1 else: deleteOriginals = 0 print deleteOriginals def AddFile(self): #Part 1 of Addfile box function. global AddTo, root #Part 2 is a separate Class, below. d = self.MyDialog(root,AddTo) root.wait_window(d.top) self.boxAdd(addElem) def boxAdd(self,addElem): #Part 3 of Addfile box. global AddTo addElem = AddTo AddTo = " " if addElem != " ": self.List.insert(END,addElem) #------------------------------------------------------------------------------------- def openfileC(self): #Compression operations. This is my part. global message, names, dirname, listed, recurse, recursive, custUse onameC = " " if custUse == 1: #This updates custom file lists self.refresh = 1 self.handleCustom() proceed = 0 if recurse == 0: onameC = tkFileDialog.askopenfilenames(filetypes=[("All Associated Files", openListC)]) if recurse == 1: message = tkFileDialog.askdirectory() if (message == "") or (message == "."): message = "NONE" #Keeping a dummy control value for cancel if message != "NONE": dirname = message names = os.listdir(message) onameC = names if onameC != " ": proceed = 1 fileToCompress = onameC #---------------------------------------------------------------------------------------------- if recurse == 0: #This part is P5 original for fileToCompress in onameC: #This enables use of askopenfilenames (plural) for key in suffixTableC.keys(): if (string.find(fileToCompress, key) != -1): compressFile(fileToCompress, key, suffixTableC[key], deleteOriginals) break #--------------------------------------------------------------------------------------------------- elif (recurse ==1) and (recursive ==1): #P5 original, as altered by Tromnek if message == "NONE": proceed = 0 i = 0 for key in suffixTableC.keys(): if (i==0): message = message + key else: message = message + ', ' + key i = i + 1 try: #TromNek this allows us to run the script outside of poser initDir = poser.AppLocation() # <-this line was in the original script except: initDir = os.getcwd() # we must be running in native python fileIndex = string.rfind(initDir, separator) initDir = initDir[:fileIndex] dirToCompress = dirname #(proceed, dirToCompress, deleteOriginals) = message if proceed == 0: #Cage changed this to prevent errors w/ browse for directory being cancelled. message = "." dirname = "NONE" names = "NONE" exit #raise 'Script cancelled' print 'Recursing from ', dirToCompress, '\n\n' arg = None #TromNek next 15 lines reldir = separator+'Runtime'+separator # get path starting with first 'Runtime' folder #reldir = '' # or not dirToCompress = os.path.normpath( dirToCompress ) begpth = string.find( string.lower(dirToCompress+separator), string.lower(reldir) ) if (begpth < 1): begpth = 0 if ((winver==1) and (dirToCompress[1]==':')): begpth = 2 while (begpth < len(dirToCompress)) and (dirToCompress[begpth] == separator): begpth = begpth+1 # skip over path separators to get to the path if begpth > 0: os.chdir( dirToCompress[:begpth] ) # change to drive and initial folder of dirToCompress dirToCompress = dirToCompress[begpth:] # strip 'driveletter:\' and initial folder from dirToCompress os.path.walk(dirToCompress, visitC, arg) print "Compression complete" if dirname != "NONE": #This last bit added by Cage. self.die() #Because the initial directory is replaced by the root directory after the walk, #kill the process after a successful recursion to prevent errors. The original #script automatically ended the program after recursion, as well. message = "." dirname = "NONE" names = "NONE" proceed = 0 #----------------------------------------------------------------------------------------------- elif (recurse == 1) and (recursive==0): #P5 and Tromnek. print 'Looking under directory:', dirname, '------' for name in names: for key in suffixTableC.keys(): #if (string.find(name, key) != -1): extIndex = string.rfind(string.lower(name), key ) #TromNek make sure it really is the extension. if ( (extIndex + len(key)) == len(name)): compressFile(dirname + separator + name, key, suffixTableC[key], deleteOriginals) break print "Compress, Folders, No Recursion, Done" #------------------------------------------------------------------------------------------------- def openfileU(self): #Uncompression functions. This is my part. global recurse, message, names, dirname, recursive, custUse onameU = " " if custUse == 1: self.refresh = 1 self.handleCustom() proceed = 0 if recurse == 0: onameU = tkFileDialog.askopenfilenames(filetypes=[("All Associated Files", openListU)]) if recurse == 1: message = tkFileDialog.askdirectory() if (message == "") or (message == "."): message = "NONE" #Keeping a dummy control value for cancel if message != "NONE": dirname = message names = os.listdir(message) onameU = names if onameU != " ": proceed = 1 fileToUncompress = onameU #--------------------------------------------------------------------------------------- if recurse == 0: #P5 original w/ minor alterations. for fileToUncompress in onameU: for key in suffixTableU.keys(): if (string.find(fileToUncompress, key) != -1): uncompressFile(fileToUncompress, key, suffixTableU[key], deleteOriginals) break #----------------------------------------------------------------------------------------- elif (recurse ==1) and (recursive ==1) and (dirname != 0): #P5 and Tromnek. i = 0 for key in suffixTableU.keys(): if (i==0): message = message + key else: message = message + ', ' + key i = i + 1 try: #TromNek this allows us to run the script outside of poser initDir = poser.AppLocation() # <-this line was in the original script except: initDir = os.getcwd() # we must be running in native python #initDir = poser.AppLocation() fileIndex = string.rfind(initDir, separator) initDir = initDir[:fileIndex] dirToUnCompress = dirname #(proceed, dirToUnCompress, deleteOriginals) = dialog(message, initDir) if proceed == 0: #Cage changed this to prevent errors w/ browse for directory being cancelled. message = "." dirname = "NONE" names = "NONE" exit #raise 'Script cancelled' print 'Recursing from ', dirToUnCompress, '\n\n' arg = None os.path.walk(dirToUnCompress, visitU, arg) print "Uncompression complete" if dirname != "NONE": #This last bit added by Cage. self.die() #Because the initial directory is replaced by the root directory after the walk, #kill the process after a successful recursion to prevent errors. The original #script automatically ended the program, as well. message = "." dirname = "NONE" names = "NONE" proceed = 0 #----------------------------------------------------------------------------------------- elif (recurse == 1) and (recursive == 0): #P5 and Tromnek. #print names print 'Looking under directory:', dirname, '------' for name in names: for key in suffixTableU.keys(): #if (string.find(name, key) != -1): extIndex = string.rfind(string.lower(name), key ) #TromNek make sure it really is the extension. if ( (extIndex + len(key)) == len(name)): uncompressFile(dirname + separator + name, key, suffixTableU[key], deleteOriginals) break print "Uncompress, Folders, No Recursion, Done" #----------------------------------------------------------------------------------------------- class MyDialog: #Part 3 of the Addfile box function. def __init__(self,parent,txt): top = self.top = Toplevel(parent) Label(top,text="Enter New Extensions").pack() Label(top,text="Including Leading Dot ('.')").pack() self.e = Entry(top) self.e.insert(0,txt) self.e.pack(padx=5) Label(top,text="uncompressed extension").pack() self.e2 =Entry(top) self.e2.insert(10,txt) self.e2.pack(padx=5) Label(top,text="compressed extension").pack() b = Button(top, text="OK", command=self.ok) b.pack(pady=5) b2 = Button(top, text="Cancel", command=self.cancel) b2.pack(pady=5) def ok(self): global AddTo, root, parent fixit = self.e.get() fixit2 = self.e2.get() fixit = string.lstrip(fixit,None) #Remove mysterious space at beginning of entry fixit2 = string.lstrip(fixit2,None) if (macver): x = " " #Assuming that existing items don't need to be removed y = " " #from the Mac tables, but new items do need to be r = " " #added. s = " " x,r = string.split(fixit,".",1) y,s = string.split(fixit2,".",1) #Strip the dots from the extensions r = r + "Z" s = s + " " typeTableC[fixit] = r #Add to the typeTables. typeTableU[fixit2] = s nAddTo = ((fixit) ,(fixit2)) #Make the tuple self.e = " " #Clear the boxes for the next entry self.e2 = " " if nAddTo and nAddTo != " ": AddTo = nAddTo nAddTo = " " self.top.destroy() if nAddTo == " ": self.top.destroy() def cancel(self): self.e = " " self.e2 = " " AddTo = " " nAddTo = " " self.top.destroy() #-------------------------------------------------------------------------------------------- app = App(root, "") root.mainloop() #--------------------------------------------------------------------------