[gnome-robots] Rewrite GamesFileList in Vala



commit a6ff58dd1b2081f2d1283329f94ba68ae2fd44e7
Author: Andrey Kutejko <andy128k gmail com>
Date:   Sun Aug 23 15:51:30 2020 +0200

    Rewrite GamesFileList in Vala

 src/file-list.vala         | 237 +++++++++++++++++++++++++++
 src/find-file.c            |   2 +-
 src/games-file-list.c      | 394 ---------------------------------------------
 src/games-file-list.h      |  65 --------
 src/image-suffix-list.vala |  16 +-
 src/meson.build            |   4 +-
 src/properties.c           |  26 +--
 7 files changed, 266 insertions(+), 478 deletions(-)
---
diff --git a/src/file-list.vala b/src/file-list.vala
new file mode 100644
index 0000000..cc8d682
--- /dev/null
+++ b/src/file-list.vala
@@ -0,0 +1,237 @@
+/* games-file-list.vala:
+   Copyright 2003 Callum McKenzie
+
+   This library is free software; you can redistribute it and'or modify
+   it under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* Authors:   Callum McKenzie <callum physics otago ac nz> */
+
+using Gtk;
+using Gee;
+
+public class GamesFileList {
+
+    [Flags]
+    public enum Flags {
+        REMOVE_EXTENSION = 1 << 0,
+        REPLACE_UNDERSCORES = 1 << 1,
+    }
+
+    private TreeSet<string> files;
+
+    /**
+     * @glob: A pattern to match files against. See g_pattern_spec_new () for
+     * details.
+     * @varargs: A NULL terminated list of strings containing directory names to
+     * be searched for files.
+     *
+     * This function takes a glob and a NULL terminated list of directories
+     * and constructs a list of all files in the directories that match the glob.
+     * Only regular files are returned.
+     *
+     * Return value: A pointer to a new FileList containing files
+     * matching the glob in the path.
+     **/
+    public GamesFileList (string glob, ...) {
+        var paths = va_list();
+        files = new_internal (glob, paths);
+    }
+
+    /**
+     * @path1: A NULL-terminated list of strings containing directories to be
+     * searched.
+     *
+     * A convenience function which constructs a list of filenames which
+     * are images that can be loaded via gdk-pixbuf. Whether a file is an
+     * image or not is determined by its extension. The list of possible
+     * extensions is determined by querying the gdk-pixbuf library the
+     * first time this function is called.
+     *
+     * Return value: A new FileList containing the list of image files.
+     **/
+    public GamesFileList.images (string path1, ...) {
+        files = new TreeSet<string> ();
+
+        find_images (path1, files);
+
+        var paths = va_list();
+        for (string? pathentry = paths.arg<string?> (); pathentry != null ; pathentry = paths.arg<string?> 
()) {
+            find_images (pathentry, files);
+        }
+    }
+
+    /* Transform the list of files to be only the basenames. */
+    public void transform_basename () {
+        var new_files = new TreeSet<string> ();
+        foreach (var file in files) {
+            new_files.add (Path.get_basename (file));
+        }
+        files = new_files;
+    }
+
+    /**
+     * Get the number of elements in the file list.
+     **/
+    public uint length () {
+        return files.size;
+    }
+
+    /**
+     * @function: (scope call): The function to call on each item. It gets called with two
+     * arguments: the file name and the pointer supplied to this function in
+     * the userdata argument.
+     * @userdata: (closure): An arbitrary pointer that gets passed as the second argument
+     * to each call of function.
+     *
+     * Apply a function to each file name in the list.
+     **/
+    //public void @foreach (Func<string> func) {
+    //    files.@foreach (func);
+    //}
+
+    /**
+     * @function: (scope call): The function to call on each item. It gets called with two
+     * arguments: the file name and the pointer supplied to this function in
+     * the userdata argument.
+     * @userdata: (closure): An arbitrary pointer that gets passed as the second argument
+     * to each call of function.
+     *
+     * Find a file name by iterating through a list until the given function
+     * returns 0.
+     *
+     * Return value: A newly allocated string containing a copy of the file name,
+     * or NULL if no file name was found.
+     **/
+    public string? find (CompareFunc<string> function, string val) {
+        return files.first_match ((file) => function (file, val) == 0);
+    }
+
+    /**
+     * @n: The 0-based index into the list.
+     *
+     * Obtain the (n+1)th file name from the list.
+     **/
+    //public string get_nth (int n) {
+    //    return files[n];
+    //}
+
+    public TreeModel create_model (Flags flags) {
+        var model = new Gtk.ListStore (2, Type.STRING, Type.STRING);
+        foreach (var item in files) {
+            var visible = item;
+
+            /* These are a bit hackish, but we don't yet have a good regexp
+             * library in glib. There are probably some ways these could
+             * seriously mangle unicode strings. */
+            if (Flags.REMOVE_EXTENSION in flags) {
+                var s = visible.last_index_of (".");
+                if (s >= 0)
+                    visible = visible.substring (0, s);
+            }
+            if (Flags.REPLACE_UNDERSCORES in flags) {
+                visible = visible.replace ("_", " ");
+            }
+
+            TreeIter iter;
+            model.append (out iter);
+
+            model.set_value (iter, 0, visible);
+            model.set_value (iter, 1, item);
+        }
+        return model;
+    }
+
+    /**
+     * @selection: The name to select as the default. NULL means no default.
+     * @flags: A set of flags to specify how the names are displayed.
+     *
+     * Create a combo box with the given list of strings as the entries. If
+     * selection is non-NULL the matching file name is selected by default.
+     * Otherwise nothing is selected. The flags affect how the names are
+     * displayed. The valid flags are GAMES_FILE_LIST_REMOVE_EXTENSION, which
+     * removes extensions, and GAMES_FILE_LIST_REPLACE_UNDERSCORES with replaces
+     * underscores with spaces.
+     *
+     * Return value: A widget with the list of names.
+     **/
+    public Widget create_widget (string? selection, Flags flags) {
+        var model = create_model (flags);
+        var widget = new ComboBox.with_model (model);
+        var renderer = new CellRendererText ();
+        widget.pack_start (renderer, true);
+        widget.add_attribute (renderer, "text", 0);
+
+        bool found = false;
+        if (selection != null) {
+            TreeIter iter;
+            if (model.get_iter_first (out iter)) {
+                do {
+                    Value file;
+                    model.get_value (iter, 1, out file);
+                    if (file == selection) {
+                        widget.set_active_iter (iter);
+                        found = true;
+                        break;
+                    }
+                } while (model.iter_next (ref iter));
+            }
+        }
+        if (!found) {
+            widget.set_active (0);
+        }
+
+        return widget;
+    }
+
+    private static TreeSet<string> new_internal (string glob, va_list paths) {
+        var result = new TreeSet<string> ();
+        var filespec = new PatternSpec (glob);
+
+        for (string? pathelement = paths.arg<string?> (); pathelement != null ; pathelement = 
paths.arg<string?> ()) {
+            try {
+                var dir = Dir.open (pathelement);
+                string? filename;
+                while ((filename = dir.read_name ()) != null) {
+                    if (filespec.match_string (filename)) {
+                        var fullname = Path.build_filename (pathelement, filename);
+                        if (FileUtils.test (fullname, FileTest.IS_REGULAR)) {
+                            result.add (fullname);
+                        }
+                    }
+                }
+            } catch (FileError e) {
+                // ignored
+            }
+        }
+
+        return result;
+    }
+
+    private static void find_images (string directory, TreeSet<string> result) {
+        try {
+            var dir = Dir.open (directory);
+            string? filename;
+            while ((filename = dir.read_name ()) != null) {
+                if (ImageSuffixList.has_image_suffix (filename)) {
+                    var fullname = Path.build_filename (directory, filename);
+                    if (FileUtils.test (fullname, FileTest.IS_REGULAR)) {
+                        result.add (fullname);
+                    }
+                }
+            }
+        } catch (FileError e) {
+            // ignored
+        }
+    }
+}
+
diff --git a/src/find-file.c b/src/find-file.c
index eda3c3b..1c8fc50 100644
--- a/src/find-file.c
+++ b/src/find-file.c
@@ -23,7 +23,7 @@
 #include <glib.h>
 
 #include "find-file.h"
-#include "games-file-list.h"
+#include "riiv.h"
 
 static gchar *
 make_canonical_name (const gchar * name)
diff --git a/src/image-suffix-list.vala b/src/image-suffix-list.vala
index e898b38..b6b22cb 100644
--- a/src/image-suffix-list.vala
+++ b/src/image-suffix-list.vala
@@ -15,24 +15,24 @@
     You should have received a copy of the GNU Library General Public License
     along with this library; if not, see <http://www.gnu.org/licenses/>.  */
 
+using Gee;
 using Gdk;
 
 namespace ImageSuffixList
 {
-    private static SList<string> list = null;
+    private static ArrayList<string> list = null;
     private static Mutex mutex;
 
-    public unowned SList<string> get()
-    {
+    public unowned ArrayList<string> get() {
         mutex.lock ();
 
-        if (list == null)
-        {
+        if (list == null) {
+            list = new ArrayList<string> ();
             Pixbuf.get_formats ().@foreach ((formats) => {
                 var suffices = formats.get_extensions ();
 
                 foreach (var suffix in suffices) {
-                    list.append (".%s".printf (suffix));
+                    list.add (".%s".printf (suffix));
                 }
             });
         }
@@ -41,4 +41,8 @@ namespace ImageSuffixList
 
         return list;
     }
+
+    public bool has_image_suffix (string filename) {
+        return get ().any_match ((suffix) => filename.has_suffix (suffix));
+    }
 }
diff --git a/src/meson.build b/src/meson.build
index aebd553..0e5f21f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,5 +1,6 @@
 vala_sources = files(
-    'image-suffix-list.vala'
+    'image-suffix-list.vala',
+    'file-list.vala',
 )
 
 vala_lib = static_library('riiv',
@@ -26,7 +27,6 @@ sources = files(
     'game.c',
     'gameconfig.c',
     'games-controls.c',
-    'games-file-list.c',
     'games-preimage.c',
     'gnome-robots.c',
     'graphics.c',
diff --git a/src/properties.c b/src/properties.c
index d389c5e..fc15f49 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -34,7 +34,7 @@
 #include "gbdefs.h"
 #include "keyboard.h"
 #include "game.h"
-#include "games-file-list.h"
+#include "riiv.h"
 #include "games-controls.h"
 
 
@@ -173,17 +173,23 @@ delete_cb (GtkWidget * w, gpointer data)
 static void
 pmap_selection (GtkWidget * widget, gpointer data)
 {
-  gint n;
+  GtkTreeIter iter;
 
-  n = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+    GtkTreeModel *model;
+    GValue value = G_VALUE_INIT;
 
-  /* FIXME: Should be de-suffixed. */
-  properties.themename = games_file_list_get_nth (theme_list, n);
+    model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+    gtk_tree_model_get_value (model, &iter, 1, &value);
 
-  conf_set_theme (properties.themename);
+    /* FIXME: Should be de-suffixed. */
+    properties.themename = g_value_get_string (&value);
 
-  load_game_graphics ();
-  clear_game_area ();
+    conf_set_theme (properties.themename);
+
+    load_game_graphics ();
+    clear_game_area ();
+  }
 }
 
 
@@ -340,8 +346,8 @@ make_theme_menu (void)
 
   return games_file_list_create_widget (theme_list,
                                         properties.themename,
-                                        GAMES_FILE_LIST_REMOVE_EXTENSION |
-                                        GAMES_FILE_LIST_REPLACE_UNDERSCORES);
+                                        GAMES_FILE_LIST_FLAGS_REMOVE_EXTENSION |
+                                        GAMES_FILE_LIST_FLAGS_REPLACE_UNDERSCORES);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]