Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include "gfileicon.h"
26 : : #include "gfile.h"
27 : : #include "gicon.h"
28 : : #include "glibintl.h"
29 : : #include "gloadableicon.h"
30 : : #include "ginputstream.h"
31 : : #include "gtask.h"
32 : : #include "gioerror.h"
33 : :
34 : :
35 : : /**
36 : : * GFileIcon:
37 : : *
38 : : * `GFileIcon` specifies an icon by pointing to an image file
39 : : * to be used as icon.
40 : : *
41 : : * It implements [iface@Gio.LoadableIcon].
42 : : */
43 : :
44 : : static void g_file_icon_icon_iface_init (GIconIface *iface);
45 : : static void g_file_icon_loadable_icon_iface_init (GLoadableIconIface *iface);
46 : : static void g_file_icon_load_async (GLoadableIcon *icon,
47 : : int size,
48 : : GCancellable *cancellable,
49 : : GAsyncReadyCallback callback,
50 : : gpointer user_data);
51 : :
52 : : struct _GFileIcon
53 : : {
54 : : GObject parent_instance;
55 : :
56 : : GFile *file;
57 : : };
58 : :
59 : : struct _GFileIconClass
60 : : {
61 : : GObjectClass parent_class;
62 : : };
63 : :
64 : : enum
65 : : {
66 : : PROP_0,
67 : : PROP_FILE
68 : : };
69 : :
70 : 208 : G_DEFINE_TYPE_WITH_CODE (GFileIcon, g_file_icon, G_TYPE_OBJECT,
71 : : G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
72 : : g_file_icon_icon_iface_init)
73 : : G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON,
74 : : g_file_icon_loadable_icon_iface_init))
75 : :
76 : : static void
77 : 1 : g_file_icon_get_property (GObject *object,
78 : : guint prop_id,
79 : : GValue *value,
80 : : GParamSpec *pspec)
81 : : {
82 : 1 : GFileIcon *icon = G_FILE_ICON (object);
83 : :
84 : 1 : switch (prop_id)
85 : : {
86 : 1 : case PROP_FILE:
87 : 1 : g_value_set_object (value, icon->file);
88 : 1 : break;
89 : :
90 : 0 : default:
91 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
92 : : }
93 : 1 : }
94 : :
95 : : static void
96 : 28 : g_file_icon_set_property (GObject *object,
97 : : guint prop_id,
98 : : const GValue *value,
99 : : GParamSpec *pspec)
100 : : {
101 : 28 : GFileIcon *icon = G_FILE_ICON (object);
102 : :
103 : 28 : switch (prop_id)
104 : : {
105 : 28 : case PROP_FILE:
106 : 28 : icon->file = G_FILE (g_value_dup_object (value));
107 : 28 : break;
108 : :
109 : 0 : default:
110 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111 : : }
112 : 28 : }
113 : :
114 : : static void
115 : 28 : g_file_icon_constructed (GObject *object)
116 : : {
117 : : #ifndef G_DISABLE_ASSERT
118 : 28 : GFileIcon *icon = G_FILE_ICON (object);
119 : : #endif
120 : :
121 : 28 : G_OBJECT_CLASS (g_file_icon_parent_class)->constructed (object);
122 : :
123 : : /* Must have be set during construction */
124 : 28 : g_assert (icon->file != NULL);
125 : 28 : }
126 : :
127 : : static void
128 : 28 : g_file_icon_finalize (GObject *object)
129 : : {
130 : : GFileIcon *icon;
131 : :
132 : 28 : icon = G_FILE_ICON (object);
133 : :
134 : 28 : if (icon->file)
135 : 28 : g_object_unref (icon->file);
136 : :
137 : 28 : G_OBJECT_CLASS (g_file_icon_parent_class)->finalize (object);
138 : 28 : }
139 : :
140 : : static void
141 : 2 : g_file_icon_class_init (GFileIconClass *klass)
142 : : {
143 : 2 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
144 : :
145 : 2 : gobject_class->get_property = g_file_icon_get_property;
146 : 2 : gobject_class->set_property = g_file_icon_set_property;
147 : 2 : gobject_class->finalize = g_file_icon_finalize;
148 : 2 : gobject_class->constructed = g_file_icon_constructed;
149 : :
150 : : /**
151 : : * GFileIcon:file:
152 : : *
153 : : * The file containing the icon.
154 : : */
155 : 2 : g_object_class_install_property (gobject_class, PROP_FILE,
156 : : g_param_spec_object ("file", NULL, NULL,
157 : : G_TYPE_FILE,
158 : : G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
159 : 2 : }
160 : :
161 : : static void
162 : 28 : g_file_icon_init (GFileIcon *file)
163 : : {
164 : 28 : }
165 : :
166 : : /**
167 : : * g_file_icon_new:
168 : : * @file: a #GFile.
169 : : *
170 : : * Creates a new icon for a file.
171 : : *
172 : : * Returns: (transfer full) (type GFileIcon): a #GIcon for the given
173 : : * @file, or %NULL on error.
174 : : **/
175 : : GIcon *
176 : 28 : g_file_icon_new (GFile *file)
177 : : {
178 : 28 : g_return_val_if_fail (G_IS_FILE (file), NULL);
179 : :
180 : 28 : return G_ICON (g_object_new (G_TYPE_FILE_ICON, "file", file, NULL));
181 : : }
182 : :
183 : : /**
184 : : * g_file_icon_get_file:
185 : : * @icon: a #GIcon.
186 : : *
187 : : * Gets the #GFile associated with the given @icon.
188 : : *
189 : : * Returns: (transfer none): a #GFile.
190 : : **/
191 : : GFile *
192 : 7 : g_file_icon_get_file (GFileIcon *icon)
193 : : {
194 : 7 : g_return_val_if_fail (G_IS_FILE_ICON (icon), NULL);
195 : :
196 : 7 : return icon->file;
197 : : }
198 : :
199 : : static guint
200 : 5 : g_file_icon_hash (GIcon *icon)
201 : : {
202 : 5 : GFileIcon *file_icon = G_FILE_ICON (icon);
203 : :
204 : 5 : return g_file_hash (file_icon->file);
205 : : }
206 : :
207 : : static gboolean
208 : 15 : g_file_icon_equal (GIcon *icon1,
209 : : GIcon *icon2)
210 : : {
211 : 15 : GFileIcon *file1 = G_FILE_ICON (icon1);
212 : 15 : GFileIcon *file2 = G_FILE_ICON (icon2);
213 : :
214 : 15 : return g_file_equal (file1->file, file2->file);
215 : : }
216 : :
217 : : static gboolean
218 : 0 : g_file_icon_to_tokens (GIcon *icon,
219 : : GPtrArray *tokens,
220 : : gint *out_version)
221 : : {
222 : 0 : GFileIcon *file_icon = G_FILE_ICON (icon);
223 : :
224 : 0 : g_return_val_if_fail (out_version != NULL, FALSE);
225 : :
226 : 0 : *out_version = 0;
227 : :
228 : 0 : g_ptr_array_add (tokens, g_file_get_uri (file_icon->file));
229 : 0 : return TRUE;
230 : : }
231 : :
232 : : static GIcon *
233 : 0 : g_file_icon_from_tokens (gchar **tokens,
234 : : gint num_tokens,
235 : : gint version,
236 : : GError **error)
237 : : {
238 : : GIcon *icon;
239 : : GFile *file;
240 : :
241 : 0 : icon = NULL;
242 : :
243 : 0 : if (version != 0)
244 : : {
245 : 0 : g_set_error (error,
246 : : G_IO_ERROR,
247 : : G_IO_ERROR_INVALID_ARGUMENT,
248 : : _("Can’t handle version %d of GFileIcon encoding"),
249 : : version);
250 : 0 : goto out;
251 : : }
252 : :
253 : 0 : if (num_tokens != 1)
254 : : {
255 : 0 : g_set_error_literal (error,
256 : : G_IO_ERROR,
257 : : G_IO_ERROR_INVALID_ARGUMENT,
258 : : _("Malformed input data for GFileIcon"));
259 : 0 : goto out;
260 : : }
261 : :
262 : 0 : file = g_file_new_for_uri (tokens[0]);
263 : 0 : icon = g_file_icon_new (file);
264 : 0 : g_object_unref (file);
265 : :
266 : 0 : out:
267 : 0 : return icon;
268 : : }
269 : :
270 : : static GVariant *
271 : 2 : g_file_icon_serialize (GIcon *icon)
272 : : {
273 : 2 : GFileIcon *file_icon = G_FILE_ICON (icon);
274 : :
275 : 2 : return g_variant_new ("(sv)", "file", g_variant_new_take_string (g_file_get_uri (file_icon->file)));
276 : : }
277 : :
278 : : static void
279 : 2 : g_file_icon_icon_iface_init (GIconIface *iface)
280 : : {
281 : 2 : iface->hash = g_file_icon_hash;
282 : 2 : iface->equal = g_file_icon_equal;
283 : 2 : iface->to_tokens = g_file_icon_to_tokens;
284 : 2 : iface->from_tokens = g_file_icon_from_tokens;
285 : 2 : iface->serialize = g_file_icon_serialize;
286 : 2 : }
287 : :
288 : :
289 : : static GInputStream *
290 : 1 : g_file_icon_load (GLoadableIcon *icon,
291 : : int size,
292 : : char **type,
293 : : GCancellable *cancellable,
294 : : GError **error)
295 : : {
296 : : GFileInputStream *stream;
297 : 1 : GFileIcon *file_icon = G_FILE_ICON (icon);
298 : :
299 : 1 : stream = g_file_read (file_icon->file,
300 : : cancellable,
301 : : error);
302 : :
303 : 1 : if (stream && type)
304 : 0 : *type = NULL;
305 : :
306 : 1 : return G_INPUT_STREAM (stream);
307 : : }
308 : :
309 : : static void
310 : 1 : load_async_callback (GObject *source_object,
311 : : GAsyncResult *res,
312 : : gpointer user_data)
313 : : {
314 : : GFileInputStream *stream;
315 : 1 : GError *error = NULL;
316 : 1 : GTask *task = user_data;
317 : :
318 : 1 : stream = g_file_read_finish (G_FILE (source_object), res, &error);
319 : 1 : if (stream == NULL)
320 : 0 : g_task_return_error (task, error);
321 : : else
322 : 1 : g_task_return_pointer (task, stream, g_object_unref);
323 : 1 : g_object_unref (task);
324 : 1 : }
325 : :
326 : : static void
327 : 1 : g_file_icon_load_async (GLoadableIcon *icon,
328 : : int size,
329 : : GCancellable *cancellable,
330 : : GAsyncReadyCallback callback,
331 : : gpointer user_data)
332 : : {
333 : 1 : GFileIcon *file_icon = G_FILE_ICON (icon);
334 : : GTask *task;
335 : :
336 : 1 : task = g_task_new (icon, cancellable, callback, user_data);
337 : 1 : g_task_set_source_tag (task, g_file_icon_load_async);
338 : :
339 : 1 : g_file_read_async (file_icon->file, 0,
340 : : cancellable,
341 : : load_async_callback, task);
342 : 1 : }
343 : :
344 : : static GInputStream *
345 : 1 : g_file_icon_load_finish (GLoadableIcon *icon,
346 : : GAsyncResult *res,
347 : : char **type,
348 : : GError **error)
349 : : {
350 : 1 : g_return_val_if_fail (g_task_is_valid (res, icon), NULL);
351 : :
352 : 1 : if (type)
353 : 0 : *type = NULL;
354 : :
355 : 1 : return g_task_propagate_pointer (G_TASK (res), error);
356 : : }
357 : :
358 : : static void
359 : 2 : g_file_icon_loadable_icon_iface_init (GLoadableIconIface *iface)
360 : : {
361 : 2 : iface->load = g_file_icon_load;
362 : 2 : iface->load_async = g_file_icon_load_async;
363 : 2 : iface->load_finish = g_file_icon_load_finish;
364 : 2 : }
|