summaryrefslogtreecommitdiff
path: root/legacy/elementary/src/bin/test_store.c
blob: 95beb8b38747cdcff909d12c38dc1538d2042d01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/* NOTE : Before testing elm_store,
          email data files should exist in your local storage.
          And you can just get example files in enlightenment website.
          Use wget to obtain it. It almost 50 Megabytes.
          http://www.enlightenment.org/~raster/store.tar.gz
 */

#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>

typedef struct _My_Item My_Item;

struct _My_Item
{
  char *from, *subject, *date, *head_content;
};

// callbacks just to see user interacting with genlist
static void
_st_selected(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
   printf("selected: %p\n", event_info);
}

static void
_st_double_clicked(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
   printf("double clicked: %p\n", event_info);
}

static void
_st_longpress(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
   printf("longpress %p\n", event_info);
}

// store callbacks to handle loading/parsing/freeing of store items from src
static Elm_Genlist_Item_Class *itc1;

static const Elm_Store_Item_Mapping it1_mapping[] =
{
  {
    ELM_STORE_ITEM_MAPPING_LABEL,
      "elm.title.1", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, from),
      { .empty = {
        EINA_TRUE
      } } },
  {
    ELM_STORE_ITEM_MAPPING_LABEL,
      "elm.title.2", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, subject),
      { .empty = {
        EINA_TRUE
      } } },
  {
    ELM_STORE_ITEM_MAPPING_LABEL,
      "elm.text", ELM_STORE_ITEM_MAPPING_OFFSET(My_Item, head_content),
      { .empty = {
        EINA_TRUE
      } } },
  {
    ELM_STORE_ITEM_MAPPING_ICON,
      "elm.swallow.icon", 0,
      { .icon = {
        48, 48,
        ELM_ICON_LOOKUP_THEME_FDO,
        EINA_TRUE, EINA_FALSE,
        EINA_TRUE,
        EINA_FALSE, EINA_FALSE,
      } } },
  {
    ELM_STORE_ITEM_MAPPING_CUSTOM,
      "elm.swallow.end", 0,
      { .custom = {
        NULL
      } } },
  ELM_STORE_ITEM_MAPPING_END
};

////// **** WARNING ***********************************************************
////   * This function runs inside a thread outside efl mainloop. Be careful! *
//     ************************************************************************
static Eina_Bool
_st_store_list(void *data EINA_UNUSED, Elm_Store_Item_Info *item_info)
{
   Elm_Store_Item_Info_Filesystem *info = (Elm_Store_Item_Info_Filesystem *)item_info;
   int id;
   char sort_id[7];

   // create a sort id based on the filename itself assuming it is a numeric
   // value like the id number in mh mail folders which is what this test
   // uses as a data source
   char *file = strrchr(info->path, '/');
   if (file) file++;
   else file = info->path;
   id = atoi(file);
   sort_id[0] = ((id >> 30) & 0x3f) + 32;
   sort_id[1] = ((id >> 24) & 0x3f) + 32;
   sort_id[2] = ((id >> 18) & 0x3f) + 32;
   sort_id[3] = ((id >> 12) & 0x3f) + 32;
   sort_id[4] = ((id >>  6) & 0x3f) + 32;
   sort_id[5] = ((id >>  0) & 0x3f) + 32;
   sort_id[6] = 0;
   info->base.sort_id = strdup(sort_id);
   // choose the item genlist item class to use (only item style should be
   // provided by the app, store will fill everything else in, so it also
   // has to be writable
   info->base.item_class = itc1; // based on item info - return the item class wanted (only style field used - rest reset to internal funcs store sets up to get label/icon etc)
   info->base.mapping = it1_mapping;
   info->base.data = NULL; // if we can already parse and load all of item here and want to - set this
   return EINA_TRUE; // return true to include this, false not to
}
//     ************************************************************************
////   * End of separate thread function.                                     *
////// ************************************************************************

////// **** WARNING ***********************************************************
////   * This function runs inside a thread outside efl mainloop. Be careful! *
//     ************************************************************************
static void
_st_store_fetch(void *data EINA_UNUSED, Elm_Store_Item *sti)
{
   const char *path = elm_store_item_filesystem_path_get(sti);
   My_Item *myit;
   FILE *f;
   char buf[4096], *p;
   Eina_Bool have_content = EINA_FALSE;
   char *content = NULL, *content_pos = NULL, *content_end = NULL;

   // if we already have my item data - skip
   if (elm_store_item_data_get(sti)) return;
   // open the mail file and parse it
   f = fopen(path, "rb");
   if (!f) return;

   // alloc my item in memory that holds data to show in the list
   myit = calloc(1, sizeof(My_Item));
   if (!myit)
     {
        fclose(f);
        return;
     }
   while (fgets(buf, sizeof(buf), f))
     {
        if (!have_content)
          {
             if (!isblank(buf[0]))
               {
                  // get key: From:, Subject: etc.
                  if (!strncmp(buf, "From:", 5))
                    {
                       p = buf + 5;
                       while ((*p) && (isblank(*p))) p++;
                       p = strdup(p);
                       if (p)
                         {
                            myit->from = p;
                            p = strchr(p, '\n');
                            if (p) *p = 0;
                         }
                    }
                  else if (!strncmp(buf, "Subject:", 8))
                    {
                       p = buf + 8;
                       while ((*p) && (isblank(*p))) p++;
                       p = strdup(p);
                       if (p)
                         {
                            myit->subject = p;
                            p = strchr(p, '\n');
                            if (p) *p = 0;
                         }
                    }
                  else if (!strncmp(buf, "Date:", 5))
                    {
                       p = buf + 5;
                       while ((*p) && (isblank(*p))) p++;
                       p = strdup(p);
                       if (p)
                         {
                            myit->date = p;
                            p = strchr(p, '\n');
                            if (p) *p = 0;
                         }
                    }
                  else if (buf[0] == '\n') // begin of content
                    have_content = EINA_TRUE;
               }
          }
        else
          {
             // get first 320 bytes of content/body
             if (!content)
               {
                  content = calloc(1, 320);
                  content_pos = content;
                  content_end = content + 319;
               }
             strncat(content_pos, buf, content_end - content_pos - 1);
             content_pos = content + strlen(content);
          }
     }
   fclose(f);
   myit->head_content = elm_entry_utf8_to_markup(content);
   free(content);
   elm_store_item_data_set(sti, myit);
}
//     ************************************************************************
////   * End of separate thread function.                                     *
////// ************************************************************************

static void
_st_store_unfetch(void *data EINA_UNUSED, Elm_Store_Item *sti)
{
   My_Item *myit = elm_store_item_data_get(sti);
   if (!myit) return;
   if (myit->from) free(myit->from);
   if (myit->subject) free(myit->subject);
   if (myit->date) free(myit->date);
   if (myit->head_content) free(myit->head_content);
   free(myit);
}

void
test_store(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Evas_Object *win, *gl, *bx;
   Elm_Store *st;

   win = elm_win_util_standard_add("store", "Store");
   elm_win_autodel_set(win, EINA_TRUE);

   bx = elm_box_add(win);
   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(win, bx);
   evas_object_show(bx);

   gl = elm_genlist_add(win);
   elm_genlist_mode_set(gl, ELM_LIST_COMPRESS);
   evas_object_smart_callback_add(gl, "selected", _st_selected, NULL);
   evas_object_smart_callback_add(gl, "clicked,double", _st_double_clicked, NULL);
   evas_object_smart_callback_add(gl, "longpressed", _st_longpress, NULL);
   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
   elm_box_pack_end(bx, gl);
   evas_object_show(gl);

   itc1 = elm_genlist_item_class_new();
   itc1->item_style = "message";

   st = elm_store_filesystem_new();
   elm_store_list_func_set(st, _st_store_list, NULL);
   elm_store_fetch_func_set(st, _st_store_fetch, NULL);
   //elm_store_fetch_thread_set(st, EINA_FALSE);
   elm_store_unfetch_func_set(st, _st_store_unfetch, NULL);
   elm_store_sorted_set(st, EINA_TRUE);
   elm_store_target_genlist_set(st, gl);
   elm_store_filesystem_directory_set(st, "./store");

   /* item_class_ref is needed for itc1. some items can be added in callbacks */
   elm_genlist_item_class_ref(itc1);
   elm_genlist_item_class_free(itc1);

   evas_object_resize(win, 480, 800);
   evas_object_show(win);
}