Add the identifying header
[kugel-rb.git] / apps / plugins / shortcuts / shortcuts_view.c
bloba63e26d7c61449397e3e200bf8cd41406b16dbca
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Bryan Childs
11 * Copyright (c) 2007 Alexander Levin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 #include "shortcuts.h"
25 PLUGIN_HEADER
27 enum sc_list_action_type
29 SCLA_NONE,
30 SCLA_SELECT,
31 SCLA_DELETE,
32 SCLA_USB,
36 static char *link_filename;
37 static bool user_file;
38 static bool usb_connected = false;
40 enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc);
42 /* Will be passed sc_file* as data */
43 static const char* build_sc_list(int selected_item, void *data,
44 char *buffer, size_t buffer_len);
46 /* Returns true iff we should leave the main loop */
47 bool list_sc(void);
49 bool goto_entry(char *file_or_dir);
50 bool ends_with(char *str, char *suffix);
53 enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc)
55 int button;
57 rb->gui_synclist_draw(gui_sc);
59 while (true) {
60 /* user input */
61 button = rb->get_action(CONTEXT_LIST, HZ);
62 /* HZ so the status bar redraws corectly */
63 if (rb->gui_synclist_do_button(gui_sc, &button,
64 LIST_WRAP_UNLESS_HELD)) {
65 /* automatic handling of user input.
66 * _UNLESS_HELD can be _ON or _OFF also
67 * selection changed, so redraw */
68 continue;
70 switch (button) { /* process the user input */
71 case ACTION_STD_OK:
72 return SCLA_SELECT;
73 case ACTION_STD_MENU:
74 /* Only allow delete entries in the default file
75 * since entries can be appended (with a plugin)
76 * to the default file only. The behaviour is thus
77 * symmetric in this respect. */
78 if (!user_file) {
79 return SCLA_DELETE;
81 break;
82 case ACTION_STD_CANCEL:
83 return SCLA_NONE;
84 default:
85 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) {
86 return SCLA_USB;
93 static const char* build_sc_list(int selected_item, void *data,
94 char *buffer, size_t buffer_len)
96 sc_file_t *file = (sc_file_t*)data;
98 if (!is_valid_index(file, selected_item)) {
99 return NULL;
101 sc_entry_t *entry = file->entries + selected_item;
102 rb->snprintf(buffer, buffer_len, "%s", entry->disp);
103 return buffer;
107 bool list_sc(void)
109 int selected_item = 0;
110 enum sc_list_action_type action = SCLA_NONE;
111 struct gui_synclist gui_sc;
113 /* Setup the GUI list object, draw it to the screen,
114 * and then handle the user input to it */
115 rb->gui_synclist_init(&gui_sc, &build_sc_list, &sc_file, false, 1, NULL);
116 rb->gui_synclist_set_title(&gui_sc,
117 (user_file?"Shortcuts (sealed)":"Shortcuts (editable)"), NOICON);
118 rb->gui_synclist_set_nb_items(&gui_sc, sc_file.entry_cnt);
119 rb->gui_synclist_limit_scroll(&gui_sc, false);
120 rb->gui_synclist_select_item(&gui_sc, 0);
122 /* Draw the prepared widget to the LCD now */
123 action = draw_sc_list(&gui_sc);
124 if (action == SCLA_USB) {
125 usb_connected = true;
126 return true;
129 /* which item do we action? */
130 selected_item = rb->gui_synclist_get_sel_pos(&gui_sc);
132 if (!is_valid_index(&sc_file, selected_item)) {
133 /* This should never happen */
134 rb->splash(HZ*2, "Bad entry selected!");
135 return true;
138 /* perform the following actions if the user "selected"
139 * the item in the list (i.e. they want to go there
140 * in the filebrowser tree */
141 switch(action) {
142 case SCLA_SELECT:
143 return goto_entry(sc_file.entries[selected_item].path);
144 case SCLA_DELETE:
145 rb->splashf(HZ, "Deleting %s", sc_file.entries[selected_item].disp);
146 remove_entry(&sc_file, selected_item);
147 dump_sc_file(&sc_file, link_filename);
148 return (sc_file.entry_cnt == 0);
149 default:
150 return true;
155 bool goto_entry(char *file_or_dir)
157 DEBUGF("Trying to go to '%s'...\n", file_or_dir);
159 bool is_dir = ends_with(file_or_dir, PATH_SEPARATOR);
160 bool exists;
161 char *what;
162 if (is_dir) {
163 what = "Directory";
164 exists = rb->dir_exists(file_or_dir);
165 } else {
166 what = "File";
167 exists = rb->file_exists(file_or_dir);
170 if (!exists) {
171 rb->splashf(HZ*2, "%s %s no longer exists on disk", what, file_or_dir);
172 return false;
174 /* Set the browsers dirfilter to the global setting
175 * This is required in case the plugin was launched
176 * from the plugins browser, in which case the
177 * dirfilter is set to only display .rock files */
178 rb->set_dirfilter(rb->global_settings->dirfilter);
180 /* Change directory to the entry selected by the user */
181 rb->set_current_file(file_or_dir);
182 return true;
186 bool ends_with(char *string, char *suffix)
188 unsigned int str_len = rb->strlen(string);
189 unsigned int sfx_len = rb->strlen(suffix);
190 if (str_len < sfx_len)
191 return false;
192 return (rb->strncmp(string + str_len - sfx_len, suffix, sfx_len) == 0);
196 enum plugin_status plugin_start(const void* void_parameter)
198 #ifdef HAVE_LCD_BITMAP
199 int i;
200 #endif
201 bool leave_loop;
203 /* This is a viewer, so a parameter must have been specified */
204 if (void_parameter == NULL) {
205 rb->splash(HZ*2, "No parameter specified!");
206 return PLUGIN_ERROR;
208 link_filename = (char*)void_parameter;
209 user_file = (rb->strcmp(link_filename, SHORTCUTS_FILENAME) != 0);
211 allocate_memory(&memory_buf, &memory_bufsize);
213 if (!load_sc_file(&sc_file, link_filename, true,
214 memory_buf, memory_bufsize)) {
215 DEBUGF("Could not load %s\n", link_filename);
216 return PLUGIN_ERROR;
218 if (sc_file.entry_cnt==0) {
219 rb->splash(HZ*2, "No shortcuts in the file!");
220 return PLUGIN_OK;
221 } else if ((sc_file.entry_cnt==1) && user_file) {
222 /* if there's only one entry in the user .link file,
223 * go straight to it without displaying the menu
224 * thus allowing 'quick links' */
225 goto_entry(sc_file.entries[0].path);
226 return PLUGIN_OK;
229 #ifdef HAVE_LCD_BITMAP
230 FOR_NB_SCREENS(i)
231 rb->viewportmanager_theme_enable(i, true, NULL);
232 #endif
234 do {
235 /* Display a menu to choose between the entries */
236 leave_loop = list_sc();
237 } while (!leave_loop);
239 #ifdef HAVE_LCD_BITMAP
240 FOR_NB_SCREENS(i)
241 rb->viewportmanager_theme_undo(i, false);
242 #endif
244 return usb_connected ? PLUGIN_USB_CONNECTED : PLUGIN_OK;