Support
Contribute
Contact
Tracker
Navigation
Personal tools
 

EWL Introduction III

The third EWL introduction builds upon the work done in both EWL Introduction and EWL Introduction II. With the completion of this tutorial your application will be able to display a grid of icons and receive DND drops along with allowing the user to double click on an icon to view the image.

The user can then rotate the image, set the view to 1:1 or fit to window or display a histogram of the image. The user can also flip back to the grid view to select another image to view.

We're going to use an Ewl_Notebook to display the two different screens of the application.

Code Explanation

As with EWL Introduction II I'm only going to explain the sections of code that are new or interesting from what we've seen in EWL Introduction II and EWL Introduction.

   static void handle_image(const char *path);
   static void handle_uri(const char *uri);

To keep things a bit cleaner I've moved the image handling code to after the main function. So, we need to pre-declare the functions.

    static void
    cb_click_icon(Ewl_Widget *w, void *ev, void *data)
    {   
        Ewl_Widget *o, *o2;
        const char *path;
        
        o = ewl_widget_name_find("image");
        if (!o) return;
        
        path = ewl_widget_data_get(w, "file");
        ewl_image_file_path_set(EWL_IMAGE(o), path);
        
        o = ewl_widget_name_find("notebook");
        o2 = ewl_widget_name_find("image_view");
        
        if (!o || !o2) return;
        ewl_notebook_visible_page_set(EWL_NOTEBOOK(o), o2);
    }

When the user clicks on one of the icons in the grid we need to switch the page of the notebook to show our image page and make the image widget show our selected image.

EWL allows you to store arbitrary data on any widget in the system. This is done using ewl_widget_data_set(). You can subsequently retrieve that data using ewl_widget_data_get(). We're making use of that here as a way to pass the file name of our image to the callback. We could have also used the callback data if we wished.

Once we've got our widgets, using ewl_widget_name_find() and have setup the image in the image widget we swap Ewl_Notebook pages. This is done by calling ewl_notebook_visible_page_set() and passing in the widget that we want to make visible. The passed widget has to be the one we added to the notebook.

    static void
    cb_back(Ewl_Widget *w, void *ev, void *data)
    {   
        Ewl_Widget *o, *o2;
        
        o = ewl_widget_name_find("notebook");
        o2 = ewl_widget_name_find("grid_view");
        
        if (!o || !o2) return;
        ewl_notebook_visible_page_set(EWL_NOTEBOOK(o), o2);
    }

cb_back just uses the same ewl_notebook_visible_page_set() to flip back to the grid view from the image view. It works in a similar fashion to cb_click_icon.

    static void
    cb_rotate(Ewl_Widget *w, void *ev, void *data)
    {   
        Ewl_Widget *o;
        
        o = ewl_widget_name_find("image");
        if (!o) return;
        
        ewl_image_rotate(EWL_IMAGE(o), EWL_ROTATE_CW_90);
    }

cb_rotate() is used to rotate the image 90 degrees clockwise. It's triggered when the user clicks on the rotate button. After retrieving the image widget we use ewl_image_rotate() to do the actual rotation work.

   static void
   cb_delete_hist(Ewl_Widget *w, void *ev, void *data)
   {   
       ewl_widget_hide(w);
   }

When the user clicks to close the histogram window we don't actually destroy it. We hide it instead. This way, the next time the user clicks to view a histogram, we've already got the window created and we just need to change the histogram data.

    static void
    cb_histogram(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *win, *o, *img;
        int i;
        int channels[] = {
                EWL_HISTOGRAM_CHANNEL_Y,
                EWL_HISTOGRAM_CHANNEL_R,
                EWL_HISTOGRAM_CHANNEL_G,
                EWL_HISTOGRAM_CHANNEL_B,
                EWL_HISTOGRAM_CHANNEL_MAX
        };

        img = ewl_widget_name_find("image");
        if (!img) return;

        win = ewl_widget_name_find("hist_window");
        if (!win)
        {
                win = ewl_window_new();
                ewl_widget_name_set(win, "hist_window");
                ewl_window_title_set(EWL_WINDOW(win), "viewer histogram");
                ewl_window_class_set(EWL_WINDOW(win), "viewer");
                ewl_window_name_set(EWL_WINDOW(win), "viewer");
                ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, cb_delete_hist, NULL);
                ewl_object_size_request(EWL_OBJECT(win), 400, 250);
        }
        ewl_widget_show(win);

        for (i = 0; channels[i] != EWL_HISTOGRAM_CHANNEL_MAX; i++)
        {
                o = ewl_histogram_new();
                ewl_histogram_channel_set(EWL_HISTOGRAM(o), channels[i]);
                ewl_histogram_image_set(EWL_HISTOGRAM(o), EWL_IMAGE(img));
                ewl_container_child_append(EWL_CONTAINER(win), o);
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_ALL);
                ewl_widget_show(o);
        }
    }

cb_histogram() is called when the user clicks on the histogram button. This will create a new window and display a histogram of the colours in the currently displayed image. When creating a histogram widget you can pick the channel to display histogram information. In our case, we want to use all channels and overlay them. Ends up looking kinda cool.

The histogram itself is created by calling ewl_histogram_new(). We specify the channel to use with ewl_histogram_channel_set() and supply the image we want to generate the histogram from with ewl_histogram_image_set(). The rest is all stuff we've seen before.

    static void
    cb_fit(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *o, *s;

        o = ewl_widget_name_find("image");
        if (!o) return;

        s = ewl_widget_name_find("image_scroll");
        if (!s) return;

        if (ewl_object_fill_policy_get(EWL_OBJECT(o)) != EWL_FLAG_FILL_ALL)
        {
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_ALL);
                ewl_scrollpane_hscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_ALWAYS_HIDDEN);
                ewl_scrollpane_vscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_ALWAYS_HIDDEN);

                ewl_button_label_set(EWL_BUTTON(w), "original");
        }
        else
        {
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_NONE);
                ewl_scrollpane_hscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_AUTO_VISIBLE);
                ewl_scrollpane_vscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_AUTO_VISIBLE);

                ewl_button_label_set(EWL_BUTTON(w), "fit");
        }

        ewl_widget_configure(s);
    }

The cb_fit() callback will be triggered when the user clicks on the fit or original button. This will either make the image fit to the window size or make it display at its original size. The easiest way to do this, and since I'm lazy the one we'll use, is to use EWLs fill policies. First we decide if we want to fit or expand based on the current fill policy. Then, if we're fitting we set the image widget to EWL_FLAG_FILL_ALL and tell the scrollpane to never show its scrollbars.

If we're expanding to our original size we tell the image widget to EWL_FLAG_FILL_NONE and let the scrollpane know it should show the scrollbars when needed.

For an introduction to EWLs fill policies please see: Fill'er Up.

    static Ewl_Widget *
    setup_grid_view(void)
    {
        Ewl_Widget *box, *s, *o;
        const char *drop_types[] = {"text/uri-list", NULL};

        box = ewl_vbox_new();
        ewl_widget_name_set(box, "grid_view");
        ewl_widget_show(box);

        s = ewl_scrollpane_new();
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_show(s);

        o = ewl_freebox_new();
        ewl_container_child_append(EWL_CONTAINER(s), o);
        ewl_dnd_accepted_types_set(o, drop_types);
        ewl_callback_append(o, EWL_CALLBACK_DND_DATA_RECEIVED, cb_dnd_data, NULL);
        ewl_widget_name_set(o, "image_box");
        ewl_widget_show(o);

        s = ewl_hbox_new();
        ewl_object_fill_policy_set(EWL_OBJECT(s), EWL_FLAG_FILL_HFILL |
                                                EWL_FLAG_FILL_VSHRINK);
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_show(s);

        o = ewl_button_new();
        ewl_button_label_set(EWL_BUTTON(o), "clear");
        ewl_callback_append(o, EWL_CALLBACK_CLICKED, cb_clear, NULL);
        ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_SHRINK);
        ewl_container_child_append(EWL_CONTAINER(s), o);
        ewl_widget_show(o);

        return box;
    }

The setup_grid() function is actually the exact same code we saw in EWL Introduction II just split out of the main routine. We're returning a container widget that will be appended into the notebook to form a notebook page.

    static Ewl_Widget *
    setup_image_view(void)
    {
        Ewl_Widget *box, *s, *o;
        int i;
        struct
        {
                char *name;
                void (*cb)(Ewl_Widget *w, void *ev, void *data);
        } buttons [] = {
                {"back", cb_back},
                {"rotate", cb_rotate},
                {"hist", cb_histogram},
                {"fit", cb_fit},
                {NULL, NULL}
        };

        box = ewl_vbox_new();
        ewl_widget_name_set(box, "image_view");
        ewl_widget_show(box);

        s = ewl_scrollpane_new();
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_name_set(s, "image_scroll");
        ewl_widget_show(s);

        o = ewl_image_new();
        ewl_container_child_append(EWL_CONTAINER(s), o);
        ewl_widget_name_set(o, "image");
        ewl_widget_show(o);

        s = ewl_hbox_new();
        ewl_object_fill_policy_set(EWL_OBJECT(s), EWL_FLAG_FILL_HFILL |
                                                EWL_FLAG_FILL_VSHRINK);
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_show(s);

        for (i = 0; buttons[i].name != NULL; i++)
        {
                o = ewl_button_new();
                ewl_button_label_set(EWL_BUTTON(o), buttons[i].name);
                ewl_callback_append(o, EWL_CALLBACK_CLICKED, buttons[i].cb, NULL);
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_SHRINK);
                ewl_container_child_append(EWL_CONTAINER(s), o);
                ewl_widget_show(o);
        }

        return box;
    }

Similar to setup_grid() the setup_image_view() routine will create the page that displays our selected image.

Along with the image we have a toolbar of buttons along the bottom of the application. Since I don't like duplicated code I'm using a simple struct and a for loop to create the buttons. Their basically all the same, just different callbacks and different names.

        box = ewl_notebook_new();
        ewl_notebook_tabbar_visible_set(EWL_NOTEBOOK(box), FALSE);
        ewl_container_child_append(EWL_CONTAINER(win), box);
        ewl_widget_name_set(box, "notebook");
        ewl_widget_show(box);

        s = setup_grid_view();
        ewl_container_child_append(EWL_CONTAINER(box), s);

        s = setup_image_view();
        ewl_container_child_append(EWL_CONTAINER(box), s);

The main() routine is very similar to that seen in EWL Introduction II. The main difference being we create a Ewl_Notebook widget and append the two pages to it.

The notebook is created with ewl_notebook_new() and functions just like any other container. You can use the normal ewl_container_child_*() calls on the notebook. Since we don't want to display the notebook tabs we're calling ewl_notebook_tabbar_visible_set() to tell the notebook to hide the bar.

We then create our two pages and append them into the notebook. If we had of wanted to display the notebook tabs we could assign names to each of the pages by calling ewl_notebook_page_tab_text_set() or ewl_notebook_page_tab_widget_set() and setting the desired values.

      ewl_callback_append(o, EWL_CALLBACK_CLICKED, cb_click_icon, NULL);

The only difference in the handle_image() routine is to add an EWL_CALLBACK_CLICKED callback to the icons as their created.

That's it. You can compile the application with:

   dj2@oni:~/t$ gcc -o view view.c `pkg-config --cflags --libs ewl`

Complete Code Listing


    #include <Ewl.h>
    #include <Ecore_File.h>
    #include <stdio.h>
    #include <string.h>

    #define PATH_MAX 1024

    static void handle_image(const char *path);
    static void handle_uri(const char *uri);

    static void
    cb_window_delete(Ewl_Widget *w, void *ev, void *data)
    {
        ewl_main_quit();
    }

    static void
    cb_key_down(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Event_Key_Down *e;

        e = ev;

        if ((!strcmp(e->base.keyname, "Escape"))
                        || (!strcmp(e->base.keyname, "q")))
                ewl_main_quit();
    }

    static void
    cb_dnd_data(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Event_Dnd_Data_Received *e;
        char ** files;
        int i;

        e = ev;
        files = e->data;

        for (i = 0; i < e->len; i++)
                handle_uri(files[i]);
    }

    static void
    cb_clear(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *free;

        free = ewl_widget_name_find("image_box");
        ewl_container_reset(EWL_CONTAINER(free));
    }

    static void
    cb_click_icon(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *o, *o2;
        const char *path;

        o = ewl_widget_name_find("image");
        if (!o) return;

        path = ewl_widget_data_get(w, "file");
        ewl_image_file_path_set(EWL_IMAGE(o), path);

        o = ewl_widget_name_find("notebook");
        o2 = ewl_widget_name_find("image_view");

        if (!o || !o2) return;
        ewl_notebook_visible_page_set(EWL_NOTEBOOK(o), o2);
    }

    static void
    cb_back(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *o, *o2;

        o = ewl_widget_name_find("notebook");
        o2 = ewl_widget_name_find("grid_view");

        if (!o || !o2) return;
        ewl_notebook_visible_page_set(EWL_NOTEBOOK(o), o2);
    }

    static void
    cb_rotate(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *o;

        o = ewl_widget_name_find("image");
        if (!o) return;

        ewl_image_rotate(EWL_IMAGE(o), EWL_ROTATE_CW_90);
    }

    static void
    cb_delete_hist(Ewl_Widget *w, void *ev, void *data)
    {
        ewl_widget_hide(w);
    }

    static void
    cb_histogram(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *win, *o, *img;
        int i;
        int channels[] = {
                EWL_HISTOGRAM_CHANNEL_Y,
                EWL_HISTOGRAM_CHANNEL_R,
                EWL_HISTOGRAM_CHANNEL_G,
                EWL_HISTOGRAM_CHANNEL_B,
                EWL_HISTOGRAM_CHANNEL_MAX
        };

        img = ewl_widget_name_find("image");
        if (!img) return;
        
        win = ewl_widget_name_find("hist_window");
        if (!win)
        {
                win = ewl_window_new();
                ewl_widget_name_set(win, "hist_window");
                ewl_window_title_set(EWL_WINDOW(win), "viewer histogram");
                ewl_window_class_set(EWL_WINDOW(win), "viewer");
                ewl_window_name_set(EWL_WINDOW(win), "viewer");
                ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, cb_delete_hist, NULL);   
                ewl_object_size_request(EWL_OBJECT(win), 400, 250);
        }
        ewl_widget_show(win);
    
        for (i = 0; channels[i] != EWL_HISTOGRAM_CHANNEL_MAX; i++)
        {
                o = ewl_histogram_new();
                ewl_histogram_channel_set(EWL_HISTOGRAM(o), channels[i]);
                ewl_histogram_image_set(EWL_HISTOGRAM(o), EWL_IMAGE(img));
                ewl_container_child_append(EWL_CONTAINER(win), o);
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_ALL);
                ewl_widget_show(o);
        }
    }
    
    static void
    cb_fit(Ewl_Widget *w, void *ev, void *data)
    {
        Ewl_Widget *o, *s;
        
        o = ewl_widget_name_find("image");
        if (!o) return;
    
        s = ewl_widget_name_find("image_scroll");
        if (!s) return;
    
        if (ewl_object_fill_policy_get(EWL_OBJECT(o)) != EWL_FLAG_FILL_ALL)
        {
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_ALL);
                ewl_scrollpane_hscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_ALWAYS_HIDDEN);
                ewl_scrollpane_vscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_ALWAYS_HIDDEN);
        
                ewl_button_label_set(EWL_BUTTON(w), "original");
        }
        else    
        {       
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_NONE);
                ewl_scrollpane_hscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_AUTO_VISIBLE);  
                ewl_scrollpane_vscrollbar_flag_set(EWL_SCROLLPANE(s), EWL_SCROLLPANE_FLAG_AUTO_VISIBLE);

                ewl_button_label_set(EWL_BUTTON(w), "fit");
        }

        ewl_widget_configure(s);
    }

    static Ewl_Widget *
    setup_grid_view(void)
    {
        Ewl_Widget *box, *s, *o;
        const char *drop_types[] = {"text/uri-list", NULL};

        box = ewl_vbox_new();
        ewl_widget_name_set(box, "grid_view");
        ewl_widget_show(box);

        s = ewl_scrollpane_new();
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_show(s);

        o = ewl_freebox_new();
        ewl_container_child_append(EWL_CONTAINER(s), o);
        ewl_dnd_accepted_types_set(o, drop_types);
        ewl_callback_append(o, EWL_CALLBACK_DND_DATA_RECEIVED, cb_dnd_data, NULL);
        ewl_widget_name_set(o, "image_box");
        ewl_widget_show(o);

        s = ewl_hbox_new();
        ewl_object_fill_policy_set(EWL_OBJECT(s), EWL_FLAG_FILL_HFILL |
                                                EWL_FLAG_FILL_VSHRINK);
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_show(s);

        o = ewl_button_new();
        ewl_button_label_set(EWL_BUTTON(o), "clear");
        ewl_callback_append(o, EWL_CALLBACK_CLICKED, cb_clear, NULL);
        ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_SHRINK);
        ewl_container_child_append(EWL_CONTAINER(s), o);
        ewl_widget_show(o);

        return box;
    }

    static Ewl_Widget *
    setup_image_view(void)
    {
        Ewl_Widget *box, *s, *o;
        int i;
        struct
        {
                char *name;
                void (*cb)(Ewl_Widget *w, void *ev, void *data);
        } buttons [] = {
                {"back", cb_back},
                {"rotate", cb_rotate},
                {"hist", cb_histogram},
                {"fit", cb_fit},
                {NULL, NULL}
        };

        box = ewl_vbox_new();
        ewl_widget_name_set(box, "image_view");
        ewl_widget_show(box);

        s = ewl_scrollpane_new();
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_name_set(s, "image_scroll");
        ewl_widget_show(s);

        o = ewl_image_new();
        ewl_container_child_append(EWL_CONTAINER(s), o);
        ewl_widget_name_set(o, "image");
        ewl_widget_show(o);

        s = ewl_hbox_new();
        ewl_object_fill_policy_set(EWL_OBJECT(s), EWL_FLAG_FILL_HFILL |
                                                EWL_FLAG_FILL_VSHRINK);
        ewl_container_child_append(EWL_CONTAINER(box), s);
        ewl_widget_show(s);

        for (i = 0; buttons[i].name != NULL; i++)
        {
                o = ewl_button_new();
                ewl_button_label_set(EWL_BUTTON(o), buttons[i].name);
                ewl_callback_append(o, EWL_CALLBACK_CLICKED, buttons[i].cb, NULL);
                ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_SHRINK);
                ewl_container_child_append(EWL_CONTAINER(s), o);
                ewl_widget_show(o);
        }

        return box;
    }

    int
    main(int argc, char ** argv)
    {
        Ewl_Widget *win, *box, *s, *o;
        int ret = 1;

        if (!ecore_init())
        {
                fprintf(stderr, "Unable to initialize Ecore.\n");
                goto SHUTDOWN;
        }

        if (!ecore_file_init())
        {
                fprintf(stderr, "Unable to intialize Ecore_File.\n");
                goto ECORE_SHUTDOWN;
        }       
                
        if (!ewl_init(&argc, argv))
        {       
                fprintf(stderr, "Unable to initialize EWL.\n");
                goto ECORE_FILE_SHUTDOWN;
        }
        
        win = ewl_window_new();
        ewl_window_title_set(EWL_WINDOW(win), "viewer");
        ewl_window_class_set(EWL_WINDOW(win), "viewer");
        ewl_window_name_set(EWL_WINDOW(win), "viewer");
        ewl_object_fill_policy_set(EWL_OBJECT(win), EWL_FLAG_FILL_ALL);
        ewl_object_size_request(EWL_OBJECT(win), 640, 480);
        ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, cb_window_delete, NULL);
        ewl_callback_append(win, EWL_CALLBACK_KEY_DOWN, cb_key_down, NULL);
        ewl_widget_name_set(win, "main_win");
        ewl_widget_show(win);
        
        box = ewl_notebook_new();
        ewl_notebook_tabbar_visible_set(EWL_NOTEBOOK(box), FALSE);
        ewl_container_child_append(EWL_CONTAINER(win), box);
        ewl_widget_name_set(box, "notebook");
        ewl_widget_show(box);                   
        
        s = setup_grid_view();
        ewl_container_child_append(EWL_CONTAINER(box), s);
        
        s = setup_image_view();
        ewl_container_child_append(EWL_CONTAINER(box), s);
                
        if (argc > 1)
                handle_uri(argv[1]);
                
        ewl_main();
        ret = 0;

    ECORE_FILE_SHUTDOWN:
        ecore_file_shutdown();
    ECORE_SHUTDOWN:
        ecore_shutdown();
    SHUTDOWN:
        return ret;
    }   
        
    static void
    handle_image(const char *path)
    {   
        Ewl_Widget *free, *o;
        char *file;
        
        free = ewl_widget_name_find("image_box");
        
        file = strrchr(path, '/');
        if (file) file++;
                
        o = ewl_icon_new();
        ewl_icon_image_set(EWL_ICON(o), path, NULL);
        ewl_icon_label_set(EWL_ICON(o), file);
        ewl_icon_constrain_set(EWL_ICON(o), 128);
        ewl_widget_data_set(o, "file", strdup(path));
        ewl_container_child_append(EWL_CONTAINER(free), o);
        ewl_callback_append(o, EWL_CALLBACK_CLICKED, cb_click_icon, NULL);
        ewl_widget_show(o);
    }

    static void
    handle_uri(const char *uri)
    {
        const char *ptr = NULL;

        /* see if this is a file pointer */
        if (!strncmp(uri, "file://", 7))
                ptr = uri + 7;
        else
                ptr = uri;

        /* do nothing if the file doesn't exists. not sure if this can
         * happen or not */
        if (!ecore_file_exists(ptr))
                return;

        if (ecore_file_is_dir(ptr))
        {
                Ecore_List *files;
                char *file, path[PATH_MAX];

                files = ecore_file_ls(ptr);
                while ((file = ecore_list_first_remove(files)))
                {
                        snprintf(path, sizeof(path), "%s/%s", ptr, file);
                        handle_image(path);

                        free(file);
                }
                ecore_list_destroy(files);
        }
        else
                handle_image(ptr);
    }