summaryrefslogtreecommitdiff
path: root/apps/plugins/shortcuts/shortcuts_view.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/shortcuts/shortcuts_view.c')
-rw-r--r--apps/plugins/shortcuts/shortcuts_view.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/apps/plugins/shortcuts/shortcuts_view.c b/apps/plugins/shortcuts/shortcuts_view.c
new file mode 100644
index 0000000000..3b28b4b34c
--- /dev/null
+++ b/apps/plugins/shortcuts/shortcuts_view.c
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Bryan Childs
11 * Copyright (c) 2007 Alexander Levin
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include "shortcuts.h"
22
23PLUGIN_HEADER
24
25enum sc_list_action_type
26{
27 SCLA_NONE,
28 SCLA_SELECT,
29 SCLA_DELETE,
30 SCLA_USB,
31};
32
33
34static char *link_filename;
35static bool user_file;
36static int gselected_item;
37static bool usb_connected = false;
38
39enum sc_list_action_type draw_sc_list(struct gui_synclist gui_sc);
40
41/* Will be passed sc_file* as data */
42char* build_sc_list(int selected_item, void *data, char *buffer);
43
44/* Returns true iff we should leave the main loop */
45bool list_sc(bool is_editable);
46
47bool goto_entry(char *file_or_dir);
48bool ends_with(char *str, char *suffix);
49
50
51enum sc_list_action_type draw_sc_list(struct gui_synclist gui_sc)
52{
53 int button;
54
55 rb->gui_synclist_draw(&gui_sc);
56
57 while (true) {
58 /* draw the statusbar, should be done often */
59 rb->gui_syncstatusbar_draw(rb->statusbars, true);
60 /* user input */
61 button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
62 if (rb->gui_synclist_do_button(&gui_sc, button,
63 LIST_WRAP_UNLESS_HELD)) {
64 /* automatic handling of user input.
65 * _UNLESS_HELD can be _ON or _OFF also
66 * selection changed, so redraw */
67 continue;
68 }
69 switch (button) { /* process the user input */
70 case ACTION_STD_OK:
71 gselected_item = rb->gui_synclist_get_sel_pos(&gui_sc);
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 gselected_item = rb->gui_synclist_get_sel_pos(&gui_sc);
80 return SCLA_DELETE;
81 }
82 break;
83 case ACTION_STD_CANCEL:
84 return SCLA_NONE;
85 default:
86 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) {
87 return SCLA_USB;
88 }
89 }
90 }
91}
92
93
94char* build_sc_list(int selected_item, void *data, char *buffer)
95{
96 char text_buffer[MAX_PATH];
97 sc_file_t *file = (sc_file_t*)data;
98
99 if (!is_valid_index(file, selected_item)) {
100 return NULL;
101 }
102 sc_entry_t *entry = file->entries + selected_item;
103 rb->snprintf(text_buffer, sizeof(text_buffer), "%s", entry->disp);
104 rb->strcpy(buffer, text_buffer);
105 return buffer;
106}
107
108
109bool list_sc(bool is_editable)
110{
111 int selected_item = 0;
112 char selected_dir[MAX_PATH];
113 enum sc_list_action_type action = SCLA_NONE;
114 struct gui_synclist gui_sc;
115
116 rb->memset(selected_dir, 0, sizeof(selected_dir));
117
118 /* Setup the GUI list object, draw it to the screen,
119 * and then handle the user input to it */
120 rb->gui_synclist_init(&gui_sc, &build_sc_list, &sc_file, false, 1);
121 rb->gui_synclist_set_title(&gui_sc,
122 (is_editable?"Shortcuts (editable)":"Shortcuts (sealed)"), NOICON);
123 rb->gui_synclist_set_nb_items(&gui_sc, sc_file.entry_cnt);
124 rb->gui_synclist_limit_scroll(&gui_sc, false);
125 rb->gui_synclist_select_item(&gui_sc, 0);
126
127 /* Draw the prepared widget to the LCD now */
128 action = draw_sc_list(gui_sc);
129 if (action == SCLA_USB) {
130 usb_connected = true;
131 return true;
132 }
133
134 /* which item do we action? */
135 selected_item = gselected_item;
136
137 if (!is_valid_index(&sc_file, selected_item)) {
138 /* This should never happen */
139 rb->splash(HZ*2, "Bad entry selected!");
140 return true;
141 }
142
143 /* perform the following actions if the user "selected"
144 * the item in the list (i.e. they want to go there
145 * in the filebrowser tree */
146 switch(action) {
147 case SCLA_SELECT:
148 return goto_entry(sc_file.entries[selected_item].path);
149 case SCLA_DELETE:
150 rb->splash(HZ, "Deleting %s", sc_file.entries[selected_item].disp);
151 remove_entry(&sc_file, selected_item);
152 dump_sc_file(&sc_file, link_filename);
153 return (sc_file.entry_cnt == 0);
154 default:
155 return true;
156 }
157}
158
159
160bool goto_entry(char *file_or_dir)
161{
162 DEBUGF("Trying to go to '%s'...\n", file_or_dir);
163
164 bool is_dir = ends_with(file_or_dir, PATH_SEPARATOR);
165 bool exists;
166 char *what;
167 if (is_dir) {
168 what = "Directory";
169 exists = dir_exists(file_or_dir);
170 } else {
171 what = "File";
172 exists = file_exists(file_or_dir);
173 }
174
175 if (!exists) {
176 rb->splash(HZ*2, "%s %s no longer exists on disk", what, file_or_dir);
177 return false;
178 }
179 /* Set the browsers dirfilter to the global setting
180 * This is required in case the plugin was launched
181 * from the plugins browser, in which case the
182 * dirfilter is set to only display .rock files */
183 rb->set_dirfilter(rb->global_settings->dirfilter);
184
185 /* Change directory to the entry selected by the user */
186 rb->set_current_file(file_or_dir);
187 return true;
188}
189
190
191bool ends_with(char *string, char *suffix)
192{
193 unsigned int str_len = rb->strlen(string);
194 unsigned int sfx_len = rb->strlen(suffix);
195 if (str_len < sfx_len)
196 return false;
197 return (rb->strncmp(string + str_len - sfx_len, suffix, sfx_len) == 0);
198}
199
200
201enum plugin_status plugin_start(struct plugin_api* api, void* void_parameter)
202{
203 rb = api;
204 bool leave_loop;
205
206 /* This is a viewer, so a parameter must have been specified */
207 if (void_parameter == NULL) {
208 rb->splash(HZ*2, "No parameter specified!");
209 return PLUGIN_ERROR;
210 }
211 link_filename = (char*)void_parameter;
212 user_file = (rb->strcmp(link_filename, SHORTCUTS_FILENAME) != 0);
213
214 allocate_memory(&memory_buf, &memory_bufsize);
215
216 if (!load_sc_file(&sc_file, link_filename, true,
217 memory_buf, memory_bufsize)) {
218 DEBUGF("Could not load %s\n", link_filename);
219 return PLUGIN_ERROR;
220 }
221 if (sc_file.entry_cnt==0) {
222 rb->splash(HZ*2, "No shortcuts in the file!");
223 return PLUGIN_OK;
224 } else if ((sc_file.entry_cnt==1) && user_file) {
225 /* if there's only one entry in the user .link file,
226 * go straight to it without displaying the menu
227 * thus allowing 'quick links' */
228 goto_entry(sc_file.entries[0].path);
229 return PLUGIN_OK;
230 }
231
232 do {
233 /* Display a menu to choose between the entries */
234 leave_loop = list_sc(!user_file);
235 } while (!leave_loop);
236
237 return usb_connected ? PLUGIN_USB_CONNECTED : PLUGIN_OK;
238}