Updated menu_main() to use RecoveryState obj

* Also fixed rescued size calculations (again)
This commit is contained in:
2Shirt 2018-08-15 21:53:22 -07:00
parent e0a695a673
commit 53a899f967
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C

View file

@ -13,8 +13,8 @@ from functions.data import *
from operator import itemgetter from operator import itemgetter
# STATIC VARIABLES # STATIC VARIABLES
AUTO_NEXT_PASS_1_THRESHOLD = 95 AUTO_PASS_1_THRESHOLD = 95
AUTO_NEXT_PASS_2_THRESHOLD = 98 AUTO_PASS_2_THRESHOLD = 98
DDRESCUE_SETTINGS = { DDRESCUE_SETTINGS = {
'--binary-prefixes': {'Enabled': True, 'Hidden': True}, '--binary-prefixes': {'Enabled': True, 'Hidden': True},
'--data-preview': {'Enabled': True, 'Hidden': True}, '--data-preview': {'Enabled': True, 'Hidden': True},
@ -118,7 +118,8 @@ class BlockPair():
def load_map_data(self): def load_map_data(self):
"""Load data from map file and set progress.""" """Load data from map file and set progress."""
map_data = read_map_file(self.map_path) map_data = read_map_file(self.map_path)
self.rescued = map_data['rescued'] * self.size / 100 self.rescued_percent = map_data['rescued']
self.rescued = (self.rescued_percent * self.size) / 100
if map_data['full recovery']: if map_data['full recovery']:
self.pass_done = [True, True, True] self.pass_done = [True, True, True]
self.rescued = self.size self.rescued = self.size
@ -157,7 +158,8 @@ class BlockPair():
"""Update progress using map file.""" """Update progress using map file."""
if os.path.exists(self.map_path): if os.path.exists(self.map_path):
map_data = read_map_file(self.map_path) map_data = read_map_file(self.map_path)
self.rescued = map_data['rescued'] * self.size self.rescued_percent = map_data['rescued']
self.rescued = (self.rescued_percent * self.size) / 100
self.status[pass_num] = get_formatted_status( self.status[pass_num] = get_formatted_status(
label='Pass {}'.format(pass_num), label='Pass {}'.format(pass_num),
data=(self.rescued/self.size)*100) data=(self.rescued/self.size)*100)
@ -260,6 +262,8 @@ class RecoveryState():
self.dest = dest self.dest = dest
self.block_pairs = [] self.block_pairs = []
self.current_pass = 0 self.current_pass = 0
self.current_pass_str = '0: Initializing'
self.ddrescue_settings = DDRESCUE_SETTINGS.copy()
self.finished = False self.finished = False
self.progress_out = '{}/progress.out'.format(global_vars['LogDir']) self.progress_out = '{}/progress.out'.format(global_vars['LogDir'])
self.rescued = 0 self.rescued = 0
@ -312,6 +316,20 @@ class RecoveryState():
# Safety checks passed # Safety checks passed
self.block_pairs.append(BlockPair(self.mode, source, dest)) self.block_pairs.append(BlockPair(self.mode, source, dest))
def current_pass_done(self):
"""Checks if pass is done for all block-pairs, returns bool."""
done = True
for bp in self.block_pairs:
done &= bp.get_pass_done(self.current_pass)
return done
def current_pass_min(self):
"""Gets minimum pass rescued percentage, returns float."""
min_percent = 100
for bp in self.block_pairs:
min_percent = min(min_percent, bp.rescued)
return min_percent
def self_checks(self): def self_checks(self):
"""Run self-checks for each BlockPair and update state values.""" """Run self-checks for each BlockPair and update state values."""
self.total_size = 0 self.total_size = 0
@ -336,14 +354,23 @@ class RecoveryState():
# Also mark overall recovery as finished if on last pass # Also mark overall recovery as finished if on last pass
self.finished = True self.finished = True
break break
if self.finished:
self.current_pass_str = '- "Done"'
elif pass_num == 0:
self.current_pass_str = '1 "Initial Read"'
elif pass_num == 1:
self.current_pass_str = '2 "Trimming bad areas"'
elif pass_num == 2:
self.current_pass_str = '3 "Scraping bad areas"'
def update_progress(self): def update_progress(self):
"""Update overall progress using block_pairs.""" """Update overall progress using block_pairs."""
self.rescued = 0 self.rescued = 0
for bp in self.block_pairs: for bp in self.block_pairs:
self.rescued += bp.rescued self.rescued += bp.rescued
self.rescued_percent = (self.rescued / self.total_size) * 100
self.status_percent = get_formatted_status( self.status_percent = get_formatted_status(
label='Recovered:', data=(self.rescued/self.total_size)*100) label='Recovered:', data=self.rescued_percent)
self.status_amount = get_formatted_status( self.status_amount = get_formatted_status(
label='', data=human_readable_size(self.rescued)) label='', data=human_readable_size(self.rescued))
@ -626,9 +653,7 @@ def menu_ddrescue(source_path, dest_path, run_mode):
# Main menu # Main menu
build_outer_panes(state) build_outer_panes(state)
# TODO Fix menu_main(state)
#menu_main(source, dest)
pause('Fake Main Menu... ')
# Done # Done
run_program(['tmux', 'kill-window']) run_program(['tmux', 'kill-window'])
@ -638,8 +663,6 @@ def menu_main(source, dest):
"""Main menu is used to set ddrescue settings.""" """Main menu is used to set ddrescue settings."""
title = '{GREEN}ddrescue TUI: Main Menu{CLEAR}\n\n'.format(**COLORS) title = '{GREEN}ddrescue TUI: Main Menu{CLEAR}\n\n'.format(**COLORS)
title += '{BLUE}Current pass: {CLEAR}'.format(**COLORS) title += '{BLUE}Current pass: {CLEAR}'.format(**COLORS)
if 'Settings' not in source:
source['Settings'] = DDRESCUE_SETTINGS.copy()
# Build menu # Build menu
main_options = [ main_options = [
@ -659,14 +682,6 @@ def menu_main(source, dest):
# Show menu # Show menu
while True: while True:
current_pass = source['Current Pass']
display_pass = '1 "Initial Read"'
if current_pass == 'Pass 2':
display_pass = '2 "Trimming bad areas"'
elif current_pass == 'Pass 3':
display_pass = '3 "Scraping bad areas"'
elif current_pass == 'Done':
display_pass = 'Done'
# Update entries # Update entries
for opt in main_options: for opt in main_options:
opt['Name'] = '{} {}'.format( opt['Name'] = '{} {}'.format(
@ -674,7 +689,7 @@ def menu_main(source, dest):
opt['Base Name']) opt['Base Name'])
selection = menu_select( selection = menu_select(
title=title+display_pass, title=title+state.current_pass_str,
main_entries=main_options, main_entries=main_options,
action_entries=actions) action_entries=actions)
@ -685,7 +700,7 @@ def menu_main(source, dest):
elif selection == 'S': elif selection == 'S':
# Set settings for pass # Set settings for pass
settings = [] settings = []
for k, v in source['Settings'].items(): for k, v in state.ddrescue_settings.items():
if not v['Enabled']: if not v['Enabled']:
continue continue
if k[-1:] == '=': if k[-1:] == '=':
@ -707,35 +722,34 @@ def menu_main(source, dest):
if 'Auto' not in opt['Base Name']: if 'Auto' not in opt['Base Name']:
opt['Enabled'] = False opt['Enabled'] = False
# Run ddrecue # Run ddrescue
first_run = True state.started = False
while auto_run or first_run: while auto_run or not state.started:
first_run = False state.started = True
run_ddrescue(source, dest, settings) run_ddrescue(state)
update_progress(source, end_run=True) if state.finished or not auto_run:
if current_pass == 'Done':
# "Pass Done" i.e. all passes done
break break
if not main_options[0]['Enabled']: if state.current_pass_done():
# Auto next pass if (state.current_pass == 0 and
break state.current_pass_min() < AUTO_PASS_1_THRESHOLD):
if source[current_pass]['Done']:
min_status = source[current_pass]['Min Status']
if (current_pass == 'Pass 1' and
min_status < AUTO_NEXT_PASS_1_THRESHOLD):
auto_run = False auto_run = False
elif (current_pass == 'Pass 2' and if (state.current_pass == 1 and
min_status < AUTO_NEXT_PASS_2_THRESHOLD): state.current_pass_min() < AUTO_PASS_2_THRESHOLD):
auto_run = False auto_run = False
else: else:
auto_run = False auto_run = False
# Update current pass for next iteration # Update current pass for next iteration
current_pass = source['Current Pass'] state.set_pass_num()
elif selection == 'C': elif selection == 'C':
menu_settings(source) menu_settings(source)
elif selection == 'Q': elif selection == 'Q':
break if state.rescued_percent < 100:
print_warning('Recovery is less than 100%')
if ask('Are you sure you want to quit?'):
break
else:
break
def menu_settings(source): def menu_settings(source):