def showEventSelectionPrompt(self): """ Prompts the user to select the events being listened for. """ # allow user to enter new types of events to log - unchanged if left blank popup, width, height = popups.init(11, 80) if popup: try: # displays the available flags popup.win.box() popup.addstr(0, 0, "Event Types:", curses.A_STANDOUT) eventLines = EVENT_LISTING.split("\n") for i in range(len(eventLines)): popup.addstr(i + 1, 1, eventLines[i][6:]) popup.win.refresh() userInput = popups.inputPrompt("Events to log: ") if userInput: userInput = userInput.replace(' ', '') # strips spaces try: self.setLoggedEvents(expandEvents(userInput)) except ValueError, exc: popups.showMsg("Invalid flags: %s" % str(exc), 2) finally: popups.finalize()
def showSnapshotPrompt(self): """ Lets user enter a path to take a snapshot, canceling if left blank. """ pathInput = popups.inputPrompt("Path to save log snapshot: ") if pathInput: try: self.saveSnapshot(pathInput) popups.showMsg("Saved: %s" % pathInput, 2) except IOError, exc: popups.showMsg("Unable to save snapshot: %s" % sysTools.getFileErrorMsg(exc), 2)
def showFilterPrompt(self): """ Prompts the user to add a new regex filter. """ regexInput = popups.inputPrompt("Regular expression: ") if regexInput: try: self.setFilter(re.compile(regexInput)) if regexInput in self.filterOptions: self.filterOptions.remove(regexInput) self.filterOptions.insert(0, regexInput) except re.error, exc: popups.showMsg("Unable to compile expression: %s" % exc, 2)
def reloadTorrc(self): """ Reloads the torrc, displaying an indicator of success or failure. """ try: torConfig.getTorrc().load() self._lastContentHeightArgs = None self.redraw(True) resultMsg = "torrc reloaded" except IOError: resultMsg = "failed to reload torrc" self._lastContentHeightArgs = None self.redraw(True) popups.showMsg(resultMsg, 1)
def handleKey(self, key): isKeystrokeConsumed = True if uiTools.isScrollKey(key): pageHeight = self.getPreferredSize()[0] - 1 newScroll = uiTools.getScrollPosition(key, self.scroll, pageHeight, self.lastContentHeight) if self.scroll != newScroll: self.valsLock.acquire() self.scroll = newScroll self.redraw(True) self.valsLock.release() elif key in (ord('u'), ord('U')): self.valsLock.acquire() self.showDuplicates = not self.showDuplicates self.redraw(True) self.valsLock.release() elif key == ord('c') or key == ord('C'): msg = "This will clear the log. Are you sure (c again to confirm)?" keyPress = popups.showMsg(msg, attr = curses.A_BOLD) if keyPress in (ord('c'), ord('C')): self.clear() elif key == ord('f') or key == ord('F'): # Provides menu to pick regular expression filters or adding new ones: # for syntax see: http://docs.python.org/library/re.html#regular-expression-syntax options = ["None"] + self.filterOptions + ["New..."] oldSelection = 0 if not self.regexFilter else 1 # does all activity under a curses lock to prevent redraws when adding # new filters panel.CURSES_LOCK.acquire() try: selection = popups.showMenu("Log Filter:", options, oldSelection) # applies new setting if selection == 0: self.setFilter(None) elif selection == len(options) - 1: # selected 'New...' option - prompt user to input regular expression self.showFilterPrompt() elif selection != -1: self.makeFilterSelection(self.filterOptions[selection - 1]) finally: panel.CURSES_LOCK.release() if len(self.filterOptions) > MAX_REGEX_FILTERS: del self.filterOptions[MAX_REGEX_FILTERS:] elif key == ord('e') or key == ord('E'): self.showEventSelectionPrompt() elif key == ord('a') or key == ord('A'): self.showSnapshotPrompt() else: isKeystrokeConsumed = False return isKeystrokeConsumed
def showWriteDialog(self): """ Provies an interface to confirm if the configuration is saved and, if so, where. """ # display a popup for saving the current configuration configLines = torConfig.getCustomOptions(True) popup, width, height = popups.init(len(configLines) + 2) if not popup: return try: # displayed options (truncating the labels if there's limited room) if width >= 30: selectionOptions = ("Save", "Save As...", "Cancel") else: selectionOptions = ("Save", "Save As", "X") # checks if we can show options beside the last line of visible content isOptionLineSeparate = False lastIndex = min(height - 2, len(configLines) - 1) # if we don't have room to display the selection options and room to # grow then display the selection options on its own line if width < (30 + len(configLines[lastIndex])): popup.setHeight(height + 1) popup.redraw(True) # recreates the window instance newHeight, _ = popup.getPreferredSize() if newHeight > height: height = newHeight isOptionLineSeparate = True key, selection = 0, 2 while not uiTools.isSelectionKey(key): # if the popup has been resized then recreate it (needed for the # proper border height) newHeight, newWidth = popup.getPreferredSize() if (height, width) != (newHeight, newWidth): height, width = newHeight, newWidth popup.redraw(True) # if there isn't room to display the popup then cancel it if height <= 2: selection = 2 break popup.win.erase() popup.win.box() popup.addstr(0, 0, "Configuration being saved:", curses.A_STANDOUT) visibleConfigLines = height - 3 if isOptionLineSeparate else height - 2 for i in range(visibleConfigLines): line = uiTools.cropStr(configLines[i], width - 2) if " " in line: option, arg = line.split(" ", 1) popup.addstr(i + 1, 1, option, curses.A_BOLD | uiTools.getColor("green")) popup.addstr(i + 1, len(option) + 2, arg, curses.A_BOLD | uiTools.getColor("cyan")) else: popup.addstr(i + 1, 1, line, curses.A_BOLD | uiTools.getColor("green")) # draws selection options (drawn right to left) drawX = width - 1 for i in range(len(selectionOptions) - 1, -1, -1): optionLabel = selectionOptions[i] drawX -= (len(optionLabel) + 2) # if we've run out of room then drop the option (this will only # occure on tiny displays) if drawX < 1: break selectionFormat = curses.A_STANDOUT if i == selection else curses.A_NORMAL popup.addstr(height - 2, drawX, "[") popup.addstr(height - 2, drawX + 1, optionLabel, selectionFormat | curses.A_BOLD) popup.addstr(height - 2, drawX + len(optionLabel) + 1, "]") drawX -= 1 # space gap between the options popup.win.refresh() key = cli.controller.getController().getScreen().getch() if key == curses.KEY_LEFT: selection = max(0, selection - 1) elif key == curses.KEY_RIGHT: selection = min(len(selectionOptions) - 1, selection + 1) if selection in (0, 1): loadedTorrc, promptCanceled = torConfig.getTorrc(), False try: configLocation = loadedTorrc.getConfigLocation() except IOError: configLocation = "" if selection == 1: # prompts user for a configuration location configLocation = popups.inputPrompt("Save to (esc to cancel): ", configLocation) if not configLocation: promptCanceled = True if not promptCanceled: try: torConfig.saveConf(configLocation, configLines) msg = "Saved configuration to %s" % configLocation except IOError, exc: msg = "Unable to save configuration (%s)" % sysTools.getFileErrorMsg(exc) popups.showMsg(msg, 2) finally: popups.finalize()
def handleKey(self, key): self.valsLock.acquire() isKeystrokeConsumed = True if uiTools.isScrollKey(key): pageHeight = self.getPreferredSize()[0] - 1 detailPanelHeight = self._config["features.config.selectionDetails.height"] if detailPanelHeight > 0 and detailPanelHeight + 2 <= pageHeight: pageHeight -= (detailPanelHeight + 1) isChanged = self.scroller.handleKey(key, self._getConfigOptions(), pageHeight) if isChanged: self.redraw(True) elif uiTools.isSelectionKey(key) and self._getConfigOptions(): # Prompts the user to edit the selected configuration value. The # interface is locked to prevent updates between setting the value # and showing any errors. panel.CURSES_LOCK.acquire() try: selection = self.getSelection() configOption = selection.get(Field.OPTION) if selection.isUnset(): initialValue = "" else: initialValue = selection.get(Field.VALUE) promptMsg = "%s Value (esc to cancel): " % configOption isPrepopulated = self._config["features.config.prepopulateEditValues"] newValue = popups.inputPrompt(promptMsg, initialValue if isPrepopulated else "") if newValue != None and newValue != initialValue: try: if selection.get(Field.TYPE) == "Boolean": # if the value's a boolean then allow for 'true' and 'false' inputs if newValue.lower() == "true": newValue = "1" elif newValue.lower() == "false": newValue = "0" elif selection.get(Field.TYPE) == "LineList": # setOption accepts list inputs when there's multiple values newValue = newValue.split(",") torTools.getConn().setOption(configOption, newValue) # forces the label to be remade with the new value selection.labelCache = None # resets the isDefault flag customOptions = torConfig.getCustomOptions() selection.fields[Field.IS_DEFAULT] = not configOption in customOptions self.redraw(True) except Exception, exc: popups.showMsg("%s (press any key)" % exc) finally: panel.CURSES_LOCK.release() elif key == ord('a') or key == ord('A'): self.showAll = not self.showAll self.redraw(True) elif key == ord('s') or key == ord('S'): self.showSortDialog() elif key == ord('v') or key == ord('V'): self.showWriteDialog() else: isKeystrokeConsumed = False self.valsLock.release() return isKeystrokeConsumed
def handleKey(self, key): self.valsLock.acquire() isKeystrokeConsumed = True if uiTools.isScrollKey(key): pageHeight = self.getPreferredSize()[0] - 1 detailPanelHeight = CONFIG["features.config.selectionDetails.height"] if detailPanelHeight > 0 and detailPanelHeight + 2 <= pageHeight: pageHeight -= (detailPanelHeight + 1) isChanged = self.scroller.handleKey(key, self._getConfigOptions(), pageHeight) if isChanged: self.redraw(True) elif uiTools.isSelectionKey(key) and self._getConfigOptions(): # Prompts the user to edit the selected configuration value. The # interface is locked to prevent updates between setting the value # and showing any errors. panel.CURSES_LOCK.acquire() try: selection = self.getSelection() configOption = selection.get(Field.OPTION) if selection.isUnset(): initialValue = "" else: initialValue = selection.get(Field.VALUE) promptMsg = "%s Value (esc to cancel): " % configOption isPrepopulated = CONFIG["features.config.prepopulateEditValues"] newValue = popups.inputPrompt(promptMsg, initialValue if isPrepopulated else "") if newValue != None and newValue != initialValue: try: if selection.get(Field.TYPE) == "Boolean": # if the value's a boolean then allow for 'true' and 'false' inputs if newValue.lower() == "true": newValue = "1" elif newValue.lower() == "false": newValue = "0" elif selection.get(Field.TYPE) == "LineList": # setOption accepts list inputs when there's multiple values newValue = newValue.split(",") torTools.getConn().setOption(configOption, newValue) # forces the label to be remade with the new value selection.labelCache = None # resets the isDefault flag customOptions = torConfig.getCustomOptions() selection.fields[Field.IS_DEFAULT] = not configOption in customOptions self.redraw(True) except Exception, exc: popups.showMsg("%s (press any key)" % exc) finally: panel.CURSES_LOCK.release() elif key == ord('a') or key == ord('A'): self.showAll = not self.showAll self.redraw(True) elif key == ord('s') or key == ord('S'): self.showSortDialog() elif key == ord('v') or key == ord('V'): self.showWriteDialog() else: isKeystrokeConsumed = False self.valsLock.release() return isKeystrokeConsumed