diff --git a/Makefile b/Makefile
index bc1d5de..6f47a2b 100644
--- a/Makefile
+++ b/Makefile
@@ -61,6 +61,7 @@ UNUNITIZED_SRC_FILES = \
 	main.vala \
 	AppWindow.vala \
 	CollectionPage.vala \
+	NaturalCmp.vala \
 	Thumbnail.vala \
 	ThumbnailCache.vala \
 	CheckerboardLayout.vala \
diff --git a/src/NaturalCmp-Test.vala b/src/NaturalCmp-Test.vala
new file mode 100644
index 0000000..79f0cfe
--- /dev/null
+++ b/src/NaturalCmp-Test.vala
@@ -0,0 +1,86 @@
+void add_bigger_as_strcmp_tests () {
+    Test.add_func ("/vala/test", () => {
+            string a = "foo";
+            string b = "bar";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            b = "Foo";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            b = "FOO";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            b = "";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            a = "foo12";
+            b = "foo";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+    });
+}
+
+void add_equals_as_strcmp_tests () {
+    Test.add_func ("/vala/test", () => {
+            string a = "foo";
+            string b = "foo";
+            assert(strcmp(a,b) == 0);
+            assert(NaturalCmp.compare(a,b) == 0);
+            a = "foo123";
+            b = "foo123";
+            assert(strcmp(a,b) == 0);
+            assert(NaturalCmp.compare(a,b) == 0);
+            a = "123";
+            b = "123";
+            assert(strcmp(a,b) == 0);
+            assert(NaturalCmp.compare(a,b) == 0);
+            a = "";
+            b = "";
+            assert(strcmp(a,b) == 0);
+            assert(NaturalCmp.compare(a,b) == 0);
+    });
+}
+
+void add_equals_unlike_strcmp_tests () {
+    Test.add_func ("/vala/test", () => {
+            string a = "0123";
+            string b = "123";
+            assert(strcmp(a,b) < 0);
+            assert(NaturalCmp.compare(a,b) == 0);
+            a = "asd123";
+            b = "asd000123";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) == 0);
+    });
+}
+
+
+void add_bigger_unlike_strcmp_tests () {
+    Test.add_func ("/vala/test", () => {
+            string a = "10";
+            string b = "2";
+            assert(strcmp(a,b) < 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            a = "asd10";
+            b = "asd2";
+            assert(strcmp(a,b) < 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            a = "asd010";
+            b = "asd002";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+            a = "000foo";
+            b = "00000000bar";
+            assert(strcmp(a,b) > 0);
+            assert(NaturalCmp.compare(a,b) > 0);
+    });
+}
+
+void main (string[] args) {
+    Test.init (ref args);
+    add_bigger_as_strcmp_tests ();
+    add_equals_as_strcmp_tests ();
+    add_equals_unlike_strcmp_tests ();
+    add_bigger_unlike_strcmp_tests ();
+    Test.run ();
+}
\ No newline at end of file
diff --git a/src/NaturalCmp.vala b/src/NaturalCmp.vala
new file mode 100644
index 0000000..9f9f2be
--- /dev/null
+++ b/src/NaturalCmp.vala
@@ -0,0 +1,111 @@
+/**
+ * NaturalCmp
+ * Simple helper class for natural comparison in Vala.
+ *
+ * (c) Tobia Tesan <tobia.tesan@gmail.com>, 2014
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+class NaturalCmp {
+
+    private static const int AFIRST=-1; // Return this value if a precedes b
+    private static const int BFIRST=1;
+    private static const int EQUAL=0;
+
+    private static bool is_number(char c) {
+        return c.to_string() in "0123456789";
+    }
+
+    private static int rip_number(owned string s, ref int index) {
+        /* 
+         * Given a string in the form [0-9]*[a-zA-Z, etc]*
+         * returns the int value of the first block and increments index
+         * by its length as a side effect.
+         */
+        int number = 0;
+        while (s.length != 0 && is_number(s[0])) {
+            number=number*10;
+            number+=int.parse(s[0].to_string());
+            s=s.substring(1);
+            index++;
+        }
+        return number;
+    }
+
+    public static int compare(string a, string b) {
+        /* 
+         * Implements natural comparison.
+         * Essentially this means that, like strcmp does, foo > bar and 1 < 2
+         * BUT, unlike strcmp, foo10 > foo2 and 1 < 02.
+         * See naturalcmp-test.vala
+         */ 
+
+        if (a.length == 0) {
+            if (b.length == 0) {
+                // a,b == ""
+                return EQUAL;
+            } else {
+                // Just a == ""
+                return AFIRST;
+            }
+        } else {  // a != ""
+            if (b.length == 0) {
+                return BFIRST;
+            } else {
+                // Both a,b != ""
+                if (is_number(a[0])) {
+                    if (is_number(b[0])) {
+                        // both have trailing numerals: we have to parse the numbers
+                        int a_chopdepth = 0;
+                        int a_number = rip_number(a, ref a_chopdepth);
+                        string a_chopped = "";
+                        assert (a.length >= a_chopdepth);
+                        // rip_number should not seek beyond string length.
+                        a_chopped = a.substring(a_chopdepth);
+
+                        int b_chopdepth = 0;
+                        int b_number = rip_number(b, ref b_chopdepth);
+                        string b_chopped = "";
+                        assert (b.length >= b_chopdepth);
+                        b_chopped = b.substring(b_chopdepth);
+
+                        if (a_number > b_number) {
+                            return BFIRST;
+                        } else if (a_number < b_number) {
+                            return AFIRST;
+                        } else {
+                            /* Nice, both numbers are exactly the same. 
+                             * We evaulate whatever comes after them.
+                             * Caveat: we'd get here if we had, e.g., asd0123 and asd123 (both evaluate to 123).
+                             * Hence, we cannot assume that we chopped the same amount of chars off each
+                             */
+                            return compare(a_chopped,b_chopped);
+                        }
+                    } else {
+                        // a starts with a numeral, b doesn't
+                        return AFIRST;
+                    }
+                } else {
+                    if (is_number(b[0])) {
+                        // b starts with a numeral, a doesn't
+                        return BFIRST;
+                    } else { // neither starts with a numberal, we handle this pair of chars strcmp-style
+                        if (a[0] > b[0]) {
+                            return BFIRST;
+                        } else if (a[0] < b[0]) {
+                            return AFIRST;
+                        } else {
+                            // equal
+                            return compare(a.substring(1),
+                                           b.substring(1));
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/Thumbnail.vala b/src/Thumbnail.vala
index c33d43b..d891f7c 100644
--- a/src/Thumbnail.vala
+++ b/src/Thumbnail.vala
@@ -161,7 +161,7 @@ public class Thumbnail : MediaSourceItem {
     }
     
     public static int64 title_ascending_comparator(void *a, void *b) {
-        int64 result = strcmp(((Thumbnail *) a)->media.get_name(), ((Thumbnail *) b)->media.get_name());
+        int64 result = NaturalCmp.compare(((Thumbnail *) a)->media.get_name(), ((Thumbnail *) b)->media.get_name());
         
         return (result != 0) ? result : photo_id_ascending_comparator(a, b);
     }
