2020-08-03 22:40:07 +02:00
/**
* @ file tui . cpp
* @ brief display user interface
* @ author hendrik schutter
* @ date 03.08 .2020
*/
2020-08-04 22:35:29 +02:00
2020-08-23 09:26:32 +02:00
# include "../include/reHDD.h"
2020-08-04 22:35:29 +02:00
2020-08-07 11:38:00 +02:00
TUI : : TUI ( void )
{
2020-08-04 22:35:29 +02:00
}
2020-08-03 22:40:07 +02:00
/**
* \ brief wipe drive with shred
* \ param pointer of Drive instance
* \ return void
*/
2020-08-04 22:35:29 +02:00
2020-08-03 22:40:07 +02:00
void TUI : : initTUI ( )
{
initscr ( ) ;
raw ( ) ;
keypad ( stdscr , TRUE ) ;
2020-08-07 11:38:00 +02:00
if ( has_colors ( ) = = TRUE )
{
start_color ( ) ;
}
else
{
printf ( " Your terminal does not support color \n " ) ;
exit ( 1 ) ;
}
2020-08-03 22:40:07 +02:00
clear ( ) ;
curs_set ( 0 ) ;
2020-08-06 22:45:05 +02:00
noecho ( ) ;
cbreak ( ) ;
2020-08-06 11:41:38 +02:00
init_pair ( COLOR_AREA_STDSCR , COLOR_WHITE , COLOR_BLUE ) ;
wbkgd ( stdscr , COLOR_PAIR ( COLOR_AREA_STDSCR ) ) ;
2020-08-07 16:17:45 +02:00
init_pair ( COLOR_AREA_ENTRY , COLOR_BLACK , COLOR_WHITE ) ;
init_pair ( COLOR_AREA_ENTRY_SELECTED , COLOR_BLACK , COLOR_RED ) ;
init_pair ( COLOR_AREA_OVERVIEW , COLOR_BLACK , COLOR_WHITE ) ;
init_pair ( COLOR_AREA_DETAIL , COLOR_BLACK , COLOR_WHITE ) ;
2020-08-07 11:38:00 +02:00
2020-08-06 22:45:05 +02:00
mvprintw ( 0 , 2 , " reHDD - HDD refurbishing tool - GPL 3.0 " ) ;
2020-08-03 22:40:07 +02:00
}
2020-08-26 18:38:39 +02:00
void TUI : : updateTUI ( vector < Drive > * pvecDrives , uint8_t u8SelectedEntry )
2020-08-07 11:38:00 +02:00
{
2020-08-04 22:35:29 +02:00
int stdscrX , stdscrY ;
getmaxyx ( stdscr , stdscrY , stdscrX ) ;
init_pair ( COLOR_AREA_STDSCR , COLOR_WHITE , COLOR_BLUE ) ;
wbkgd ( stdscr , COLOR_PAIR ( COLOR_AREA_STDSCR ) ) ;
2020-08-06 11:41:38 +02:00
2020-08-04 22:35:29 +02:00
refresh ( ) ;
2020-08-03 22:40:07 +02:00
2020-08-04 22:35:29 +02:00
overview = createOverViewWindow ( ( int ) ( stdscrX / 3 ) , ( stdscrY - 15 ) ) ;
wrefresh ( overview ) ;
2020-08-03 22:40:07 +02:00
2020-08-07 22:52:11 +02:00
systemview = createSystemStats ( ( int ) ( stdscrX / 3 ) , 10 , ( stdscrY - 11 ) ) ;
wrefresh ( systemview ) ;
2020-08-23 10:42:03 +02:00
delwin ( detailview ) ;
2020-08-04 22:35:29 +02:00
vector < Drive > : : iterator it ;
for ( it = pvecDrives - > begin ( ) ; it ! = pvecDrives - > end ( ) ; + + it )
2020-08-07 11:38:00 +02:00
{
string sModelFamily = it - > getModelFamily ( ) ;
string sModelName = it - > getModelName ( ) ;
string sCapacity = it - > sCapacityToText ( ) ;
2020-08-23 10:42:03 +02:00
string sState = " " ;
2020-08-07 11:38:00 +02:00
bool bSelectedEntry = false ;
2020-08-26 18:38:39 +02:00
if ( u8SelectedEntry = = ( it - pvecDrives - > begin ( ) ) )
2020-08-07 11:38:00 +02:00
{
2020-08-23 09:26:32 +02:00
bSelectedEntry = true ; //mark this drive in entries list
2020-08-26 18:38:39 +02:00
displaySelectedDrive ( pvecDrives - > at ( u8SelectedEntry ) , stdscrX , stdscrY ) ;
2020-08-07 11:38:00 +02:00
}
2020-08-28 15:28:57 +02:00
stringstream stream ;
2020-08-23 09:26:32 +02:00
switch ( it - > state )
{
case Drive : : SHRED_ACTIVE :
2020-08-28 15:28:57 +02:00
stream < < fixed < < setprecision ( 2 ) < < ( it - > getTaskPercentage ( ) ) ;
sState = " Shredding: " + stream . str ( ) + " % " ;
2020-08-23 09:26:32 +02:00
break ;
case Drive : : DELETE_ACTIVE :
sState = " Deleting ... " ;
break ;
case Drive : : NONE :
case Drive : : SHRED_SELECTED :
case Drive : : DELETE_SELECTED :
if ( it - > bWasDeleteted )
{
sState = " DELETED " ; //mark drive as deleted previously
}
if ( it - > bWasShredded )
{
sState = " SHREDDED " ; //mark drive as shreded previously, overwrite if deleted
}
break ;
default :
break ;
}
WINDOW * tmp = createEntryWindow ( ( ( int ) ( stdscrX / 3 ) - 2 ) , 5 , 3 , ( 5 * ( it - pvecDrives - > begin ( ) ) ) + 3 , sModelFamily , sModelName , sCapacity , sState , bSelectedEntry ) ;
2020-08-07 11:38:00 +02:00
wrefresh ( tmp ) ;
2020-08-26 18:38:39 +02:00
} //end loop though drives
if ( pvecDrives - > size ( ) = = 0 )
{
//no selected drive present
struct MenuState menustate ;
menustate . bAbort = false ;
menustate . bConfirmDelete = false ;
menustate . bConfirmShred = false ;
menustate . bDelete = false ;
menustate . bShred = false ;
menuview = createMenuView ( ( ( stdscrX ) - ( int ) ( stdscrX / 3 ) - 7 ) , 10 , ( int ) ( stdscrX / 3 ) + 5 , ( stdscrY - 11 ) , menustate ) ;
wrefresh ( menuview ) ;
detailview = overwriteDetailViewWindow ( ( ( stdscrX ) - ( int ) ( stdscrX / 3 ) - 7 ) , ( stdscrY - 15 ) , ( int ) ( stdscrX / 3 ) + 5 ) ;
wrefresh ( detailview ) ;
2020-08-07 11:38:00 +02:00
}
2020-08-06 22:45:05 +02:00
}
2020-08-04 22:35:29 +02:00
2020-08-07 11:38:00 +02:00
enum TUI : : UserInput TUI : : readUserInput ( )
{
int ch = wgetch ( stdscr ) ;
switch ( ch )
2020-08-06 22:45:05 +02:00
{
case KEY_UP :
return TUI : : UserInput : : UpKey ;
break ;
case KEY_DOWN :
return TUI : : UserInput : : DownKey ;
break ;
case 10 :
return TUI : : UserInput : : Enter ;
break ;
case 27 :
return TUI : : UserInput : : ESC ;
break ;
case ' a ' :
return TUI : : UserInput : : Abort ;
break ;
case ' d ' :
return TUI : : UserInput : : Delete ;
break ;
case ' s ' :
return TUI : : UserInput : : Shred ;
break ;
default :
return TUI : : UserInput : : Undefined ;
break ;
}
return TUI : : UserInput : : Undefined ;
2020-08-04 22:35:29 +02:00
}
2020-08-07 11:38:00 +02:00
void TUI : : centerTitle ( WINDOW * pwin , const char * title )
{
2020-08-04 22:35:29 +02:00
int x , maxX , stringSize ;
getmaxyx ( pwin , maxX , maxX ) ;
stringSize = 4 + strlen ( title ) ;
x = ( maxX - stringSize ) / 2 ;
mvwaddch ( pwin , 0 , x , ACS_RTEE ) ;
waddch ( pwin , ' ' ) ;
waddstr ( pwin , title ) ;
waddch ( pwin , ' ' ) ;
waddch ( pwin , ACS_LTEE ) ;
}
2020-08-07 11:38:00 +02:00
WINDOW * TUI : : createOverViewWindow ( int iXSize , int iYSize )
{
2020-08-04 22:35:29 +02:00
WINDOW * newWindow ;
newWindow = newwin ( iYSize , iXSize , 2 , 2 ) ;
2020-08-07 11:38:00 +02:00
2020-08-04 22:35:29 +02:00
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_OVERVIEW ) ) ;
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
2020-08-07 22:52:11 +02:00
centerTitle ( newWindow , " Detected Drives " ) ;
2020-08-04 22:35:29 +02:00
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-04 22:35:29 +02:00
return newWindow ;
}
2020-08-07 12:07:29 +02:00
WINDOW * TUI : : createDetailViewWindow ( int iXSize , int iYSize , int iXStart , Drive drive )
2020-08-07 11:38:00 +02:00
{
2020-08-04 22:35:29 +02:00
WINDOW * newWindow ;
newWindow = newwin ( iYSize , iXSize , 2 , iXStart ) ;
2020-08-07 16:17:45 +02:00
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_DETAIL ) ) ;
2020-08-04 22:35:29 +02:00
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
2020-08-26 18:38:39 +02:00
2020-08-07 12:07:29 +02:00
string title = " Selected Drive: " + drive . getModelName ( ) + " " + drive . sCapacityToText ( ) ;
centerTitle ( newWindow , title . c_str ( ) ) ;
2020-08-07 16:17:45 +02:00
string sPath = " Path: " + drive . getPath ( ) ;
string sModelFamlily = " ModelFamily: " + drive . getModelFamily ( ) ;
string sModelName = " ModelName: " + drive . getModelName ( ) ;
string sCapacity = " Capacity: " + drive . sCapacityToText ( ) ;
string sSerial = " Serial: " + drive . getSerial ( ) ;
string sPowerOnHours = " PowerOnHours: " + drive . sPowerOnHoursToText ( ) ;
string sPowerCycle = " PowerCycle: " + drive . sPowerCyclesToText ( ) ;
string sErrorCount = " ErrorCount: " + drive . sErrorCountToText ( ) ;
2020-08-07 12:07:29 +02:00
2020-08-07 16:17:45 +02:00
uint16_t u16Line = 2 ;
2020-08-07 12:07:29 +02:00
2020-08-07 16:17:45 +02:00
mvwaddstr ( newWindow , u16Line + + , 3 , sPath . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sModelFamlily . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sModelName . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sCapacity . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sSerial . c_str ( ) ) ;
2020-08-07 12:07:29 +02:00
2020-08-07 16:17:45 +02:00
attroff ( COLOR_PAIR ( COLOR_AREA_DETAIL ) ) ;
2020-08-04 22:35:29 +02:00
2020-08-07 16:17:45 +02:00
if ( drive . getPowerOnHours ( ) > = WORSE_HOURS )
{
mvwaddstr ( newWindow , u16Line + + , 3 , " ------------> WARNING: OPERATING HOURS <----------- " ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sPowerOnHours . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , " --------------------------------------------------- " ) ;
}
else
{
mvwaddstr ( newWindow , u16Line + + , 3 , sPowerOnHours . c_str ( ) ) ;
}
if ( drive . getPowerCycles ( ) > = WORSE_POWERUP )
{
mvwaddstr ( newWindow , u16Line + + , 3 , " ------------> WARNING: POWER-ON <------------------ " ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sPowerCycle . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , " --------------------------------------------------- " ) ;
}
else
{
mvwaddstr ( newWindow , u16Line + + , 3 , sPowerCycle . c_str ( ) ) ;
}
if ( drive . getErrorCount ( ) > 0 )
{
mvwaddstr ( newWindow , u16Line + + , 3 , " ------------> WARNING: S.M.A.R.T ERROR <----------- " ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , sErrorCount . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , " --------------------------------------------------- " ) ;
}
else
{
mvwaddstr ( newWindow , u16Line + + , 3 , sErrorCount . c_str ( ) ) ;
}
2020-08-09 21:41:28 +02:00
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-04 22:35:29 +02:00
return newWindow ;
}
2020-08-26 18:38:39 +02:00
WINDOW * TUI : : overwriteDetailViewWindow ( int iXSize , int iYSize , int iXStart )
{
WINDOW * newWindow ;
newWindow = newwin ( iYSize , iXSize , 2 , iXStart ) ;
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_DETAIL ) ) ;
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
string title = " About this tool " ;
centerTitle ( newWindow , title . c_str ( ) ) ;
string sLine01 = " Path: NextLine " ;
string sLine02 = " Path: NextLine " ;
string sLine03 = " Path: NextLine " ;
string sLine04 = " Path: NextLine " ;
string sLine05 = " Path: NextLine " ;
string sLine06 = " Path: NextLine " ;
string sLine07 = " Path: NextLine " ;
uint16_t u16Line = 5 ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine01 . size ( ) / 2 ) , sLine01 . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine02 . size ( ) / 2 ) , sLine02 . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine03 . size ( ) / 2 ) , sLine03 . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine04 . size ( ) / 2 ) , sLine04 . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine05 . size ( ) / 2 ) , sLine05 . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine06 . size ( ) / 2 ) , sLine06 . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , ( iXSize / 2 ) - ( sLine07 . size ( ) / 2 ) , sLine07 . c_str ( ) ) ;
attroff ( COLOR_PAIR ( COLOR_AREA_DETAIL ) ) ;
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-26 18:38:39 +02:00
return newWindow ;
}
2020-08-23 09:26:32 +02:00
WINDOW * TUI : : createEntryWindow ( int iXSize , int iYSize , int iXStart , int iYStart , string sModelFamily , string sModelName , string sCapacity , string sState , bool bSelected )
2020-08-07 11:38:00 +02:00
{
2020-08-04 22:35:29 +02:00
WINDOW * newWindow ;
newWindow = newwin ( iYSize , iXSize , iYStart , iXStart ) ;
2020-08-07 11:38:00 +02:00
if ( ! bSelected )
{
// entry is NOT selected
attron ( COLOR_PAIR ( COLOR_AREA_ENTRY ) ) ;
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_ENTRY ) ) ;
}
else
{
// entry IS selected
attron ( COLOR_PAIR ( COLOR_AREA_ENTRY ) ) ;
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_ENTRY_SELECTED ) ) ;
}
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
2020-08-06 22:45:05 +02:00
2020-08-06 11:41:38 +02:00
mvwaddstr ( newWindow , 1 , 1 , sModelFamily . c_str ( ) ) ;
mvwaddstr ( newWindow , 2 , 1 , sModelName . c_str ( ) ) ;
mvwaddstr ( newWindow , 3 , 1 , sCapacity . c_str ( ) ) ;
2020-08-04 22:35:29 +02:00
2020-08-23 09:26:32 +02:00
mvwaddstr ( newWindow , 2 , iXSize - sState . length ( ) - 5 , sState . c_str ( ) ) ;
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-04 22:35:29 +02:00
return newWindow ;
}
2020-08-07 22:52:11 +02:00
2020-08-09 21:41:28 +02:00
WINDOW * TUI : : createSystemStats ( int iXSize , int iYSize , int iYStart )
{
2020-08-07 22:52:11 +02:00
2020-08-09 21:41:28 +02:00
WINDOW * newWindow ;
2020-08-07 22:52:11 +02:00
newWindow = newwin ( iYSize , iXSize , iYStart , 2 ) ;
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_OVERVIEW ) ) ;
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
centerTitle ( newWindow , " System " ) ;
time_t rawtime ;
struct tm * timeinfo ;
char buffer [ 80 ] ;
time ( & rawtime ) ;
timeinfo = localtime ( & rawtime ) ;
strftime ( buffer , sizeof ( buffer ) , " Date: %d-%m-%Y Time: %H:%M " , timeinfo ) ;
string time ( buffer ) ;
mvwaddstr ( newWindow , 2 , 2 , time . c_str ( ) ) ;
2020-08-09 21:41:28 +02:00
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-09 21:41:28 +02:00
return newWindow ;
}
WINDOW * TUI : : createMenuView ( int iXSize , int iYSize , int iXStart , int iYStart , struct MenuState menustate )
{
WINDOW * newWindow ;
newWindow = newwin ( iYSize , iXSize , iYStart , iXStart ) ;
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_OVERVIEW ) ) ;
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
centerTitle ( newWindow , " Controls " ) ;
uint16_t u16Line = 2 ;
if ( menustate . bAbort )
{
mvwaddstr ( newWindow , u16Line + + , 3 , " Press A for Abort " ) ;
}
if ( menustate . bShred )
{
mvwaddstr ( newWindow , u16Line + + , 3 , " Press S for Shred " ) ;
}
if ( menustate . bDelete )
{
mvwaddstr ( newWindow , u16Line + + , 3 , " Press D for Delete " ) ;
}
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-09 23:05:32 +02:00
return newWindow ;
}
WINDOW * TUI : : createDialog ( int iXSize , int iYSize , int iXStart , int iYStart , string task , string optionA , string optionB )
{
WINDOW * newWindow ;
newWindow = newwin ( iYSize , iXSize , iYStart , iXStart ) ;
wbkgd ( newWindow , COLOR_PAIR ( COLOR_AREA_ENTRY_SELECTED ) ) ;
box ( newWindow , ACS_VLINE , ACS_HLINE ) ;
centerTitle ( newWindow , task . c_str ( ) ) ;
uint16_t u16Line = 2 ;
mvwaddstr ( newWindow , u16Line + + , 3 , optionA . c_str ( ) ) ;
mvwaddstr ( newWindow , u16Line + + , 3 , optionB . c_str ( ) ) ;
2020-08-09 21:41:28 +02:00
2020-08-28 15:28:57 +02:00
//keypad(newWindow, TRUE);
2020-08-07 22:52:11 +02:00
return newWindow ;
}
2020-08-10 22:52:13 +02:00
void TUI : : displaySelectedDrive ( Drive drive , int stdscrX , int stdscrY )
{
struct MenuState menustate ;
menustate . bAbort = false ;
menustate . bConfirmDelete = false ;
menustate . bConfirmShred = false ;
menustate . bDelete = false ;
menustate . bShred = false ;
// set menustate based on drive state
switch ( drive . state )
{
case Drive : : NONE : //no task running or selected for this drive
menustate . bShred = true ;
menustate . bDelete = true ;
break ;
case Drive : : DELETE_ACTIVE : //delete task running for this drive
menustate . bAbort = true ;
break ;
case Drive : : SHRED_ACTIVE : //shred task running for this drive
menustate . bAbort = true ;
break ;
case Drive : : DELETE_SELECTED : //delete task selected for this drive
menustate . bConfirmDelete = true ;
break ;
case Drive : : SHRED_SELECTED : //shred task selected for this drive
menustate . bConfirmShred = true ;
break ;
default :
break ;
}
detailview = createDetailViewWindow ( ( ( stdscrX ) - ( int ) ( stdscrX / 3 ) - 7 ) , ( stdscrY - 15 ) , ( int ) ( stdscrX / 3 ) + 5 , drive ) ;
wrefresh ( detailview ) ;
menuview = createMenuView ( ( ( stdscrX ) - ( int ) ( stdscrX / 3 ) - 7 ) , 10 , ( int ) ( stdscrX / 3 ) + 5 , ( stdscrY - 11 ) , menustate ) ;
wrefresh ( menuview ) ;
if ( menustate . bConfirmShred = = true )
{
dialog = createDialog ( 70 , 10 , ( ( stdscrX ) - ( int ) ( stdscrX / 3 ) - 7 ) - ( int ) ( ( stdscrX / 3 ) + 5 ) / 2 , ( int ) ( stdscrY / 2 ) - 5 , " Confirm SHRED " , " Press ENTER for SHRED " , " Press ESC for cancel " ) ;
wrefresh ( dialog ) ;
}
else if ( menustate . bConfirmDelete = = true )
{
dialog = createDialog ( 70 , 10 , ( ( stdscrX ) - ( int ) ( stdscrX / 3 ) - 7 ) - ( int ) ( ( stdscrX / 3 ) + 5 ) / 2 , ( int ) ( stdscrY / 2 ) - 5 , " Confirm DELETE " , " Press ENTER for DELETE " , " Press ESC for cancel " ) ;
wrefresh ( dialog ) ;
}
else
{
delwin ( dialog ) ;
}
}