diff options
Diffstat (limited to 'logout-manager-ncurses.py')
-rwxr-xr-x | logout-manager-ncurses.py | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/logout-manager-ncurses.py b/logout-manager-ncurses.py new file mode 100755 index 0000000..7356569 --- /dev/null +++ b/logout-manager-ncurses.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# File: logout-manager-tui.py +# License: MIT +# Author: adamlamers, bgstack15 +# Startdate: 2020-03-09 17:06 +# Title: ncurses based logout manager +# Usage: +# +# Reference: +# https://docs.python.org/3/howto/curses.html +# ripped straight from http://adamlamers.com/post/FTPD9KNRA8CT +# https://stackoverflow.com/questions/3061/calling-a-function-of-a-module-by-using-its-name-a-string/12025554#12025554 +# Improve: +# add "disabled" option in menu, with default=enabled +# Documentation: + +import curses, sys, os +sys.path.append("/home/bgirton/dev/logout-manager") +import lmlib + +class CursesMenu(object): + + INIT = {'type' : 'init'} + + def __init__(self, menu_options): + self.screen = curses.initscr() + self.menu_options = menu_options + self.selected_option = 0 + self._previously_selected_option = None + self.running = True + + #init curses and curses input + curses.noecho() + curses.cbreak() + curses.start_color() + curses.curs_set(0) #Hide cursor + self.screen.keypad(1) + + #set up color pair for highlighted option + curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) + self.hilite_color = curses.color_pair(1) + self.normal_color = curses.A_NORMAL + + def prompt_selection(self, parent=None): + if parent is None: + lastoption = "Cancel" + else: + lastoption = "Return to previous menu ({})".format(parent['title']) + + option_count = len(self.menu_options['options']) + + input_key = None + + ENTER_KEY = ord('\n') + #NUM_KEYS = [ord('1')] + #NUM_KEYS = [ord(1),ord(2)...] + NUM_KEYS = [ord(str(i)) for i in range(1,option_count+2)] + done = False + while not done: + if self.selected_option != self._previously_selected_option: + self._previously_selected_option = self.selected_option + + self.screen.border(0) + self._draw_title() + for option in range(option_count): + if self.selected_option == option: + self._draw_option(option, self.hilite_color) + else: + self._draw_option(option, self.normal_color) + + if self.selected_option == option_count: + self.screen.addstr(5 + option_count, 4, "{:2} - {}".format(option_count+1, + lastoption), self.hilite_color) + else: + self.screen.addstr(5 + option_count, 4, "{:2} - {}".format(option_count+1, + lastoption), self.normal_color) + + max_y, max_x = self.screen.getmaxyx() + if input_key is not None: + self.screen.addstr(max_y-3, max_x - 5, "{:3}".format(self.selected_option)) + self.screen.refresh() + + + input_key = self.screen.getch() + down_keys = [curses.KEY_DOWN, ord('j')] + up_keys = [curses.KEY_UP, ord('k')] + exit_keys = [ord('q')] + + if input_key in down_keys: + if self.selected_option < option_count: + self.selected_option += 1 + else: + self.selected_option = 0 + + if input_key in up_keys: + if self.selected_option > 0: + self.selected_option -= 1 + else: + self.selected_option = option_count + + if input_key in exit_keys: + self.selected_option = option_count #auto select exit and return + break + + if input_key == ENTER_KEY or input_key in NUM_KEYS: + if input_key in NUM_KEYS: + self.selected_option=int(chr(input_key))-1 + done = True + return self.selected_option + + def _draw_option(self, option_number, style): + self.screen.addstr(5 + option_number, + 4, + "{:2} - {}".format(option_number+1, self.menu_options['options'][option_number]['title']), + style) + + def _draw_title(self): + self.screen.addstr(2, 2, self.menu_options['title'], curses.A_STANDOUT) + self.screen.addstr(4, 2, self.menu_options['subtitle'], curses.A_BOLD) + + def display(self): + selected_option = self.prompt_selection() + i, _ = self.screen.getmaxyx() + curses.endwin() + #os.system('clear') + if selected_option < len(self.menu_options['options']): + selected_opt = self.menu_options['options'][selected_option] + return selected_opt + else: + self.running = False + return {'title' : 'Cancel', 'type' : 'exitmenu'} + +menu = {'title' : 'Logout Manager', + 'type' : 'menu', + 'subtitle' : 'Use arrows or number keys'} + +option_1 = {'title' : 'Hello World', + 'type' : 'command', + 'command' : 'echo Hello World!'} + +# build menu object from config. +config = lmlib.Initialize_config() +actions = lmlib.Actions + +menu['options'] = [ + {'title': 'Lock', 'type': 'action', 'action': 'lock'}, + {'title': 'Logout', 'type': 'action', 'action': 'logout'}, + {'title': 'Hibernate', 'type': 'action', 'action': 'hibernate'}, + {'title': 'Shutdown', 'type': 'action', 'action': 'shutdown'}, + {'title': 'Reboot', 'type': 'action', 'action': 'reboot'} + ] + +m = CursesMenu(menu) +selected_action = m.display() + +if selected_action['type'] == 'exitmenu': + print("Cancelled") +elif selected_action['type'] == 'command': + os.system(selected_action['command']) +elif selected_action['type'] == 'action': + #a = selected_action['action']: + func = getattr(globals()['actions'],selected_action['action']) + func(config) |