1 #include <webkit2/webkit2.h>
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);
10 struct DownloadManager
22 WebKitDownload *download;
26 key_downloadmanager(GtkWidget *widget, GdkEvent *event, gpointer data)
28 if (event->type == GDK_KEY_PRESS) {
29 if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
30 int key = ((GdkEventKey *)event)->keyval;
31 if ((def_key("close_tab", GDK_KEY_q) == key) ||
32 (def_key("download_manager", GDK_KEY_y) == key)) {
33 downloadmanager_delete(dm.win, NULL);
43 changed_download_progress(GObject *obj, GParamSpec *pspec, gpointer data)
45 WebKitDownload *download = WEBKIT_DOWNLOAD(obj);
46 WebKitURIResponse *resp;
47 GtkToolItem *tb = GTK_TOOL_ITEM(data);
50 gchar *t, *filename, *base;
52 p = webkit_download_get_estimated_progress(download);
56 resp = webkit_download_get_response(download);
57 size_mb = webkit_uri_response_get_content_length(resp) / 1e6;
59 uri = webkit_download_get_destination(download);
60 filename = g_filename_from_uri(uri, NULL, NULL);
61 if (filename == NULL) {
62 /* This really should not happen because WebKit uses that URI to
63 * write to a file... */
64 fprintf(stderr, __NAME__": Could not construct file name from URI!\n");
65 t = g_strdup_printf("%s (%.0f%% of %.1f MB)",
66 webkit_uri_response_get_uri(resp), p, size_mb);
68 base = g_path_get_basename(filename);
69 t = g_strdup_printf("%s (%.0f%% of %.1f MB)", base, p, size_mb);
73 gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), t);
77 download_finished(WebKitDownload *download, gpointer data)
79 if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(data)),
81 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(data), "emblem-downloads");
86 download_start(WebKitWebView *web_view, WebKitDownload *download,
89 g_signal_connect(G_OBJECT(download), "decide-destination",
90 G_CALLBACK(download_handle), data);
94 download_handle(WebKitDownload *download, gchar *suggested_filename,
97 gchar *sug_clean, *path, *path2 = NULL, *uri;
102 sug_clean = g_strdup(suggested_filename);
103 for (i = 0; i < strlen(sug_clean); i++)
104 if (sug_clean[i] == G_DIR_SEPARATOR)
107 path = g_build_filename((char *)data, sug_clean, NULL);
108 path2 = g_strdup(path);
109 while (g_file_test(path2, G_FILE_TEST_EXISTS) && suffix < 1000) {
112 path2 = g_strdup_printf("%s.%d", path, suffix);
116 if (suffix == 1000) {
117 fprintf(stderr, __NAME__": Suffix reached limit for download.\n");
118 webkit_download_cancel(download);
120 uri = g_filename_to_uri(path2, NULL, NULL);
121 webkit_download_set_destination(download, uri);
124 tb = gtk_tool_button_new(NULL, NULL);
125 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb), "network-receive");
126 gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), sug_clean);
127 gtk_toolbar_insert(GTK_TOOLBAR(dm.toolbar), tb, 0);
128 gtk_widget_show_all(dm.win);
130 g_signal_connect(G_OBJECT(download), "notify::estimated-progress",
131 G_CALLBACK(changed_download_progress), tb);
134 g_signal_connect(G_OBJECT(download), "finished",
135 G_CALLBACK(download_finished), tb);
137 g_object_ref(download);
139 struct DownloadItem *payload = malloc(sizeof(*payload));
140 payload->tb = (GtkToolButton *)tb;
141 payload->download = download;
142 g_signal_connect(G_OBJECT(tb), "clicked",
143 G_CALLBACK(download_click),
145 g_signal_connect(G_OBJECT(tb), "failed", G_CALLBACK(download_cancel),
147 g_signal_connect(G_OBJECT(tb), "destroy_event", G_CALLBACK(g_free),
155 /* Propagate -- to whom it may concern. */
160 download_cancel(GtkMenuItem *tb, gpointer data)
162 struct DownloadItem *payload = data;
163 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(payload->tb), "dialog-error");
164 webkit_download_cancel(payload->download);
168 download_remove(GtkMenuItem *tb, gpointer data)
170 struct DownloadItem *payload = data;
171 g_object_unref(payload->download);
172 gtk_widget_destroy(GTK_WIDGET(payload->tb));
176 download_copy_url(GtkMenuItem *tb, gpointer data)
178 struct DownloadItem *payload = data;
179 WebKitURIRequest *req = webkit_download_get_request(payload->download);
180 const gchar *uri = webkit_uri_request_get_uri(req);
181 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri,
186 download_copy_path(GtkMenuItem *tb, gpointer data)
188 struct DownloadItem *payload = data;
189 const gchar *path = webkit_download_get_destination(payload->download);
190 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), path + 7,
191 strlen(path) - 7); // Offset by 7 to remove "file://"
195 download_click(GtkToolButton *tb, gpointer data)
197 GtkWidget *pmenu = gtk_menu_new();
200 if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(tb)),
201 "network-receive") == 0) {
202 option = gtk_menu_item_new_with_label("Cancel download");
203 g_signal_connect(G_OBJECT(option), "activate",
204 G_CALLBACK(download_cancel), data);
206 option = gtk_menu_item_new_with_label("Remove download");
207 g_signal_connect(G_OBJECT(option), "activate",
208 G_CALLBACK(download_remove), data);
210 gtk_widget_show(option);
211 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
213 option = gtk_menu_item_new_with_label("Copy download URL");
214 gtk_widget_show(option);
215 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
216 g_signal_connect(G_OBJECT(option), "activate",
217 G_CALLBACK(download_copy_url), data);
219 option = gtk_menu_item_new_with_label("Copy local path");
220 gtk_widget_show(option);
221 gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
222 g_signal_connect(G_OBJECT(option), "activate",
223 G_CALLBACK(download_copy_path), data);
225 gtk_menu_popup_at_pointer(GTK_MENU(pmenu), NULL);
229 downloadmanager_delete(GtkWidget *obj, gpointer data)
231 if (!quit_if_nothing_active())
232 gtk_widget_hide(dm.win);
238 downloadmanager_setup(void)
240 dm.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
241 gtk_window_set_type_hint(GTK_WINDOW(dm.win), GDK_WINDOW_TYPE_HINT_DIALOG);
242 gtk_window_set_default_size(GTK_WINDOW(dm.win), 500, 250);
243 gtk_window_set_title(GTK_WINDOW(dm.win), __NAME__" - Download Manager");
244 g_signal_connect(G_OBJECT(dm.win), "delete-event",
245 G_CALLBACK(downloadmanager_delete), NULL);
246 g_signal_connect(G_OBJECT(dm.win), "key-press-event",
247 G_CALLBACK(key_downloadmanager), NULL);
249 dm.toolbar = gtk_toolbar_new();
250 gtk_orientable_set_orientation(GTK_ORIENTABLE(dm.toolbar),
251 GTK_ORIENTATION_VERTICAL);
252 gtk_toolbar_set_style(GTK_TOOLBAR(dm.toolbar), GTK_TOOLBAR_BOTH_HORIZ);
253 gtk_toolbar_set_show_arrow(GTK_TOOLBAR(dm.toolbar), FALSE);
255 dm.scroll = gtk_scrolled_window_new(NULL, NULL);
256 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dm.scroll),
257 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
258 gtk_container_add(GTK_CONTAINER(dm.scroll), dm.toolbar);
260 gtk_container_add(GTK_CONTAINER(dm.win), dm.scroll);
264 downloadmanager_show(void)
266 gtk_widget_show_all(dm.win);