Use GFile for presentation loading
authorThomas White <taw@bitwiz.me.uk>
Sun, 1 Apr 2018 09:08:38 +0000 (11:08 +0200)
committerThomas White <taw@bitwiz.me.uk>
Sun, 1 Apr 2018 09:08:38 +0000 (11:08 +0200)
data/colloquium.gresource.xml
meson.build
src/colloquium.c
src/imagestore.c
src/imagestore.h
src/narrative_window.c
src/presentation.c
src/presentation.h

index 99b27ff..15f244f 100644 (file)
@@ -1,8 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
-       <gresource prefix="/uk/me/bitwiz/Colloquium">
-               <file>sky.png</file>
-               <file>app-menu.ui</file>
-               <file>menu-bar.ui</file>
-       </gresource>
+  <gresource prefix="/uk/me/bitwiz/Colloquium">
+    <file>sky.png</file>
+    <file>app-menu.ui</file>
+    <file>menu-bar.ui</file>
+    <file>demo.sc</file>
+    <file>canvas.png</file>
+    <file>alpha_warning.svg</file>
+    <file>colloquium.svg</file>
+  </gresource>
 </gresources>
index 2433443..115a3f4 100644 (file)
@@ -44,14 +44,11 @@ executable('colloquium',
            dependencies : [gtkdep, mdep],
            install : true)
 
-# Data files, icon, desktop file etc
-install_data(['data/demo.sc', 'data/canvas.png',
-              'data/alpha_warning.svg'],
-             install_dir : datadir)
-
+# Desktop file
 install_data(['data/colloquium.desktop'],
              install_dir : get_option('datadir')+'/applications')
 
+# Icon
 install_data(['data/colloquium.svg'],
              install_dir : get_option('datadir')+'/icons/hicolor/scalable/apps')
 
index 63cacc8..26c45f3 100644 (file)
@@ -220,15 +220,14 @@ static void colloquium_open(GApplication  *papp, GFile **files, gint n_files,
 
        for ( i = 0; i<n_files; i++ ) {
                struct presentation *p;
-               char *uri = g_file_get_path(files[i]);
-               /* FIXME: Use GFile properly, hence support weird URIs etc */
                p = new_presentation(app->imagestore);
-               if ( load_presentation(p, uri) == 0 ) {
+               if ( load_presentation(p, files[i]) == 0 ) {
                        narrative_window_new(p, papp);
                } else {
+                       char *uri = g_file_get_uri(files[i]);
                        fprintf(stderr, "Failed to load '%s'\n", uri);
+                       g_free(uri);
                }
-               g_free(uri);
        }
 }
 
@@ -352,7 +351,7 @@ static void colloquium_startup(GApplication *papp)
        if ( !g_file_test(app->mydir, G_FILE_TEST_IS_DIR) ) {
 
                /* Folder not created yet */
-               GFile *file = g_file_new_for_path(DATADIR"/demo.sc");
+               GFile *file = g_file_new_for_uri("resource:///uk/me/bitwiz/Colloquium/demo.sc");
                g_application_open(G_APPLICATION(app), &file, 1, "");
                app->first_run = 1;
                g_object_unref(file);
index d060de8..1aed378 100644 (file)
@@ -31,6 +31,7 @@
 #include <libgen.h>
 #include <cairo.h>
 #include <glib.h>
+#include <gio/gio.h>
 #include <gdk/gdk.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
@@ -54,7 +55,8 @@ struct _imagestore
        int n_images;
        struct image_record *images;
        int max_images;
-       char *dname;
+       GFile *pparent;
+       GFile *iparent;
        const char *storename;
 };
 
@@ -81,8 +83,12 @@ ImageStore *imagestore_new(const char *storename)
        if ( is == NULL ) return NULL;
 
        is->images = NULL;
-       is->dname = NULL;
-       is->storename = storename;
+       is->pparent = NULL;
+       if ( storename != NULL ) {
+               is->iparent = g_file_new_for_uri(storename);
+       } else {
+               is->iparent = NULL;
+       }
        is->n_images = 0;
        is->max_images = 0;
        if ( alloc_images(is, 32) ) {
@@ -94,17 +100,12 @@ ImageStore *imagestore_new(const char *storename)
 }
 
 
-void imagestore_set_presentation_file(ImageStore *is, const char *filename)
+void imagestore_set_parent(ImageStore *is, GFile *parent)
 {
-       const char *dname;
-       char *cpy;
-
-       /* dirname() is yukky */
-       cpy = strdup(filename);
-       dname = dirname(cpy);
-       free(is->dname);
-       is->dname = strdup(dname);
-       free(cpy);
+       if ( is->pparent != NULL ) {
+               g_object_unref(is->pparent);
+       }
+       is->pparent = parent;
 }
 
 
@@ -121,6 +122,8 @@ void imagestore_destroy(ImageStore *is)
                        }
                }
        }
+       g_object_unref(is->pparent);
+       g_object_unref(is->iparent);
        free(is->images);
        free(is);
 }
@@ -154,39 +157,46 @@ static cairo_surface_t *pixbuf_to_surface(GdkPixbuf *t)
 }
 
 
-static char *try_all_locations(const char *filename,
-                               const char *dname, const char *iname)
+static int try_load(GFile *file, GdkPixbuf **pixbuf, gint w, gint h)
 {
-       if ( g_file_test(filename, G_FILE_TEST_EXISTS) ) {
-               return strdup(filename);
+       GFileInputStream *stream;
+       GError *error = NULL;
+
+       stream = g_file_read(file, NULL, &error);
+       if ( stream != NULL ) {
+               GError *pberr = NULL;
+               *pixbuf = gdk_pixbuf_new_from_stream_at_scale(G_INPUT_STREAM(stream),
+                                                             w, h, TRUE,
+                                                             NULL, &pberr);
+               g_object_unref(stream);
+               g_object_unref(file);
+               return 1;
        }
 
+       return 0;
+}
+
+
+static GdkPixbuf *load_image(const char *uri, GFile *pparent, GFile *iparent,
+                             gint w, gint h)
+{
+       GFile *file;
+       GdkPixbuf *pixbuf;
+
+       /* Literal pathname */
+       file = g_file_new_for_path(uri);
+       if ( try_load(file, &pixbuf, w, h) ) return pixbuf;
+
        /* Try the file prefixed with the directory the presentation is in */
-       if ( dname != NULL ) {
-               char *tmp;
-               tmp = malloc(strlen(filename) + strlen(dname) + 2);
-               if ( tmp == NULL ) return NULL;
-               strcpy(tmp, dname);
-               strcat(tmp, "/");
-               strcat(tmp, filename);
-               if ( g_file_test(tmp, G_FILE_TEST_EXISTS) ) {
-                       return tmp;
-               }
-               free(tmp);
+       if ( pparent != NULL ) {
+               file = g_file_get_child(pparent, uri);
+               if ( try_load(file, &pixbuf, w, h) ) return pixbuf;
        }
 
        /* Try prefixing with imagestore folder */
-       if ( iname != NULL ) {
-               char *tmp;
-               tmp = malloc(strlen(filename) + strlen(iname) + 2);
-               if ( tmp == NULL ) return NULL;
-               strcpy(tmp, iname);
-               strcat(tmp, "/");
-               strcat(tmp, filename);
-               if ( g_file_test(tmp, G_FILE_TEST_EXISTS) ) {
-                       return tmp;
-               }
-               free(tmp);
+       if ( iparent != NULL ) {
+               file = g_file_get_child(iparent, uri);
+               if ( try_load(file, &pixbuf, w, h) ) return pixbuf;
        }
 
        return NULL;
@@ -196,12 +206,14 @@ static char *try_all_locations(const char *filename,
 int imagestore_get_size(ImageStore *is, const char *filename,
                         int *w, int *h)
 {
-       char *fullfn;
+       GdkPixbuf *pixbuf;
+
+       pixbuf = load_image(filename, is->pparent, is->iparent, -1, -1);
+       if ( pixbuf == NULL ) return 1;
+
+       *w = gdk_pixbuf_get_width(pixbuf);
+       *h = gdk_pixbuf_get_height(pixbuf);
 
-       fullfn = try_all_locations(filename, is->dname, is->storename);
-       if ( gdk_pixbuf_get_file_info(fullfn, w, h) == NULL ) {
-               return 1;
-       }
        return 0;
 }
 
@@ -230,21 +242,15 @@ static int find_earliest(struct image_record *im)
 
 static cairo_surface_t *add_image_size(struct image_record *im,
                                        const char *filename,
-                                       const char *dname, const char *iname,
+                                       GFile *pparent, GFile *iparent,
                                        int w)
 {
-       char *fullfn;
        cairo_surface_t *surf;
        GdkPixbuf *t;
-       GError *error = NULL;
        int pos;
 
-       fullfn = try_all_locations(filename, dname, iname);
-       if ( fullfn == NULL ) return NULL;
-
-       t = gdk_pixbuf_new_from_file_at_size(fullfn, w, -1, &error);
-       free(fullfn);
-
+       t = load_image(filename, pparent, iparent, w, -1);
+       if ( t == NULL ) return NULL;
        surf = pixbuf_to_surface(t);
        g_object_unref(t);
 
@@ -280,8 +286,8 @@ static cairo_surface_t *add_new_image(ImageStore *is, const char *filename, int
        is->images[idx].filename = strdup(filename);
        is->images[idx].h_last_used = 0;
 
-       return add_image_size(&is->images[idx], filename, is->dname,
-                             is->storename, w);
+       return add_image_size(&is->images[idx], filename, is->pparent,
+                             is->iparent, w);
 }
 
 
@@ -324,7 +330,7 @@ cairo_surface_t *lookup_image(ImageStore *is, const char *filename, int w)
        }
 
        /* We don't have this size yet */
-       surf = add_image_size(&is->images[i], filename, is->dname,
-                             is->storename, w);
+       surf = add_image_size(&is->images[i], filename, is->pparent,
+                             is->iparent, w);
        return surf;
 }
index 0923da1..0d4df24 100644 (file)
 #endif
 
 #include <cairo.h>
-
+#include <gio/gio.h>
 
 typedef struct _imagestore ImageStore;
 
 extern ImageStore *imagestore_new(const char *storename);
-
 extern void imagestore_destroy(ImageStore *is);
-
-extern void imagestore_set_presentation_file(ImageStore *is,
-                                             const char *filename);
-
-extern cairo_surface_t *lookup_image(ImageStore *is, const char *filename, int w);
-
-extern int imagestore_get_size(ImageStore *is, const char *filename,
-                               int *w, int *h);
-
+extern void imagestore_set_parent(ImageStore *is, GFile *parent);
 extern void show_imagestore(ImageStore *is);
 
+extern cairo_surface_t *lookup_image(ImageStore *is, const char *uri, int w);
+extern int imagestore_get_size(ImageStore *is, const char *uri, int *w, int *h);
+
 #endif /* IMAGESTORE_H */
index 6bed315..42084b8 100644 (file)
@@ -86,15 +86,13 @@ static gint saveas_response_sig(GtkWidget *d, gint response,
 {
        if ( response == GTK_RESPONSE_ACCEPT ) {
 
-               char *filename;
-
-               filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+               GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(d));
 
-               if ( save_presentation(nw->p, filename) ) {
+               if ( save_presentation(nw->p, file) ) {
                        //show_error(sw, "Failed to save presentation");
                }
 
-               g_free(filename);
+               g_object_unref(file);
 
        }
 
@@ -128,12 +126,16 @@ static void saveas_sig(GSimpleAction *action, GVariant *parameter, gpointer vp)
 static void save_sig(GSimpleAction *action, GVariant *parameter, gpointer vp)
 {
        NarrativeWindow *nw = vp;
+       GFile *file;
 
        if ( nw->p->filename == NULL ) {
                return saveas_sig(NULL, NULL, nw);
        }
 
-       save_presentation(nw->p, nw->p->filename);
+       /* FIXME: Do this properly with GFile */
+       file = g_file_new_for_path(nw->p->filename);
+       save_presentation(nw->p, file);
+       g_object_unref(file);
 }
 
 
index 1c822c4..d338a1a 100644 (file)
@@ -125,22 +125,22 @@ struct presentation *new_presentation(const char *imagestore)
 }
 
 
-int save_presentation(struct presentation *p, const char *filename)
+int save_presentation(struct presentation *p, GFile *file)
 {
        FILE *fh;
-       char *old_fn;
+       char *filename;
+
+       /* FIXME: Do this properly using GFile */
+       filename = g_file_get_path(file);
+       printf("Saving to %s\n", filename);
 
        fh = fopen(filename, "w");
        if ( fh == NULL ) return 1;
 
        save_sc_block(fh, p->scblocks);
 
-       /* Slightly fiddly because someone might
-        * do save_presentation(p, p->filename) */
-       old_fn = p->filename;
-       imagestore_set_presentation_file(p->is, filename);
+       imagestore_set_parent(p->is, g_file_get_parent(file));
        p->filename = strdup(filename);
-       if ( old_fn != NULL ) free(old_fn);
 
        fclose(fh);
        p->saved = 1;
@@ -331,21 +331,20 @@ static void set_slide_size_from_stylesheet(struct presentation *p)
 }
 
 
-int load_presentation(struct presentation *p, const char *filename)
+int load_presentation(struct presentation *p, GFile *file)
 {
        int r = 0;
        char *everything;
 
        assert(p->completely_empty);
 
-       everything = load_everything(filename);
-       if ( everything == NULL ) {
-               fprintf(stderr, "Failed to load '%s'\n", filename);
+       if ( !g_file_load_contents(file, NULL, &everything, NULL, NULL, NULL) ) {
+               fprintf(stderr, "Failed to load '%s'\n", g_file_get_uri(file));
                return 1;
        }
 
        p->scblocks = sc_parse(everything);
-       free(everything);
+       g_free(everything);
 
        p->lang = pango_language_get_default();
 
@@ -361,8 +360,8 @@ int load_presentation(struct presentation *p, const char *filename)
        set_slide_size_from_stylesheet(p);
 
        assert(p->filename == NULL);
-       p->filename = strdup(filename);
-       imagestore_set_presentation_file(p->is, filename);
+       p->filename = g_file_get_uri(file);
+       imagestore_set_parent(p->is, g_file_get_parent(file));
 
        return 0;
 }
index d3cafa2..ccf696d 100644 (file)
@@ -77,8 +77,8 @@ extern SCBlock *last_slide(struct presentation *p);
 extern SCBlock *next_slide(struct presentation *p, SCBlock *sl);
 extern SCBlock *prev_slide(struct presentation *p, SCBlock *sl);
 
-extern int load_presentation(struct presentation *p, const char *filename);
-extern int save_presentation(struct presentation *p, const char *filename);
+extern int load_presentation(struct presentation *p, GFile *file);
+extern int save_presentation(struct presentation *p, GFile *file);
 
 #define UNUSED __attribute__((unused))