diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:42:35 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:42:35 +0900 |
commit | 72835b3d805ac6c7cdaac7d3aff107567e938314 (patch) | |
tree | 0f2a04dc3d0672c0960a62804c6e7758673e393c /base/tui.py | |
parent | eb5e5ee9adb02776056d1b4494f66150a2fc45f1 (diff) | |
download | hplip-72835b3d805ac6c7cdaac7d3aff107567e938314.tar.gz hplip-72835b3d805ac6c7cdaac7d3aff107567e938314.tar.bz2 hplip-72835b3d805ac6c7cdaac7d3aff107567e938314.zip |
Tizen 2.1 base
Diffstat (limited to 'base/tui.py')
-rw-r--r-- | base/tui.py | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/base/tui.py b/base/tui.py new file mode 100644 index 0000000..e012636 --- /dev/null +++ b/base/tui.py @@ -0,0 +1,483 @@ +# -*- coding: utf-8 -*- +# +# (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Author: Don Welch +# + +# Std Lib +import sys +import re + +# Local +from g import * +import pexpect +import utils + + +def enter_yes_no(question, default_value='y', choice_prompt=None): + if type(default_value) == type(""): + if default_value == 'y': + default_value = True + else: + default_value = False + + #assert default_value in [True, False] + + if choice_prompt is None: + if default_value: + question += " (y=yes*, n=no, q=quit) ? " + else: + question += " (y=yes, n=no*, q=quit) ? " + else: + question += choice_prompt + + while True: + try: + user_input = raw_input(log.bold(question)).lower().strip() + except EOFError: + continue + + if not user_input: + return True, default_value + + if user_input == 'n': + return True, False + + if user_input == 'y': + return True, True + + if user_input in ('q', 'c'): # q -> quit, c -> cancel + return False, default_value + + log.error("Please press <enter> or enter 'y', 'n', or 'q'.") + + +def enter_range(question, min_value, max_value, default_value=None): + while True: + try: + user_input = raw_input(log.bold(question)).lower().strip() + except EOFError: + continue + + if not user_input: + if default_value is not None: + return True, default_value + + if user_input == 'q': + return False, default_value + + try: + value_int = int(user_input) + except ValueError: + log.error('Please enter a number between %d and %d, or "q" to quit.' % + (min_value, max_value)) + continue + + if value_int < min_value or value_int > max_value: + log.error('Please enter a number between %d and %d, or "q" to quit.' % + (min_value, max_value)) + continue + + return True, value_int + + +def enter_choice(question, choices, default_value=None): + if 'q' not in choices: + choices.append('q') + + while True: + try: + user_input = raw_input(log.bold(question)).lower().strip() + except EOFError: + continue + + + if (not user_input and default_value) or user_input == default_value: + if default_value == 'q': + return False, default_value + else: + return True, default_value + + #print user_input + if user_input == 'q': + return False, user_input + + if user_input in choices: + return True, user_input + + log.error("Please enter %s or press <enter> for the default of '%s'." % + (', '.join(["'%s'" % x for x in choices]), default_value)) + + +def title(text): + log.info("") + log.info("") + log.info(log.bold(text)) + log.info(log.bold("-"*len(text))) + + +def header(text): + c = len(text) + log.info("") + log.info("-"*(c+4)) + log.info("| "+text+" |") + log.info("-"*(c+4)) + log.info("") + + +def load_paper_prompt(): + return continue_prompt("A page will be printed.\nPlease load plain paper into the printer.") + + +def load_scanner_for_align_prompt(): + return continue_prompt("Load the alignment page on the scanner bed and push the 'Scan' or 'Enter' button on the printer to complete the alignment.") + +def load_photo_paper_prompt(): + return continue_prompt("A page will be printed.\nPlease load HP Advanced Photo Paper - Glossy into the printer.") + + +def continue_prompt(prompt=''): + while True: + try: + x = raw_input(log.bold(prompt + " Press <enter> to continue or 'q' to quit: ")).lower().strip() + except EOFError: + continue + + if not x: + return True + + elif x == 'q': + return False + + log.error("Please press <enter> or enter 'q' to quit.") + + +def enter_regex(regex, prompt, pattern, default_value=None): + re_obj = re.compile(regex) + while True: + try: + x = raw_input(log.bold(prompt)) + except EOFError: + continue + + if not x and default_value is not None: + return default_value, x + + elif x == 'q': + return False, default_value + + match = re_obj.search(x) + + if not match: + log.error("Incorrect input. Please enter correct input.") + continue + + return True, x + + +def ttysize(): + try: + import commands # TODO: Replace with subprocess (commands is deprecated in Python 3.0) + ln1 = commands.getoutput('stty -a').splitlines()[0] + vals = {'rows':None, 'columns':None} + for ph in ln1.split(';'): + x = ph.split() + if len(x) == 2: + vals[x[0]] = x[1] + vals[x[1]] = x[0] + return int(vals['rows']), int(vals['columns']) + except TypeError: + return 40, 64 + + +class ProgressMeter(object): + def __init__(self, prompt="Progress:"): + self.progress = 0 + self.prompt = prompt + self.prev_length = 0 + self.spinner = "\|/-\|/-*" + self.spinner_pos = 0 + self.max_size = ttysize()[1] - len(prompt) - 25 + self.update(0) + + def update(self, progress, msg=''): # progress in % + self.progress = progress + + x = self.progress * self.max_size / 100 + if x > self.max_size: x = self.max_size + + if self.progress >= 100: + self.spinner_pos = 8 + self.progress = 100 + + sys.stdout.write("\b" * self.prev_length) + + y = "%s [%s%s%s] %d%% %s " % \ + (self.prompt, '*'*(x-1), self.spinner[self.spinner_pos], + ' '*(self.max_size-x), self.progress, msg) + + sys.stdout.write(y) + + sys.stdout.flush() + self.prev_length = len(y) + self.spinner_pos = (self.spinner_pos + 1) % 8 + + + +class Formatter(object): + def __init__(self, margin=2, header=None, min_widths=None, max_widths=None): + self.margin = margin # int + self.header = header # tuple of strings + self.rows = [] # list of tuples + self.max_widths = max_widths # tuple of ints + self.min_widths = min_widths # tuple of ints + + + def add(self, row_data): # tuple of strings + self.rows.append(row_data) + + + def output(self): + if self.rows: + num_cols = len(self.rows[0]) + for r in self.rows: + if len(r) != num_cols: + log.error("Invalid number of items in row: %s" % r) + return + + if len(self.header) != num_cols: + log.error("Invalid number of items in header.") + + min_calc_widths = [] + for c in self.header: + header_parts = c.split(' ') + max_width = 0 + for x in header_parts: + max_width = max(max_width, len(x)) + + min_calc_widths.append(max_width) + + max_calc_widths = [] + for x, c in enumerate(self.header): + max_width = 0 + for r in self.rows: + max_width = max(max_width, len(r[x])) + + max_calc_widths.append(max_width) + + max_screen_width = None + + if self.max_widths is None: + max_screen_width = ttysize()[1] + def_max = 8*(max_screen_width/num_cols)/10 + self.max_widths = [] + for c in self.header: + self.max_widths.append(def_max) + else: + if len(self.max_widths) != num_cols: + log.error("Invalid number of items in max col widths.") + + if self.min_widths is None: + if max_screen_width is None: + max_screen_width = ttysize()[1] + def_min = 4*(max_screen_width/num_cols)/10 + self.min_widths = [] + for c in self.header: + self.min_widths.append(def_min) + else: + if len(self.min_widths) != num_cols: + log.error("Invalid number of items in min col widths.") + + col_widths = [] + formats = [] + for m1, m2, m3, m4 in zip(self.min_widths, min_calc_widths, + self.max_widths, max_calc_widths): + col_width = max(max(m1, m2), min(m3, m4)) + col_widths.append(col_width) + formats.append({'width': col_width, 'margin': self.margin}) + + formatter = utils.TextFormatter(tuple(formats)) + + log.info(formatter.compose(self.header)) + + sep = [] + for c in col_widths: + sep.append('-'*c) + + log.info(formatter.compose(tuple(sep))) + + for r in self.rows: + log.info(formatter.compose(r)) + + else: + log.error("No data rows") + + + +ALIGN_LEFT = 0 +ALIGN_CENTER = 1 +ALIGN_RIGHT = 2 + + +def align(line, width=70, alignment=ALIGN_LEFT): + space = width - len(line) + + if alignment == ALIGN_CENTER: + return ' '*(space/2) + line + \ + ' '*(space/2 + space%2) + + elif alignment == ALIGN_RIGHT: + return ' '*space + line + + else: + return line + ' '*space + + +def format_paragraph(paragraph, width=None, alignment=ALIGN_LEFT): + if width is None: + width = ttysize()[1] + + result = [] + words = paragraph.split() + try: + current, words = words[0], words[1:] + except IndexError: + return [paragraph] + + for word in words: + increment = 1 + len(word) + + if len(current) + increment > width: + result.append(align(current, width, alignment)) + current = word + + else: + current = current+" "+word + + result.append(align(current, width, alignment)) + return result + + +def printer_table(printers): + header("SELECT PRINTER") + last_used_printer_name = user_conf.get('last_used', 'printer_name') + ret = None + + table = Formatter(header=('Num', 'CUPS Printer'), + max_widths=(8, 100), min_widths=(8, 20)) + + default_index = None + for x, _ in enumerate(printers): + if last_used_printer_name == printers[x]: + table.add((str(x) + '*', printers[x])) + default_index = x + else: + table.add((str(x), printers[x])) + + table.output() + + if default_index is not None: + ok, i = enter_range("\nEnter number 0...%d for printer (q=quit, <enter>=default: *%d) ?" % (x, default_index), + 0, x, default_index) + else: + ok, i = enter_range("\nEnter number 0...%d for printer (q=quit) ?" % x, 0, x) + + if ok: + ret = printers[i] + + return ret + + +def device_table(devices, scan_flag=False): + header("SELECT DEVICE") + last_used_device_uri = user_conf.get('last_used', 'device_uri') + ret = None + + if scan_flag: + table = Formatter(header=('Num', 'Scan device URI'), + max_widths=(8, 100), min_widths=(8, 12)) + else: + table = Formatter(header=('Num', 'Device URI', 'CUPS Printer(s)'), + max_widths=(8, 100, 100), min_widths=(8, 12, 12)) + + default_index = None + device_index = {} + for x, d in enumerate(devices): + device_index[x] = d + if last_used_device_uri == d: + if scan_flag: + table.add((str(x) + "*", d)) + else: + table.add((str(x) + "*", d, ','.join(devices[d]))) + default_index = x + else: + if scan_flag: + table.add((str(x), d)) + else: + table.add((str(x), d, ','.join(devices[d]))) + + table.output() + + if default_index is not None: + ok, i = enter_range("\nEnter number 0...%d for device (q=quit, <enter>=default: %d*) ?" % (x, default_index), + 0, x, default_index) + else: + ok, i = enter_range("\nEnter number 0...%d for device (q=quit) ?" % x, 0, x) + + if ok: + ret = device_index[i] + + return ret + + +def connection_table(): + ret, ios, x = None, {0: ('usb', "Universal Serial Bus (USB)") }, 1 + + if prop.net_build: + ios[x] = ('net', "Network/Ethernet/Wireless (direct connection or JetDirect)") + x += 1 + + if prop.par_build: + ios[x] = ('par', "Parallel Port (LPT:)") + x += 1 + + if len(ios) > 1: + header("SELECT CONNECTION (I/O) TYPE") + + table = Formatter(header=('Num', 'Connection Type', 'Description'), + max_widths=(8, 20, 80), min_widths=(8, 10, 40)) + + for x, data in ios.items(): + if x == 0: + table.add((str(x) + "*", data[0], data[1])) + else: + table.add((str(x), data[0], data[1])) + + table.output() + + ok, val = enter_range("\nEnter number 0...%d for connection type (q=quit, enter=usb*) ? " % x, + 0, x, 0) + + if ok: + ret = [ios[val][0]] + + else: + ret = ['usb'] + + return ret + |