]> git.armaanb.net Git - chorizo.git/blobdiff - downloads.c
draft
[chorizo.git] / downloads.c
diff --git a/downloads.c b/downloads.c
new file mode 100644 (file)
index 0000000..c738863
--- /dev/null
@@ -0,0 +1,271 @@
+#include <webkit2/webkit2.h>
+
+#include "downloads.h"
+
+gboolean download_handle(WebKitDownload *, gchar *, gpointer);
+void download_click(GtkToolButton *, gpointer);
+void download_cancel(GtkMenuItem *, gpointer);
+gboolean downloadmanager_delete(GtkWidget *, gpointer);
+
+struct DownloadManager {
+       GtkWidget *scroll;
+       GtkWidget *toolbar;
+       GtkWidget *win;
+} dm;
+
+gint downloads = 0;
+
+struct DownloadItem {
+       GtkToolButton *tb;
+       WebKitDownload *download;
+};
+gboolean
+key_downloadmanager(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       if (event->type == GDK_KEY_PRESS) {
+               if (((GdkEventKey *)event)->state & GDK_CONTROL_MASK) {
+                       int key = ((GdkEventKey *)event)->keyval;
+                       if ((GDK_KEY_q == key) || (GDK_KEY_y == key)) {
+                               downloadmanager_delete(dm.win, NULL);
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
+void
+changed_download_progress(GObject *obj, GParamSpec *pspec, gpointer data)
+{
+       WebKitDownload *download = WEBKIT_DOWNLOAD(obj);
+       WebKitURIResponse *resp;
+       GtkToolItem *tb = GTK_TOOL_ITEM(data);
+       gdouble p, size_mb;
+       const gchar *uri;
+       gchar *t, *filename, *base;
+       p = webkit_download_get_estimated_progress(download);
+       p = p > 1 ? 1 : p;
+       p = p < 0 ? 0 : p;
+       p *= 100;
+       resp = webkit_download_get_response(download);
+       size_mb = webkit_uri_response_get_content_length(resp) / 1e6;
+
+       uri = webkit_download_get_destination(download);
+       filename = g_filename_from_uri(uri, NULL, NULL);
+       base = g_path_get_basename(filename);
+       t = g_strdup_printf("%s (%.0f%% of %.1f MB)", base, p, size_mb);
+       g_free(filename);
+       g_free(base);
+       gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), t);
+       g_free(t);
+}
+
+void
+download_finished(WebKitDownload *download, gpointer data)
+{
+       if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(data)),
+                  "dialog-error") != 0)
+               gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(data),
+                                             "emblem-downloads");
+       downloads--;
+}
+
+void
+download_start(WebKitWebView *web_view, WebKitDownload *download, gpointer data)
+{
+       g_signal_connect(G_OBJECT(download), "decide-destination",
+                        G_CALLBACK(download_handle), data);
+}
+gboolean
+download_handle(WebKitDownload *download, gchar *suggested_filename,
+               gpointer data)
+{
+       gchar *uri;
+       GtkToolItem *tb;
+
+       GtkWidget *chooser = gtk_file_chooser_dialog_new(
+               "Choose download location", GTK_WINDOW(dm.win),
+               GTK_FILE_CHOOSER_ACTION_SAVE, "Save file", GTK_RESPONSE_ACCEPT,
+               "Cancel", GTK_RESPONSE_CANCEL, NULL);
+       gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser),
+                                           (char *)data);
+       gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser),
+                                         suggested_filename);
+       gtk_file_chooser_set_do_overwrite_confirmation(
+               GTK_FILE_CHOOSER(chooser), TRUE);
+       gint res = gtk_dialog_run(GTK_DIALOG(chooser));
+       switch (res) {
+       case GTK_RESPONSE_ACCEPT:
+               uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser));
+               webkit_download_set_destination(
+                       download,
+                       gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(chooser)));
+               break;
+       case GTK_RESPONSE_CANCEL:
+               return FALSE;
+       default:
+               return FALSE;
+       }
+
+       gtk_widget_destroy(chooser);
+
+       remove(uri + 7);
+       tb = gtk_tool_button_new(NULL, NULL);
+       gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb), "network-receive");
+       gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb), uri);
+       gtk_toolbar_insert(GTK_TOOLBAR(dm.toolbar), tb, 0);
+       gtk_widget_show_all(dm.win);
+
+       g_signal_connect(G_OBJECT(download), "notify::estimated-progress",
+                        G_CALLBACK(changed_download_progress), tb);
+
+       downloads++;
+       g_signal_connect(G_OBJECT(download), "finished",
+                        G_CALLBACK(download_finished), tb);
+
+       g_object_ref(download);
+
+       struct DownloadItem *payload = malloc(sizeof(*payload));
+       payload->tb = (GtkToolButton *)tb;
+       payload->download = download;
+       g_signal_connect(G_OBJECT(tb), "clicked", G_CALLBACK(download_click),
+                        payload);
+       g_signal_connect(G_OBJECT(tb), "failed", G_CALLBACK(download_cancel),
+                        payload);
+       g_signal_connect(G_OBJECT(tb), "destroy_event", G_CALLBACK(g_free),
+                        payload);
+
+       //Propagate-- to whom it may concern.
+       return FALSE;
+}
+
+void
+download_cancel(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(payload->tb),
+                                     "dialog-error");
+       webkit_download_cancel(payload->download);
+}
+
+void
+download_remove(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       g_object_unref(payload->download);
+       gtk_widget_destroy(GTK_WIDGET(payload->tb));
+}
+
+void
+download_copy_url(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       WebKitURIRequest *req = webkit_download_get_request(payload->download);
+       const gchar *uri = webkit_uri_request_get_uri(req);
+       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), uri,
+                              strlen(uri));
+}
+
+void
+download_copy_path(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       const gchar *path = webkit_download_get_destination(payload->download);
+       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+                              path + 7, strlen(path) - 7);
+       //Offset by 7 to remove "file://"
+}
+
+void
+download_xdg_open(GtkMenuItem *tb, gpointer data)
+{
+       struct DownloadItem *payload = data;
+       const gchar *path = webkit_download_get_destination(payload->download);
+       char *cmd = malloc(strlen(path) + 9);
+       sprintf(cmd, "xdg-open %s", path);
+       system(cmd);
+}
+
+void
+download_click(GtkToolButton *tb, gpointer data)
+{
+       GtkWidget *pmenu = gtk_menu_new();
+       GtkWidget *option;
+       if (strcmp(gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(tb)),
+                  "network-receive") == 0) {
+               option = gtk_menu_item_new_with_label("Cancel download");
+               g_signal_connect(G_OBJECT(option), "activate",
+                                G_CALLBACK(download_cancel), data);
+               gtk_widget_show(option);
+               gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+       } else {
+               option = gtk_menu_item_new_with_label("Remove download");
+               g_signal_connect(G_OBJECT(option), "activate",
+                                G_CALLBACK(download_remove), data);
+               gtk_widget_show(option);
+               gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+
+               option =
+                       gtk_menu_item_new_with_label("Open file with xdg-open");
+               gtk_widget_show(option);
+               gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+               g_signal_connect(G_OBJECT(option), "activate",
+                                G_CALLBACK(download_xdg_open), data);
+       }
+
+       option = gtk_menu_item_new_with_label("Copy download URL");
+       gtk_widget_show(option);
+       gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+       g_signal_connect(G_OBJECT(option), "activate",
+                        G_CALLBACK(download_copy_url), data);
+
+       option = gtk_menu_item_new_with_label("Copy local path");
+       gtk_widget_show(option);
+       gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), option);
+       g_signal_connect(G_OBJECT(option), "activate",
+                        G_CALLBACK(download_copy_path), data);
+
+       gtk_menu_popup_at_pointer(GTK_MENU(pmenu), NULL);
+}
+gboolean
+downloadmanager_delete(GtkWidget *obj, gpointer data)
+{
+       if (!quit_if_nothing_active())
+               gtk_widget_hide(dm.win);
+
+       return TRUE;
+}
+
+void
+downloadmanager_setup(void)
+{
+       dm.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_type_hint(GTK_WINDOW(dm.win),
+                                GDK_WINDOW_TYPE_HINT_DIALOG);
+       gtk_window_set_default_size(GTK_WINDOW(dm.win), 500, 250);
+       gtk_window_set_title(GTK_WINDOW(dm.win), "chorizo - Download Manager");
+       g_signal_connect(G_OBJECT(dm.win), "delete-event",
+                        G_CALLBACK(downloadmanager_delete), NULL);
+       g_signal_connect(G_OBJECT(dm.win), "key-press-event",
+                        G_CALLBACK(key_downloadmanager), NULL);
+
+       dm.toolbar = gtk_toolbar_new();
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(dm.toolbar),
+                                      GTK_ORIENTATION_VERTICAL);
+       gtk_toolbar_set_style(GTK_TOOLBAR(dm.toolbar), GTK_TOOLBAR_BOTH_HORIZ);
+       gtk_toolbar_set_show_arrow(GTK_TOOLBAR(dm.toolbar), FALSE);
+
+       dm.scroll = gtk_scrolled_window_new(NULL, NULL);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dm.scroll),
+                                      GTK_POLICY_AUTOMATIC,
+                                      GTK_POLICY_AUTOMATIC);
+       gtk_container_add(GTK_CONTAINER(dm.scroll), dm.toolbar);
+
+       gtk_container_add(GTK_CONTAINER(dm.win), dm.scroll);
+}
+
+void
+downloadmanager_show(void)
+{
+       gtk_widget_show_all(dm.win);
+}