Dynamic list creation for ddlist

Description

Dynamic list creation for drop down list.

What MCU/Processor/Board and compiler are you using?

ESP32

What do you want to achieve?

Populate the dropdown list with the directory list of files from spiffs directory.

What have you tried so far?

I followed the example code from the documentation. Saw that the hardcoded list items are just text with the \n separator between them. I tried making a string out of the directory list and got into trouble inserting the \n. Spent half a day solving it but eventually got over it only to find out that the list should be a pointer object.
My question is: is there a better way of populating the dropdown list rather than using the method i made?

Code to reproduce

The code block(s) should be formatted like:




Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Code in C++ to do that

void FileBrowser::refreshObjects()
{
    lv_ta_set_text(pathBox, path.string().c_str());
    listBox->ClearItems();
    std::vector<dirent> files;
    for (const auto& entry : dirit(path))
    {
        #ifdef _WINDOWS
        if (entry.is_directory())
            files.push_back(entry);
        #else
        if(std::experimental::filesystem::is_directory(entry))
            files.push_back(entry);
        #endif
    }
    for (const auto& entry : dirit(path))
    {
        #ifdef _WINDOWS
        if (!entry.is_directory())
        #else
        if(std::experimental::filesystem::is_directory(entry))
        #endif
        {
            if (ext.empty())
            {
                files.push_back(entry);
            }
            else
            {
                bool add = false;
                for (std::string e : ext)
                    if (entry.path().extension() == e)
                    {
                        add = true;
                        break;
                    }
                if (add)
                    files.push_back(entry);
            }
        }
    }
    for (const auto& element : files)
    {
        std::string icon = LV_SYMBOL_FILE;
        #ifdef _WINDOWS
        if (element.is_directory())
        #else
        if(std::experimental::filesystem::is_directory(element))
        #endif        
            icon = LV_SYMBOL_DIRECTORY;
        pathType p = element.path().filename();
        listBox->AddItem(p.string(), icon);
    }
}

The above uses the STL library to get the files, but thats not really your question.

Thanks rohmer! really appreciate it.
Your pulling me to deeper water too soon :smiley: I’m barely a month here with no formal programming training. I was digesting you code and it seems like it is almost the same as the sample file on SPIFFS. The last two lines in your code are i think what’s important.

Here’s what i have at the moment.

char FileList = "";
char * FileListptr = &FileList;

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
//=======================================================================================
    File root = fs.open(dirname);
    if(!root){
        Serial.println("- failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println(" - not a directory");
        return;
    }
    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.println(file.name());
            FileList = (file.name());
            FileList = ('"' + FileList + "\\n"+ '"');
        }
        file = root.openNextFile();
        Serial.println (FileList);
        return;
    }
}

Maybe i’m making newbie mistake. Dont laugh. Bear with me :stuck_out_tongue:

As far as i known, SPIFFS in ESP32 is not support true directory.

Then the better you should add only files in SPIFFS (not by adding fake directory filename)
and list all the files to your ddlist.

Thanks Trident. Im aware of that. The source code was from espressifs own sample file. Just the same im still figuring out how to get them in the drop down list.

image

First you list all of filenames from espressif sample code
and add them to a new variable with ‘\n’ between filenames.
And use by the upper api.

https://docs.littlevgl.com/en/html/object-types/ddlist.html#_CPPv421lv_ddlist_set_optionsP8lv_obj_tPKc

But that would be hard coding the file list right?

My idea is that files would be uploaded to the spiffs memory and the dropdown list would include all uploaded files there.

Sorry i did make this clear earlier in the post.

You create the option string dynamically too:


    static char opts[256] = {""};

    strcpy(&opts[strlen(opts)], "file1");
    strcpy(&opts[strlen(opts)], "\n");

    strcpy(&opts[strlen(opts)], "file2");
    strcpy(&opts[strlen(opts)], "\n");

    strcpy(&opts[strlen(opts)], "file3");
    strcpy(&opts[strlen(opts)], "\n");

    strcpy(&opts[strlen(opts)], "file4");

    lv_obj_t * ddlist = lv_ddlist_create(lv_scr_act(), NULL);
    lv_ddlist_set_options(ddlist, opts);
1 Like

Whew! Thanks!

I have been working on this this morning. What i only have is this.

 strcat (buf, file.name());
            strcat (buf,"\\n");
            Serial.println(buf);

        }
        file = root.openNextFile();
    }
    FileNames = (buf);
    return ;

i have to make a pointer to the buffer cause the compiler throws an char* to char error. i guess it is caused by the file.name() function of the file system.

anyway, i am sending the buffer to the serial monitor and the result turns out ok. its not loading on the ddlist correctly though. upon checking the value of the reference variable the first few chars are ok then some garbled text. working on it right now.

a few more pointers , pun intended, will be greatly appreciated. :smiley:
regards.

Update:

taking cue from @kisvegabor’s advice, i finally have this code

static char buf[256]= {""};
    File root = fs.open(dirname);
    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.println(file.name());
        } else {
            strcpy (&buf[strlen(buf)],"\"");
            strcpy (&buf[strlen(buf)], file.name());
            strcpy (&buf[strlen(buf)],"\\n");
            strcpy (&buf[strlen(buf)],"\"");
            Serial.println(buf);
        }
        file = root.openNextFile();
    }
    FileNames = (buf);

Output from the serial monitor turns up without the garble characters. However it only shows up as a single line from the drop down list like so:

“/stress_test.gcode\n”"/cover01.stl\n""/electric_turtle.nc\n""/ordbot_handle.nc\n""/arc_rword_test.gcode\n""/enclosure.nc\n""/serial_stress_test.gcode\n""/shapeoko.txt\n""/cover05.stl\n"

thoughts?

Escaping the newline character defeats the purpose of using it (and the quotes are not necessary). This should be enough:

            strcpy (&buf[strlen(buf)], file.name());
            strcpy (&buf[strlen(buf)],"\n");
2 Likes

Thanks everyone! You got it working. :blush: