diff --git a/twander.py b/twander.py index c695db5..d3a237f 100755 --- a/twander.py +++ b/twander.py @@ -4,7 +4,7 @@ # For Updates See: http://www.tundraware.com/Software/twander PROGNAME = "twander" -RCSID = "$Id: twander.py,v 2.47 2003/01/07 21:29:14 tundra Exp $" +RCSID = "$Id: twander.py,v 2.48 2003/01/09 18:03:07 tundra Exp $" VERSION = RCSID.split()[2] @@ -61,8 +61,8 @@ # General Program Commands -MOUSECTX = '' # Invoke context menu -MOUSEDIR = '' # Invoke directory menu +MOUSECTX = '' # Pop-up Context Menu +MOUSEDIR = '' # Pop-up Directory Menu KEYPRESS = '' # Any keypress (for commands) QUITPROG = '' # Quit the program READCONF = '' # Re-read the configuration file @@ -200,6 +200,13 @@ Button4Mask = (1<<11) Button5Mask = (1<<12) +# Alt Key is OS-dependent + +if OSNAME == 'nt': + AltMask = (1<<17) +else: + AltMask = Mod1Mask + # Stat-Related Constants @@ -840,7 +847,7 @@ self.DirBtn.menu = Menu(self.DirBtn, font=("courier", FSZ, "bold")) self.DirBtn.pack(side=LEFT, padx='2m') - # Setup the visual elements + # Setup the Directory Listing and Scrollbars self.hSB = Scrollbar(root, orient=HORIZONTAL) self.vSB = Scrollbar(root, orient=VERTICAL) @@ -873,12 +880,14 @@ def BindAllHandlers(self): + ### # General Program Commands + ### - # Bind handler to invoke context menu + # Bind handler to invoke Context Menu self.DirList.bind(self.KeyBindings["MOUSECTX"], MouseClick) - # Bind handler to invoke directory menu + # Bind handler to invoke Directory Menu self.DirList.bind(self.KeyBindings["MOUSEDIR"], MouseClick) # Bind handler for individual keystrokes @@ -896,8 +905,9 @@ # Bind handler for "Toggle Detail" self.DirList.bind(self.KeyBindings["TOGDETAIL"], KeyToggleDetail) - + ### # Directory Navigation + ### # Bind handler for "Change Directory" self.DirList.bind(self.KeyBindings["CHANGEDIR"], ChangeDir) @@ -926,8 +936,9 @@ # Bind handler for "Mouse Up Dir" self.DirList.bind(self.KeyBindings["MOUSEUP"], MouseDblClick) - + ### # Selection Keys + ### # Bind handler for "Select All" self.DirList.bind(self.KeyBindings["SELALL"], KeySelAll) @@ -950,7 +961,9 @@ # Bind handler for "Last Item" self.DirList.bind(self.KeyBindings["SELEND"], KeySelEnd) + ### # Scrolling Keys + ### # Bind Handler for "Move Page Down self.DirList.bind(self.KeyBindings["PGDN"], KeyPageDown) @@ -964,8 +977,9 @@ # Bind Handler for "Move Page Up" self.DirList.bind(self.KeyBindings["PGLFT"], KeyPageLeft) - + ### # Execute commands + ### # Bind handler for "Run Command" self.DirList.bind(self.KeyBindings["RUNCMD"], KeyRunCommand) @@ -1086,6 +1100,38 @@ ##### + # Set a particular selection, w/bounds checking + # Note that 'selection' is passed as a string + # but 'active' is passed as a number. + ##### + + def SetSelection(self, selection, active): + + # Clear all current selection(s) + self.DirList.selection_clear(0, END) + + # Get current maximum index + maxindex = self.DirList.size() - 1 + + # And bounds check/adjust + + if active > maxindex: + active = maxindex + + # Set desired selected items, if any + + if selection: + for entry in selection: + self.DirList.select_set(entry) + self.DirList.see(selection[-1]) + + # Now set the active entry + self.DirList.activate(active) + + # End of method 'twanderUI.SetSelection()' + + + ##### # Update title bar with most current information ##### @@ -1120,10 +1166,12 @@ def MouseClick(event): if event.state == Button3Mask: # Button-3 / No Modifier - ContextMenu(event) # Display Context Menu + x, y = UI.DirList.winfo_pointerxy() # Position near mouse + CommandMenu(event, x, y) # Display Context Menu elif event.state == (Button3Mask | ShiftMask): # ShiftButton-3 - DirMenu(event) # Display Directory Menu + x, y = UI.DirList.winfo_pointerxy() # Position near mouse + DirMenu(event, x, y) # Display Directory Menu # End Of 'MouseClick() @@ -1153,29 +1201,27 @@ # Event Handler: Context Menu ##### -def ContextMenu(event): +def CommandMenu(event, x, y): - # Popup a menu of available commands near the current mouse pointer, + # Popup a menu of available commands at requested coordinates # but only if there are commands defined. if UI.CmdBtn.menu.index(END): - x, y = UI.DirList.winfo_pointerxy() UI.CmdBtn.menu.tk_popup(x, y) -# End of 'ContextMenu()' +# End of 'CommandMenu()' ##### # Event Handler: Directory Menu ##### -def DirMenu(event): +def DirMenu(event, x, y): - # Popup a menu of available directories near the current mouse pointer, + # Popup a menu of available directories at requested coordinates # but only if there are previously visited directories. if UI.DirBtn.menu.index(END): - x, y = UI.DirList.winfo_pointerxy() UI.DirBtn.menu.tk_popup(x, y) # End of 'DirMenu()' @@ -1187,6 +1233,47 @@ def KeystrokeHandler(event): + # Check for, and handle accelerator keys + if event.state == AltMask: + + if event.char == 'c': + + # Get current location/size of Command Menu + + parts = UI.CmdBtn.winfo_geometry().split('+') # Geometry returned as "WidthxHeight+X+Y" + dims = parts[0].split('x') + x, y = int(parts[1]), int(parts[2]) + w, h = int(dims[0]), int(dims[1]) + + x += UIroot.winfo_rootx() # This is relative to root window position + y += UIroot.winfo_rooty() # So adjust accordingly + + # Display the Command Menu + + CommandMenu(event, x, y+h) + + # Inhibit event from getting picked up by local accelerator key handlers + + return "break" + + elif event.char == 'd': + # Get current location/size of Directory Menu + + parts = UI.DirBtn.winfo_geometry().split('+') # Geometry returned as "WidthxHeight+X+Y" + dims = parts[0].split('x') + x, y = int(parts[1]), int(parts[2]) + w, h = int(dims[0]), int(dims[1]) + + x += UIroot.winfo_rootx() # This is relative to root window position + y += UIroot.winfo_rooty() # So adjust accordingly + + # Display the Command Menu + DirMenu(event, x, y+h) + + # Inhibit event from getting picked up by local accelerator key handlers + + return "break" + # We *only* want to handle simple single-character # keystrokes. This means that there must be a character # present and that the only state modifier permitted @@ -1439,7 +1526,7 @@ if (next < UI.DirList.size() - 1): next += 1 - SetSelection((str(next),), next) + UI.SetSelection((str(next),), next) # End of 'KeySelNext()' @@ -1465,7 +1552,7 @@ if prev: prev -= 1 - SetSelection((str(prev),), prev) + UI.SetSelection((str(prev),), prev) # End of 'KeySelPrev()' @@ -1480,7 +1567,7 @@ sz = UI.DirList.size() - 1 # And setup to last item accordingly - SetSelection((str(sz),), sz) + UI.SetSelection((str(sz),), sz) # End of 'KeySelEnd()' @@ -1490,7 +1577,7 @@ ##### def KeySelTop(event): - SetSelection(('0',),0) + UI.SetSelection(('0',),0) # End of 'KeySelTop()' @@ -1886,8 +1973,23 @@ # Get first ST_SZxNAME chars of owner and group names on unix if OSNAME == 'posix': - owner = pwd.getpwuid(stinfo[ST_UID])[0][:ST_SZUNAME-1] - group = grp.getgrgid(stinfo[ST_GID])[0][:ST_SZGNAME-1] + + # Convert UID to name, if possible + try: + owner = pwd.getpwuid(stinfo[ST_UID])[0][:ST_SZUNAME-1] + + # No valid name associated with UID, so use number instead + except: + owner = str(stinfo[ST_UID]) + + # Convert GID to name, if possible + try: + group = grp.getgrgid(stinfo[ST_GID])[0][:ST_SZGNAME-1] + + # No valid name associated with GID, so use number instead + except: + group = str(stinfo[ST_GID]) + # Handle Win32 systems elif OSNAME == 'nt': @@ -1984,7 +2086,7 @@ UI.DirList.insert(0, *BuildDirList(UI.CurrentDir)) # Restore selection(s) - SetSelection(sellist, active) + UI.SetSelection(sellist, active) # Restore scroll positions @@ -2000,38 +2102,6 @@ # End of 'RefreshDirList() -##### -# Set a particular selection, w/bounds checking -# Note that 'selection' is passed as a string -# but 'active' is passed as a number. -##### - -def SetSelection(selection, active): - - # Clear all current selection(s) - UI.DirList.selection_clear(0, END) - - # Get current maximum index - maxindex = UI.DirList.size() - 1 - - # And bounds check/adjust - - if active > maxindex: - active = maxindex - - # Set desired selected items, if any - - if selection: - for entry in selection: - UI.DirList.select_set(entry) - UI.DirList.see(selection[-1]) - - # Now set the active entry - UI.DirList.activate(active) - -# End of 'SetSelection()' - - #---------------------- Menu Handlers ---------------------# #####