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