Search code examples
bashuser-interfacedialogcalibre

Trying to make a dynamic dialog bash menu (form, input, info, fselect)


I want to make a script to add some books or folder to calibredb, i want to use bash gui with dialog. I'm pretty new and learning by myself so the code can be weird..

My main_menu look like this :

function main_menu(){

    MENU=$(dialog --clear --title "Calibre" \
        --backtitle "Add Books" \
        --menu "What to do ?" \
        0 0 0 "C" "Choose a book or a folder" "M" "Enter metadata infos" "L" "Add selected Book(s)" "D" "Change default Directory for books" "E" "Exit" \
        2>&1 >/dev/tty)
        
    if [ $MENU = "C" ];then
        select=$(file_selector $mnt)
    elif [ $MENU = "M" ];then
        form_data
    elif [ $MENU = "L" ];then
        if [ -d $select ];then
            add_folder $select
        elif [ -f $select ];then
            if [[ $file == *.cbz || $file == *.pdf ]]; then
                add_book $select
            else
                error "Books should has extension .cbz .pdf"
            fi
        else
            error "No file or folder selected"
        fi
    elif [ $MENU = "D" ];then
        NEWDIR=$(file_selector $mnt)
    
    elif [ $MENU = "E" ];then
        exit
    fi
    
}

When I type M to go to function submenu form_data it works at launch, but not if i go in others submenus first. Also i used if statement and not case because i can't get it, always errors at launch. My form_data function is :

function form_data() { 
    auth=""
    serie=""
    tag=""
    ind="1"

    echo "form data" 
    exec 3>&1
    IFS=$'\n'
    VALUES=($(dialog --clear --ok-label "Submit" \
          --backtitle "Calibre" \
          --title "Manager" \
          --form "Add a book" \
        15 50 0 \
        "Author's name:" 1 1    "$auth"     1 20 30 0 \
        "Serie's name:"    2 1  "$serie"    2 20 30 0 \
        "Tag:"    3 1   "$tag"      3 20 30 0 \
        "Serie's index (int):"     4 1  "$ind"  4 20 30 0 \
        2>&1 1>&3))
    
    exec 3>&-
    main_menu
}

As you can see i call the main_menu at the end cause i want to back to it when i Submit the form. Pretty not sure that's the way to do this.

Also a lot of info dialog box doesn't work properly.

function error() {
    dialog --clear --title "Error : " --msgbox $1 10 50
    sleep 1
    main_menu
}

And finally the goal is to call the add_book or add_folder function to put in calibre, i didn't try but i expect to show a progress bar in dialog but i don't if the calibredb can return it's progress :

function add_folder() { 
    echo "add folder "
    echo $1
    echo ${VALUES[@]}
    nbBooks=$(find $1 -maxdepth 1 -type f | wc -l);
    listBooks=($(find $1 -maxdepth 1 -type f))
    for (( i; i<=$nbBooks; i++ )); do
            calibredb add -a "${VALUES[0]}" -s "${VALUES[1]}" -T "${VALUES[2]}" -S "$i" "${listBooks[$i]}" --with-library /home/gregory/books

    done
    main_menu
}

After a lot of headache, reading documentation, you are all my last hope to understand the way to this. Thanks in advance.


Solution

  • Don't use recursion to repeat the main menu, use a top-level loop.

    function main_menu(){
        while :; do
            MENU=$(dialog --clear --title "Calibre" \
                --backtitle "Add Books" \
                --menu "What to do ?" \
                0 0 0 "C" "Choose a book or a folder" "M" "Enter metadata infos" "L" "Add selected Book(s)" "D" "Change default Directory for books" "E" "Exit" \
                2>&1 >/dev/tty)
            case "$MENU" in
            C)
                select=$(file_selector $mnt) ;;
            M)
                form_data ;;
            L)
                if [ -d "$select" ];then
                    add_folder "$select"
                elif [ -f "$select" ];then
                    if [[ "$select" == *.cbz || "$select" == *.pdf ]]; then
                        add_book "$select"
                    else
                        error "Books should have extension .cbz or .pdf"
                    fi
                else
                    error "No file or folder selected"
                fi ;;
            D)
                NEWDIR=$(file_selector $mnt) ;;
            E) 
                exit ;;
            esac
        done    
    }
    

    Then your other functions should simply return rather than calling main_menu.