]> git.armaanb.net Git - chorizo.git/blob - downloads.c
draft 8
[chorizo.git] / downloads.c
1 #include <webkit2/webkit2.h>
2
3 #include "chorizo.h"
4
5 gboolean download_handle(WebKitDownload *, gchar *, gpointer);
6 void download_click(GtkToolButton *, gpointer);
7 void download_cancel(GtkMenuItem *, gpointer);
8 gboolean downloadmanager_delete(GtkWidget *, gpointer);
9
10 struct DownloadManager {
11         GtkWidget *scroll;
12         GtkWidget *toolbar;
13         GtkWidget *win;
14 } dm;
15
16 gint downloads = 0;
17
18 gboolean
19 key_downloadmanager(GtkWidget *widget, GdkEvent *event, gpointer data)
20 {
21         if (event->type == GDK_KEY_PRESS) {
22                 if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
23                         int key = ((GdkEventKey *)event)->keyval;
24                         if ((GDK_KEY_q == key) || (GDK_KEY_y == key)) {
25                                 downloadmanager_delete(dm.win, NULL);
26                                 return TRUE;
27                         }
28                 }
29         }
30         return FALSE;
31 }
32
33 void
34 changed_download_progress(GObject *obj, GParamSpec *pspec, gpointer data)
35 {
36         WebKitDownload *download = WEBKIT_DOWNLOAD(obj);
37         WebKitURIResponse *resp;
38         GtkToolItem *tb = GTK_TOOL_ITEM(data);
39         gdouble p, size_mb;
40         const gchar *uri;
41         gchar *t, *filename, *base;
42         p = webkit_download_get_estimated_progress(download);
43         p = p > 1 ? 1 : p;
44         p = p < 0 ? 0 : p;
45         p *= 100;
46         resp = webkit_download_get_response(download);
47         size_mb = webkit_uri_response_get_content_length(resp) / 1e6;
48
49         uri = webkit_download_get_destination(download);
50         filename = g_filename_from_uri(uri, NULL, NULL);
51         base = g_path_get_basename(filename);
52         t = g_strdup_printf("%s (%.0f%% of %.1f MB)", base, p, size_mb);
53         g_free(filename);
54         g_free(base);
55         gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), t);
56         g_free(t);
57 }
58
59 void
60 download_finished(WebKitDownload *download, gpointer data)
61 {
62         if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(data)),
63                    "dialog-error") != 0)
64                 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(data),
65                                               "emblem-downloads");
66         downloads--;
67 }
68
69 void
70 download_start(WebKitWebView *web_view, WebKitDownload *download, gpointer data)
71 {
72         g_signal_connect(G_OBJECT(download), "decide-destination",
73                          G_CALLBACK(download_handle), data);
74 }
75 gboolean
76 download_handle(WebKitDownload *download, gchar *suggested_filename,
77                 gpointer data)
78 {
79         gchar *uri;
80         GtkToolItem *tb;
81
82         GtkWidget *chooser = gtk_file_chooser_dialog_new(
83                 "Save File", GTK_WINDOW(dm.win), GTK_FILE_CHOOSER_ACTION_SAVE,
84                 "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT,
85                 NULL);
86         gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser),
87                                             (char *)data);
88         gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser),
89                                           suggested_filename);
90         gtk_file_chooser_set_do_overwrite_confirmation(
91                 GTK_FILE_CHOOSER(chooser), TRUE);
92         gint res = gtk_dialog_run(GTK_DIALOG(chooser));
93
94         if (res != GTK_RESPONSE_ACCEPT) {
95                 gtk_widget_destroy(chooser);
96         } else {
97                 uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser));
98                 webkit_download_set_destination(download, uri);
99
100                 remove(uri + 7); // Remove before overwrite
101
102                 gtk_widget_destroy(chooser);
103
104                 tb = gtk_tool_button_new(NULL, NULL);
105                 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb),
106                                               "network-receive");
107                 gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), uri);
108                 gtk_toolbar_insert(GTK_TOOLBAR(dm.toolbar), tb, 0);
109                 gtk_widget_show_all(dm.win);
110
111                 g_signal_connect(G_OBJECT(download),
112                                  "notify::estimated-progress",
113                                  G_CALLBACK(changed_download_progress), tb);
114
115                 downloads++;
116                 g_signal_connect(G_OBJECT(download), "finished",
117                                  G_CALLBACK(download_finished), tb);
118
119                 g_object_ref(download);
120
121                 struct DownloadItem *payload = malloc(sizeof(*payload));
122                 payload->tb = (GtkToolButton *)tb;
123                 payload->download = download;
124                 g_signal_connect(G_OBJECT(tb), "clicked",
125                                  G_CALLBACK(download_click), payload);
126                 g_signal_connect(G_OBJECT(payload->download), "failed",
127                                  G_CALLBACK(download_cancel), payload);
128                 g_signal_connect(G_OBJECT(tb), "destroy_event",
129                                  G_CALLBACK(g_free), payload);
130         }
131         return FALSE;
132 }
133
134 void
135 download_cancel(GtkMenuItem *tb, gpointer data)
136 {
137         struct DownloadItem *payload = data;
138         gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(payload->tb),
139                                       "dialog-error");
140         webkit_download_cancel(payload->download);
141 }
142
143 const char *
144 download_get_path(struct DownloadItem *payload)
145 {
146         const char *path = webkit_download_get_destination(payload->download);
147         return path += 7;
148 }
149
150 void
151 download_hide(GtkMenuItem *tb, gpointer data)
152 {
153         struct DownloadItem *payload = data;
154         g_object_unref(payload->download);
155         gtk_widget_destroy(GTK_WIDGET(payload->tb));
156 }
157
158 void
159 download_delete(GtkMenuItem *tb, gpointer data)
160 {
161         remove(download_get_path((struct DownloadItem *)data));
162         download_hide(tb, data);
163 }
164
165 void
166 download_copy_url(GtkMenuItem *tb, gpointer data)
167 {
168         struct DownloadItem *payload = data;
169         WebKitURIRequest *req = webkit_download_get_request(payload->download);
170         const gchar *uri = webkit_uri_request_get_uri(req);
171         gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri,
172                                strlen(uri));
173 }
174
175 void
176 download_copy_path(GtkMenuItem *tb, gpointer data)
177 {
178         const char *path = download_get_path((struct DownloadItem *)data);
179         gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), path,
180                                strlen(path));
181 }
182
183 void
184 download_xdg_open(GtkMenuItem *tb, gpointer data)
185 {
186         struct DownloadItem *payload = data;
187         const gchar *path = webkit_download_get_destination(payload->download);
188         char *cmd = malloc(strlen(path) + 9);
189         sprintf(cmd, "xdg-open %s", path);
190         system(cmd);
191 }
192
193 void
194 download_click(GtkToolButton *tb, gpointer data)
195 {
196         GtkWidget *pmenu = gtk_menu_new();
197         GtkWidget *option;
198         if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(tb)),
199                    "network-receive") == 0) {
200                 option = gtk_menu_item_new_with_label("Cancel download");
201                 g_signal_connect(G_OBJECT(option), "activate",
202                                  G_CALLBACK(download_cancel), data);
203                 gtk_widget_show(option);
204                 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
205         } else {
206                 option =
207                         gtk_menu_item_new_with_label("Hide download from list");
208                 g_signal_connect(G_OBJECT(option), "activate",
209                                  G_CALLBACK(download_hide), data);
210                 gtk_widget_show(option);
211                 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
212
213                 option = gtk_menu_item_new_with_label("Delete downloaded file");
214                 g_signal_connect(G_OBJECT(option), "activate",
215                                  G_CALLBACK(download_delete), data);
216                 gtk_widget_show(option);
217                 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
218
219                 option =
220                         gtk_menu_item_new_with_label("Open file with xdg-open");
221                 gtk_widget_show(option);
222                 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
223                 g_signal_connect(G_OBJECT(option), "activate",
224                                  G_CALLBACK(download_xdg_open), data);
225         }
226
227         option = gtk_menu_item_new_with_label("Copy download URL");
228         gtk_widget_show(option);
229         gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
230         g_signal_connect(G_OBJECT(option), "activate",
231                          G_CALLBACK(download_copy_url), data);
232
233         option = gtk_menu_item_new_with_label("Copy local path");
234         gtk_widget_show(option);
235         gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
236         g_signal_connect(G_OBJECT(option), "activate",
237                          G_CALLBACK(download_copy_path), data);
238
239         gtk_menu_popup_at_pointer(GTK_MENU(pmenu), NULL);
240 }
241 gboolean
242 downloadmanager_delete(GtkWidget *obj, gpointer data)
243 {
244         if (!quit_if_nothing_active()) gtk_widget_hide(dm.win);
245
246         return TRUE;
247 }
248
249 void
250 downloadmanager_setup(void)
251 {
252         dm.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
253         gtk_window_set_type_hint(GTK_WINDOW(dm.win),
254                                  GDK_WINDOW_TYPE_HINT_DIALOG);
255         gtk_window_set_default_size(GTK_WINDOW(dm.win), 500, 250);
256         gtk_window_set_title(GTK_WINDOW(dm.win), "chorizo - Download Manager");
257         g_signal_connect(G_OBJECT(dm.win), "delete-event",
258                          G_CALLBACK(downloadmanager_delete), NULL);
259         g_signal_connect(G_OBJECT(dm.win), "key-press-event",
260                          G_CALLBACK(key_downloadmanager), NULL);
261
262         dm.toolbar = gtk_toolbar_new();
263         gtk_orientable_set_orientation(GTK_ORIENTABLE(dm.toolbar),
264                                        GTK_ORIENTATION_VERTICAL);
265         gtk_toolbar_set_style(GTK_TOOLBAR(dm.toolbar), GTK_TOOLBAR_BOTH_HORIZ);
266         gtk_toolbar_set_show_arrow(GTK_TOOLBAR(dm.toolbar), FALSE);
267
268         dm.scroll = gtk_scrolled_window_new(NULL, NULL);
269         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dm.scroll),
270                                        GTK_POLICY_AUTOMATIC,
271                                        GTK_POLICY_AUTOMATIC);
272         gtk_container_add(GTK_CONTAINER(dm.scroll), dm.toolbar);
273
274         gtk_container_add(GTK_CONTAINER(dm.win), dm.scroll);
275 }
276
277 void
278 downloadmanager_show(void)
279 {
280         gtk_widget_show_all(dm.win);
281 }