1 /*
2  * Copyright © 2009-2018 Siyan Panayotov <contact@siyanpanayotov.com>
3  *
4  * This file is part of Viewnior.
5  *
6  * Viewnior is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Viewnior is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Viewnior.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <libintl.h>
21 #include <glib/gi18n.h>
22 #define _(String) gettext (String)
23 
24 #include <gtk/gtk.h>
25 #include <gio/gio.h>
26 #include <gdk/gdkpixbuf.h>
27 #include "vnr-file.h"
28 #include "vnr-tools.h"
29 
30 G_DEFINE_TYPE (VnrFile, vnr_file, G_TYPE_OBJECT);
31 
32 GList * supported_mime_types;
33 
34 static gint
compare_files(VnrFile * file,char * uri)35 compare_files(VnrFile *file, char *uri)
36 {
37     if(g_strcmp0(uri, file->path) == 0)
38         return 0;
39     else
40         return 1;
41 }
42 
43 /* Modified version of eog's eog_image_get_supported_mime_types */
44 static GList *
vnr_file_get_supported_mime_types(void)45 vnr_file_get_supported_mime_types (void)
46 {
47     GSList *format_list, *it;
48     gchar **mime_types;
49     int i;
50 
51     if (!supported_mime_types) {
52         format_list = gdk_pixbuf_get_formats ();
53 
54         for (it = format_list; it != NULL; it = it->next) {
55             mime_types =
56                 gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) it->data);
57 
58             for (i = 0; mime_types[i] != NULL; i++) {
59                 supported_mime_types =
60                     g_list_prepend (supported_mime_types,
61                             g_strdup (mime_types[i]));
62             }
63 
64             g_strfreev (mime_types);
65         }
66 
67         supported_mime_types = g_list_prepend(supported_mime_types,
68                                               "image/vnd.microsoft.icon");
69 
70         supported_mime_types = g_list_sort (supported_mime_types,
71                             (GCompareFunc) compare_quarks);
72 
73         g_slist_free (format_list);
74     }
75 
76     return supported_mime_types;
77 }
78 
79 static gboolean
vnr_file_is_supported_mime_type(const char * mime_type)80 vnr_file_is_supported_mime_type (const char *mime_type)
81 {
82     GList *result;
83     GQuark quark;
84 
85     if (mime_type == NULL) {
86         return FALSE;
87     }
88 
89     supported_mime_types = vnr_file_get_supported_mime_types ();
90 
91     quark = g_quark_from_string (mime_type);
92 
93     result = g_list_find_custom (supported_mime_types,
94                      GINT_TO_POINTER (quark),
95                      (GCompareFunc) compare_quarks);
96 
97     return (result != NULL);
98 }
99 
100 static void
vnr_file_class_init(VnrFileClass * klass)101 vnr_file_class_init (VnrFileClass * klass)
102 {
103 }
104 
105 static void
vnr_file_init(VnrFile * file)106 vnr_file_init (VnrFile * file)
107 {
108     file->display_name = NULL;
109 }
110 
111 VnrFile *
vnr_file_new()112 vnr_file_new ()
113 {
114     return VNR_FILE (g_object_new (VNR_TYPE_FILE, NULL));
115 }
116 
117 static void
vnr_file_set_display_name(VnrFile * vnr_file,char * display_name)118 vnr_file_set_display_name(VnrFile *vnr_file, char *display_name)
119 {
120     vnr_file->display_name = g_strdup(display_name);
121     vnr_file->display_name_collate = g_utf8_collate_key_for_filename(display_name, -1);
122 }
123 
124 
125 static gint
vnr_file_list_compare(gconstpointer a,gconstpointer b,gpointer user_data)126 vnr_file_list_compare(gconstpointer a, gconstpointer b, gpointer user_data){
127     return g_strcmp0(VNR_FILE(a)->display_name_collate,
128                      VNR_FILE(b)->display_name_collate);
129 }
130 
131 
132 static GList *
vnr_file_dir_content_to_list(gchar * path,gboolean sort,gboolean include_hidden)133 vnr_file_dir_content_to_list(gchar *path, gboolean sort, gboolean include_hidden)
134 {
135     GList *file_list = NULL;
136     GFile *file;
137     GFileEnumerator *f_enum ;
138     GFileInfo *file_info;
139     VnrFile *vnr_file;
140     const char *mimetype;
141 
142     file = g_file_new_for_path(path);
143     f_enum = g_file_enumerate_children(file, G_FILE_ATTRIBUTE_STANDARD_NAME","
144                                        G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
145                                        G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
146                                        G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
147                                        G_FILE_QUERY_INFO_NONE,
148                                        NULL, NULL);
149     file_info = g_file_enumerator_next_file(f_enum,NULL,NULL);
150 
151 
152     while(file_info != NULL){
153         vnr_file = vnr_file_new();
154 
155         mimetype =g_file_info_get_content_type(file_info);
156 
157         if(vnr_file_is_supported_mime_type(mimetype) && (include_hidden || !g_file_info_get_is_hidden (file_info)) ){
158             vnr_file_set_display_name(vnr_file, (char*)g_file_info_get_display_name (file_info));
159 
160             vnr_file->path =g_strjoin(G_DIR_SEPARATOR_S, path,
161                                       vnr_file->display_name, NULL);
162 
163             file_list = g_list_prepend(file_list, vnr_file);
164         }
165 
166         g_object_unref(file_info);
167         file_info = g_file_enumerator_next_file(f_enum,NULL,NULL);
168     }
169 
170     g_object_unref (file);
171     g_file_enumerator_close (f_enum, NULL, NULL);
172     g_object_unref (f_enum);
173 
174     if(sort)
175         file_list = g_list_sort_with_data(file_list,
176                                           vnr_file_list_compare, NULL);
177 
178     return file_list;
179 }
180 
181 
182 void
vnr_file_load_single_uri(char * p_path,GList ** file_list,gboolean include_hidden,GError ** error)183 vnr_file_load_single_uri(char *p_path, GList **file_list, gboolean include_hidden, GError **error)
184 {
185     GFile *file;
186     GFileInfo *fileinfo;
187     GFileType filetype;
188 
189     file = g_file_new_for_path(p_path);
190     fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE","
191                                   G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
192                                   0, NULL, error);
193 
194     if (fileinfo == NULL)
195         return;
196 
197     filetype = g_file_info_get_file_type(fileinfo);
198 
199     if (filetype == G_FILE_TYPE_DIRECTORY)
200     {
201         *file_list = vnr_file_dir_content_to_list(p_path, TRUE, include_hidden);
202     }
203     else
204     {
205         GFile *parent;
206         GList *current_position;
207 
208         parent = g_file_get_parent(file);
209         *file_list = vnr_file_dir_content_to_list(g_file_get_path(parent), TRUE, include_hidden);
210 
211         g_object_unref(parent);
212 
213         current_position = g_list_find_custom(*file_list, p_path,
214                                   (GCompareFunc)compare_files);
215 
216         if(current_position != NULL)
217             *file_list = current_position;
218         else if(*file_list == NULL)
219             return;
220         else
221         {
222             *error = g_error_new(1, 0,
223                                  _("Couldn't recognise the image file\n"
224                                  "format for file '%s'"),
225                                  g_file_info_get_display_name (fileinfo));
226         }
227     }
228     g_object_unref (file);
229     g_object_unref(fileinfo);
230 }
231 
232 void
vnr_file_load_uri_list(GSList * uri_list,GList ** file_list,gboolean include_hidden,GError ** error)233 vnr_file_load_uri_list (GSList *uri_list, GList **file_list, gboolean include_hidden, GError **error)
234 {
235     GFile *file;
236     GFileInfo *fileinfo;
237     GFileType filetype;
238     gchar *p_path;
239 
240     while(uri_list != NULL)
241     {
242         p_path = uri_list->data;
243         file = g_file_new_for_path(p_path);
244         fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE","
245                                       G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
246                                       G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
247                                       G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
248                                       0, NULL, error);
249 
250         if (fileinfo == NULL)
251         {
252             g_clear_error (error);
253             g_object_unref (file);
254 
255             uri_list = g_slist_next(uri_list);
256             continue;
257         }
258 
259         filetype = g_file_info_get_file_type(fileinfo);
260 
261         if (filetype == G_FILE_TYPE_DIRECTORY)
262         {
263             *file_list = g_list_concat (*file_list, vnr_file_dir_content_to_list(p_path, FALSE, include_hidden));
264         }
265         else
266         {
267             VnrFile *new_vnrfile;
268             const char *mimetype;
269 
270             new_vnrfile = vnr_file_new();
271 
272             mimetype = g_file_info_get_content_type(fileinfo);
273 
274             if(vnr_file_is_supported_mime_type(mimetype) && (include_hidden || !g_file_info_get_is_hidden (fileinfo)) )
275             {
276                 vnr_file_set_display_name(new_vnrfile, (char*)g_file_info_get_display_name (fileinfo));
277 
278                 new_vnrfile->path = p_path;
279 
280                 *file_list = g_list_prepend(*file_list, new_vnrfile);
281             }
282         }
283         g_object_unref (file);
284         g_object_unref (fileinfo);
285 
286         uri_list = g_slist_next(uri_list);
287     }
288 
289     *file_list = g_list_sort_with_data(*file_list, vnr_file_list_compare, NULL);
290 }
291