Fix #283: add support for loading remote URLs
authorColin Clark <colin.clark@cclark.uk>
Wed, 10 Jul 2019 18:23:36 +0000 (19:23 +0100)
committerColin Clark <colin.clark@cclark.uk>
Wed, 10 Jul 2019 18:23:36 +0000 (19:23 +0100)
https://github.com/BestImageViewer/geeqie/issues/283

Type in or drag-drop a URL to the Path Entry field.
Remote command --file:<file> also recognizes URLs

doc/docbook/GuideMainWindowFolderPane.xml
doc/docbook/GuideReferenceCommandLine.xml
src/layout.c
src/main.c
src/remote.c
src/ui_fileops.c
src/ui_fileops.h

index c30245b..239179c 100644 (file)
       </para>\r
     </note>\r
     <para>Next to the path entry is a button with a down arrow, clicking this will display a drop down list containing the most recent locations viewed. The list is ordered such that the most recent location is at the top. Selecting a location from the drop down list will change the window to display the location.</para>\r
+    <para>An Internet URL may be typed or drag-and-dropped into this field. The file will be downloaded to a temporary file and displayed.</para>\r
     <para />\r
   </section>\r
   <section id="Folderlist">\r
index 7c23592..a5ac3a2 100644 (file)
@@ -8,6 +8,7 @@
       <footnote id='ref1'>The name of a collection, with or without either path or extension (.gqv) may be used. If a path is not used and there is a name conflict with a file or folder, that will take precedence.</footnote>\r
     </programlisting>\r
   </para>\r
+  <para>You may also use a URL as a filename. The file will be downloaded to a temporary file and displayed.</para>\r
   <para>These are the command line options available to Geeqie:</para>\r
   <table frame="all">\r
     <tgroup cols="3" rowsep="1" colsep="1">\r
index fe9a31e..2b92d30 100644 (file)
@@ -262,9 +262,13 @@ static void layout_path_entry_cb(const gchar *path, gpointer data)
        gchar *buf;
 
        buf = g_strdup(path);
-       parse_out_relatives(buf);
 
-       layout_set_path(lw, buf);
+       if (!download_web_file(buf, lw))
+               {
+               parse_out_relatives(buf);
+
+               layout_set_path(lw, buf);
+               }
 
        g_free(buf);
 }
index 03aef4c..cb1652c 100644 (file)
@@ -259,6 +259,9 @@ static void parse_command_line(gint argc, gchar *argv[])
                                parse_command_line_process_file(cmd_all, &command_line->path, &command_line->file,
                                                                &list, &command_line->collection_list, &first_dir);
                                }
+                       else if (download_web_file(cmd_line, NULL))
+                               {
+                               }
                        else if (is_collection(cmd_line))
                                {
                                gchar *path = NULL;
index b543544..aab8043 100644 (file)
@@ -649,33 +649,37 @@ static void gr_quit(const gchar *text, GIOChannel *channel, gpointer data)
 static void gr_file_load_no_raise(const gchar *text, GIOChannel *channel, gpointer data)
 {
        gchar *filename;
-       gchar *tilde_filename = expand_tilde(text);
-
-       filename = set_pwd(tilde_filename);
+       gchar *tilde_filename;
 
-       if (isfile(filename))
+       if (!download_web_file(text, NULL))
                {
-               if (file_extension_match(filename, GQ_COLLECTION_EXT))
+               tilde_filename = expand_tilde(text);
+               filename = set_pwd(tilde_filename);
+
+               if (isfile(filename))
                        {
-                       collection_window_new(filename);
+                       if (file_extension_match(filename, GQ_COLLECTION_EXT))
+                               {
+                               collection_window_new(filename);
+                               }
+                       else
+                               {
+                               layout_set_path(lw_id, filename);
+                               }
                        }
-               else
+               else if (isdir(filename))
                        {
                        layout_set_path(lw_id, filename);
                        }
-               }
-       else if (isdir(filename))
-               {
-               layout_set_path(lw_id, filename);
-               }
-       else
-               {
-               log_printf("remote sent filename that does not exist:\"%s\"\n", filename);
-               layout_set_path(lw_id, homedir());
-               }
+               else
+                       {
+                       log_printf("remote sent filename that does not exist:\"%s\"\n", filename);
+                       layout_set_path(lw_id, homedir());
+                       }
 
-       g_free(filename);
-       g_free(tilde_filename);
+               g_free(filename);
+               g_free(tilde_filename);
+               }
 }
 
 static void gr_file_load(const gchar *text, GIOChannel *channel, gpointer data)
index 3eea7df..12071fc 100644 (file)
@@ -42,6 +42,8 @@
 #include "md5-util.h"
 
 #include "filefilter.h"
+#include "layout.h"
+#include "utilops.h"
 #include "secure_save.h"
 
 /*
@@ -988,5 +990,122 @@ gchar *md5_text_from_file_utf8(const gchar *path, const gchar *error_text)
        return md5_digest_to_text(digest);
 }
 
+/* Download web file
+ */
+typedef struct _WebData WebData;
+struct _WebData
+{
+       GenericDialog *gd;
+       GCancellable *cancellable;
+       LayoutWindow *lw;
+
+       GtkWidget *progress;
+       GFile *tmp_g_file;
+       GFile *web_file;
+};
+
+static void web_file_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
+{
+       GError *error = NULL;
+       WebData* web = data;
+       gchar *tmp_filename;
+
+       if (!g_cancellable_is_cancelled(web->cancellable))
+               {
+               generic_dialog_close(web->gd);
+               }
+
+       if (g_file_copy_finish(G_FILE(source_object), res, &error))
+               {
+               tmp_filename = g_file_get_parse_name(web->tmp_g_file);
+               g_free(tmp_filename);
+               layout_set_path(web->lw, g_file_get_path(web->tmp_g_file));
+               }
+       else
+               {
+               file_util_warning_dialog(_("Web file download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
+               }
+
+       g_object_unref(web->tmp_g_file);
+       web->tmp_g_file = NULL;
+       g_object_unref(web->cancellable);
+       g_object_unref(web->web_file);
+}
+
+static void web_file_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
+{
+       WebData* web = data;
+
+       if (!g_cancellable_is_cancelled(web->cancellable))
+               {
+               gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(web->progress), (gdouble)current_num_bytes / total_num_bytes);
+               }
+}
 
+static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
+{
+       WebData* web = data;
+       GError *error = NULL;
+
+       g_cancellable_cancel(web->cancellable);
+}
+
+gboolean download_web_file(const gchar *text, gpointer data)
+{
+       gchar *scheme;
+       LayoutWindow *lw = data;
+       gchar *tmp_dir;
+       GError *error = NULL;
+       WebData *web;
+       gchar *base;
+       gboolean ret;
+       gchar *message;
+
+       scheme = g_uri_parse_scheme(text);
+       if (g_strcmp0("http", scheme) == 0 || g_strcmp0("https", scheme) == 0)
+               {
+               tmp_dir = g_dir_make_tmp("geeqie_XXXXXX", &error);
+               if (error)
+                       {
+                       log_printf("Error: could not create temporary file n%s\n", error->message);
+                       g_error_free(error);
+                       error = NULL;
+                       ret = TRUE;
+                       }
+               else
+                       {
+                       web = g_new0(WebData,1);
+                       web->lw = lw;
+
+                       web->web_file = g_file_new_for_uri(text);
+
+                       base = g_strdup(g_file_get_basename(web->web_file));
+                       web->tmp_g_file = g_file_new_for_path(g_build_filename(tmp_dir, base, NULL));
+
+                       web->gd = generic_dialog_new(_("Download web file"), "download_web_file", NULL, TRUE, timezone_cancel_button_cb, web);
+
+                       message = g_strconcat(_("Downloading "), base, NULL);
+                       generic_dialog_add_message(web->gd, GTK_STOCK_DIALOG_INFO, message, NULL, FALSE);
+
+                       web->progress = gtk_progress_bar_new();
+                       gtk_box_pack_start(GTK_BOX(web->gd->vbox), web->progress, FALSE, FALSE, 0);
+                       gtk_widget_show(web->progress);
+
+                       gtk_widget_show(web->gd->dialog);
+                       web->cancellable = g_cancellable_new();
+                       g_file_copy_async(web->web_file, web->tmp_g_file, G_FILE_COPY_OVERWRITE, G_PRIORITY_LOW, web->cancellable, web_file_progress_cb, web, web_file_async_ready_cb, web);
+
+                       g_free(base);
+                       g_free(message);
+                       ret = TRUE;
+                       }
+               }
+       else
+               {
+               ret = FALSE;
+               }
+
+       g_free(scheme);
+       return ret;
+}
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index 3b408df..c2acbf9 100644 (file)
@@ -109,5 +109,6 @@ gboolean recursive_mkdir_if_not_exists(const gchar *path, mode_t mode);
 gchar *md5_text_from_file_utf8(const gchar *path, const gchar *error_text);
 gboolean md5_get_digest_from_file_utf8(const gchar *path, guchar digest[16]);
 
+gboolean download_web_file(const gchar *text, gpointer data);
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */