diff --git a/twander.py b/twander.py index a105943..f604e60 100755 --- a/twander.py +++ b/twander.py @@ -6,7 +6,7 @@ # Program Information PROGNAME = "twander" -RCSID = "$Id: twander.py,v 3.121 2003/03/02 00:52:06 tundra Exp $" +RCSID = "$Id: twander.py,v 3.122 2003/03/03 22:49:08 tundra Exp $" VERSION = RCSID.split()[2] # Copyright Information @@ -307,7 +307,7 @@ # Sort Field Names In Normal View -fNONE = "None" +fNONE = "No Sort" fPERMISSIONS = "Permissions" fLINKS = "Links" fOWNER = "Owner" @@ -318,7 +318,7 @@ # Sort Field Names In Drive List View -dlvNONE = "None" +dlvNONE = "No Sort" dlvLABEL = "Label/Share" dlvTYPE = "Drive Type" dlvFREE = "Free Space" @@ -327,10 +327,20 @@ # 'Fake' sorting field used to set SORTREVERSE and SORTSEPARATE -fREVERSE = -1 -fSEPARATE = -2 +fREVERSE = "Reverse" +fSEPARATE = "Separate" -# Associate each legal field name with the corresponding sortkey field position +# Build a dictionary whose keys are the names of all the legal sort fields +# and whose entries are tuples in the form: +# +# (field #, +# Name Of Sort Option In Normal View, +# Name Of Sort Option In Drive List View) +# +# Placing a None value in either of the last two tuple entries causes the +# keystroke combination associated with that sort option to be ignored AND +# prevents that option from appearing in the Sort Menu. +# # Note that fNONE indicates that no sorting is to be done, so there # is no real associated sortkey field. @@ -338,8 +348,9 @@ index = -1 for x, y in [(fNONE, dlvNONE), (fPERMISSIONS, dlvLABEL), (fLINKS, dlvTYPE), (fOWNER, dlvFREE), - (fGROUP, dlvTOTAL), (fLENGTH, dlvLETTER), (fDATE, dlvLETTER), (fNAME, dlvLETTER)]: - Name2Key[x.lower()] = (index, y) + (fGROUP, dlvTOTAL), (fLENGTH, dlvLETTER), (fDATE, None), (fNAME, None), + (fREVERSE, fREVERSE), (fSEPARATE, None)]: + Name2Key[x.lower()] = (index, x, y) index += 1 # Highest key index needed by Drive List View @@ -445,6 +456,20 @@ # Stat-Related Stuff ##### +# Misc. Stat-Related Strings + +FILEGROUP = "group" +FILEOWNER = "owner" +NODRIVE = "" +NOLABEL = "" +SYMPTR = " -> " +UNAVAILABLE = "Unavailable" +WIN32GROUP = "win32" + FILEGROUP +WIN32OWNER = "win32" + FILEOWNER +WIN32FREE = " free" +WIN32TOTAL = " total " + + if WIN32ALL: # Used with win32all-based permissions logic. @@ -467,13 +492,13 @@ # Size of each of the drive detail fields, including room for trailing space. - SZ_DRIVE_LABEL = 14 # Must be wide enough to hold NODRIVE + 1 or NOLABEL + 1 - SZ_DRIVE_FREE = 13 # In this case there is no trailing space but a trailing '/' - SZ_DRIVE_TTL = 13 # so we can have a 'free/total' presentation - SZ_DRIVE_TYPE = 20 - SZ_DRIVE_HOST = 19 # Leave room for leading '\\' - no trailing space, trailing '\' - SZ_DRIVE_TOTAL = SZ_DRIVE_LABEL + SZ_DRIVE_FREE + SZ_DRIVE_TTL + SZ_DRIVE_TYPE + SZ_DRIVE_HOST + SZ_DRIVE_SHARE = 24 # Can be label or share string - leave plenty of room + SZ_DRIVE_TYPE = 20 + SZ_DRIVE_FREE = 13 # The trailing text string has as leading blank for separation + SZ_DRIVE_TTL = 13 # The trailing text string has leading and trailing blanks for separation + + SZ_DRIVE_TOTAL = SZ_DRIVE_SHARE + SZ_DRIVE_TYPE + SZ_DRIVE_FREE + len(WIN32FREE) + SZ_DRIVE_TTL + len(WIN32TOTAL) # Constants used with the more usual Unix-style details # Used both by Unix and Win32 when win32all is not present or disabled. @@ -508,19 +533,6 @@ SETGID_MASK = 2 SETUID_MASK = 4 -# Misc. Stat-Related Strings - -FILEGROUP = "group" -FILEOWNER = "owner" -NODRIVE = "" -NOLABEL = "" -SYMPTR = " -> " -UNAVAILABLE = "Unavailable" -WIN32GROUP = "win32" + FILEGROUP -WIN32OWNER = "win32" + FILEOWNER -WIN32FREE = "free" -WIN32TOTAL = "total" - ##### # Configuration File-Related Constants & Globals @@ -843,13 +855,13 @@ def PadString(string, width, Rjust=FALSE): - string = string[:(width-1)] + s = string[:(width-1)] if Rjust: - string = string.rjust(width) + s = s.rjust(width) else: - string = string.ljust(width) + s = s.ljust(width) - return string + return s # End of 'PadString()' @@ -1428,40 +1440,9 @@ UpdateMenu(UI.HistBtn, UI.CmdHist, MAXMENU, MAXMENUBUF, KeyRunCommand, fakeevent=TRUE) UpdateMenu(UI.WildBtn, UI.WildHist, MAXMENU, MAXMENUBUF, KeySelWild, fakeevent=TRUE) - # Setup the sorting menu - - # Clear out any old entries + # Initialize the Sorting Menu - UI.SortBtn.config(state=DISABLED) - UI.SortBtn.menu.delete(0,END) - - - # Add the menu selections - - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fNONE, Name2Key[fNONE.lower()][1]), - command=lambda parm=fNONE : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fPERMISSIONS, Name2Key[fPERMISSIONS.lower()][1]), - command=lambda parm=fPERMISSIONS : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fLINKS, Name2Key[fLINKS.lower()][1]), - command=lambda parm=fLINKS : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fOWNER, Name2Key[fOWNER.lower()][1]), - command=lambda parm=fOWNER : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fGROUP, Name2Key[fGROUP.lower()][1]), - command=lambda parm=fGROUP : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fLENGTH, Name2Key[fLENGTH.lower()][1]), - command=lambda parm=fLENGTH : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fDATE, Name2Key[fDATE.lower()][1]), - command=lambda parm=fDATE : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s %s / %s" % (sSORTBY, fNAME, Name2Key[fNAME.lower()][1]), - command=lambda parm=fNAME : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s" % (sREVERSE), command=lambda parm=fREVERSE : KeySetSortParm(parm)) - UI.SortBtn.menu.add_command(label="%s" % (sSEPARATE), command=lambda parm=fSEPARATE : KeySetSortParm(parm)) - - - # Enable the menu selections - - UI.SortBtn['menu'] = UI.SortBtn.menu - UI.SortBtn.config(state=NORMAL) + LoadSortMenu() # Initialize the Help Menu LoadHelpMenu() @@ -1473,6 +1454,46 @@ ##### +# Load The Sorting Menu with the latest information +##### + +def LoadSortMenu(): + + # Sort Menu content is different if in Drive List View + # Show options appropriate to the current view + + if UI.CurrentDir == SHOWDRIVES: + idx = 2 + else: + idx = 1 + + # Clear out any old entries + + UI.SortBtn.config(state=DISABLED) + UI.SortBtn.menu.delete(0,END) + + # Add the menu selections + + for entry in [fNONE, fPERMISSIONS, fLINKS, fOWNER, fGROUP, fLENGTH, fDATE, fNAME, fREVERSE, fSEPARATE]: + + t = Name2Key[entry.lower()] + if t[idx]: + UI.SortBtn.menu.add_command(label=t[idx], command=lambda parm=t[1] : KeySetSortParm(parm)) + + # Store the current directory - used in subsequent calls to this funtion to + # determine whether or not we're moving between Normal <--> Drive List Views + + UI.SortBtn.CurrentDir = UI.CurrentDir + + # Enable the menu selections + + UI.SortBtn['menu'] = UI.SortBtn.menu + UI.SortBtn.config(state=NORMAL) + +# End of 'LoadSortMenu()' + + +##### # Load Help Menu with latest information ##### @@ -2008,7 +2029,15 @@ def UpdateTitle(self, mainwin): if UI.CurrentDir == SHOWDRIVES: - srtfld = Name2Key[SORTBYFIELD.lower()][1].upper() + + # SORTBYFIELD can have values not meaningful + # in Drive List View - these are always mapped to fNAME + + if Name2Key[SORTBYFIELD.lower()][0] > MAXDLVKEY: + srtfld = fNAME.upper() + else: + srtfld = Name2Key[SORTBYFIELD.lower()][2].upper() + fld3 = "" else: @@ -2178,6 +2207,10 @@ elif event.char == 'h': button = UI.HistBtn + # Sort Menu + elif event.char == 's': + button = UI.SortBtn + # Wildcard Menu elif event.char == 'w': button = UI.WildBtn @@ -2869,6 +2902,8 @@ def KeySetSortParm(parm): global SORTBYFIELD, SORTREVERSE, SORTSEPARATE + # Which entry in the Name2Key + refresh = FALSE if parm == fREVERSE: @@ -2883,15 +2918,43 @@ SORTSEPARATE = not SORTSEPARATE refresh = TRUE - # Only actually change the sort key if it is different than last time - # Again we want to suppress unnecessary refreshes + # Sort By Selected Parameter + # In Drive List View only respond to those keys that have a + # corresponding Sort Menu Entry - elif ((UI.CurrentDir != SHOWDRIVES) and (parm.lower() != SORTBYFIELD.lower())) or \ - ((UI.CurrentDir == SHOWDRIVES) and \ - (Name2Key[parm.lower()][1].lower() != Name2Key[SORTBYFIELD.lower()][1].lower())): + else: + - SORTBYFIELD = parm - refresh = TRUE + # First determine whether we even want to act on this keystroke. + # A given keystroke is ignored if the Name of the sort option associated + # with the current view is None (the Python value None, not the string 'None'). + + # Get index of desired entry in Name2Key tuple + + if UI.CurrentDir == SHOWDRIVES: + idx = 2 + else: + idx = 1 + + # Get the tuple associated with new key + n2k = Name2Key[parm.lower()] + + # Get the name associated with the new key appropriate for the current view + sortname = n2k[idx] + + # If the new key is the same as the old key, ignore - ignore, we're already + # sorted this way. This avoids unnecessary refreshes. + # + # If the new key is (Python) None, it means we do not want to process this + # keystoke, so ignore it. + + if (parm == SORTBYFIELD) or not sortname: + return + + # Go ahead and do the new sort + else: + SORTBYFIELD = parm + refresh = TRUE if refresh: LoadHelpMenu() @@ -3102,15 +3165,13 @@ # Keep list of all unique directories visited in the Directory Menu UpdateDirMenu(newdir) - # And always force selection of first item there. - # This guarantees a selection in the new - # directory context, so subsequent commands - # won't try to operate on an item selected in a - # previous directory + # Nothing should be pre-selected in the new directory listing + KeySelNone(None) - KeySelTop(None) + # Update Help Menu to reflect whether we're in Normal or Drive List View + LoadSortMenu() - # Update titlebar to reflect any changes + # Update Titlebar to reflect any changes UI.UpdateTitle(UIroot) #Release the lock @@ -3320,7 +3381,8 @@ for drive in drivelist: - fields = [""] + + fields = [""] # Drive Label - Drive Might Not Be Available try: @@ -3345,7 +3407,7 @@ else: name = label - entry = PadString(name, SZ_DRIVE_HOST + SZ_DRIVE_LABEL) + entry = PadString(name, SZ_DRIVE_SHARE) fields.append(name) # Add the drive type @@ -3370,12 +3432,12 @@ freespace = PadString(freespace, SZ_DRIVE_FREE, Rjust=TRUE) totalspace = PadString(totalspace, SZ_DRIVE_TTL, Rjust=TRUE) + entry += "%s%s%s%s" % (freespace, WIN32FREE, totalspace, WIN32TOTAL) - - entry += "%s %s %s %s" % (freespace, WIN32FREE, totalspace, WIN32TOTAL) fields.append(fspace) fields.append(tspace) + # Finally, tack on the drive name with some leading space entry += " %s" % drive fields.append(drive) @@ -4349,7 +4411,6 @@ # Initialize the UI directory listing LoadDirList(STARTDIR) -KeySelTop(None) # Process options to catch any changes detected in # environment variable or command line