2
* xfdesktop - xfce4's desktop manager
4
* Copyright(c) 2006 Brian Tarricone, <bjt23@cornell.edu>
5
* Copyright(c) 2006 Benedikt Meurer, <benny@xfce.org>
6
* Copyright(c) 2010-2011 Jannis Pohlmann, <jannis@xfce.org>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU Library General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49
#include <libxfce4ui/libxfce4ui.h>
52
#include <thunarx/thunarx.h>
55
#include "xfdesktop-file-utils.h"
56
#include "xfdesktop-common.h"
57
#include "xfdesktop-regular-file-icon.h"
59
#define EMBLEM_SYMLINK "emblem-symbolic-link"
61
struct _XfdesktopRegularFileIconPrivate
69
GFileInfo *filesystem_info;
74
static void xfdesktop_regular_file_icon_finalize(GObject *obj);
76
static GdkPixbuf *xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
78
static G_CONST_RETURN gchar *xfdesktop_regular_file_icon_peek_label(XfdesktopIcon *icon);
79
static G_CONST_RETURN gchar *xfdesktop_regular_file_icon_peek_tooltip(XfdesktopIcon *icon);
80
static GdkDragAction xfdesktop_regular_file_icon_get_allowed_drag_actions(XfdesktopIcon *icon);
81
static GdkDragAction xfdesktop_regular_file_icon_get_allowed_drop_actions(XfdesktopIcon *icon);
82
static gboolean xfdesktop_regular_file_icon_do_drop_dest(XfdesktopIcon *icon,
83
XfdesktopIcon *src_icon,
84
GdkDragAction action);
86
static GFileInfo *xfdesktop_regular_file_icon_peek_file_info(XfdesktopFileIcon *icon);
87
static GFileInfo *xfdesktop_regular_file_icon_peek_filesystem_info(XfdesktopFileIcon *icon);
88
static GFile *xfdesktop_regular_file_icon_peek_file(XfdesktopFileIcon *icon);
89
static void xfdesktop_regular_file_icon_update_file_info(XfdesktopFileIcon *icon,
91
static gboolean xfdesktop_regular_file_can_write_parent(XfdesktopFileIcon *icon);
94
static void xfdesktop_regular_file_icon_tfi_init(ThunarxFileInfoIface *iface);
97
static inline void xfdesktop_regular_file_icon_invalidate_pixbuf(XfdesktopRegularFileIcon *icon);
101
G_DEFINE_TYPE_EXTENDED(XfdesktopRegularFileIcon, xfdesktop_regular_file_icon,
102
XFDESKTOP_TYPE_FILE_ICON, 0,
103
G_IMPLEMENT_INTERFACE(THUNARX_TYPE_FILE_INFO,
104
xfdesktop_regular_file_icon_tfi_init)
107
G_DEFINE_TYPE(XfdesktopRegularFileIcon, xfdesktop_regular_file_icon,
108
XFDESKTOP_TYPE_FILE_ICON)
114
xfdesktop_regular_file_icon_class_init(XfdesktopRegularFileIconClass *klass)
116
GObjectClass *gobject_class = (GObjectClass *)klass;
117
XfdesktopIconClass *icon_class = (XfdesktopIconClass *)klass;
118
XfdesktopFileIconClass *file_icon_class = (XfdesktopFileIconClass *)klass;
120
g_type_class_add_private(klass, sizeof(XfdesktopRegularFileIconPrivate));
122
gobject_class->finalize = xfdesktop_regular_file_icon_finalize;
124
icon_class->peek_pixbuf = xfdesktop_regular_file_icon_peek_pixbuf;
125
icon_class->peek_label = xfdesktop_regular_file_icon_peek_label;
126
icon_class->peek_tooltip = xfdesktop_regular_file_icon_peek_tooltip;
127
icon_class->get_allowed_drag_actions = xfdesktop_regular_file_icon_get_allowed_drag_actions;
128
icon_class->get_allowed_drop_actions = xfdesktop_regular_file_icon_get_allowed_drop_actions;
129
icon_class->do_drop_dest = xfdesktop_regular_file_icon_do_drop_dest;
131
file_icon_class->peek_file_info = xfdesktop_regular_file_icon_peek_file_info;
132
file_icon_class->peek_filesystem_info = xfdesktop_regular_file_icon_peek_filesystem_info;
133
file_icon_class->peek_file = xfdesktop_regular_file_icon_peek_file;
134
file_icon_class->update_file_info = xfdesktop_regular_file_icon_update_file_info;
135
file_icon_class->can_rename_file = xfdesktop_regular_file_can_write_parent;
136
file_icon_class->can_delete_file = xfdesktop_regular_file_can_write_parent;
140
xfdesktop_regular_file_icon_init(XfdesktopRegularFileIcon *icon)
142
icon->priv = G_TYPE_INSTANCE_GET_PRIVATE(icon,
143
XFDESKTOP_TYPE_REGULAR_FILE_ICON,
144
XfdesktopRegularFileIconPrivate);
145
icon->priv->pix_opacity = 100;
146
icon->priv->display_name = NULL;
150
xfdesktop_regular_file_icon_finalize(GObject *obj)
152
XfdesktopRegularFileIcon *icon = XFDESKTOP_REGULAR_FILE_ICON(obj);
153
GtkIconTheme *itheme = gtk_icon_theme_get_for_screen(icon->priv->gscreen);
155
g_signal_handlers_disconnect_by_func(G_OBJECT(itheme),
156
G_CALLBACK(xfdesktop_regular_file_icon_invalidate_pixbuf),
160
g_object_unref(G_OBJECT(icon->priv->pix));
162
if(icon->priv->file_info)
163
g_object_unref(icon->priv->file_info);
165
if(icon->priv->filesystem_info)
166
g_object_unref(icon->priv->filesystem_info);
168
g_object_unref(icon->priv->file);
170
g_free(icon->priv->display_name);
172
if(icon->priv->tooltip)
173
g_free(icon->priv->tooltip);
175
G_OBJECT_CLASS(xfdesktop_regular_file_icon_parent_class)->finalize(obj);
180
xfdesktop_regular_file_icon_tfi_init(ThunarxFileInfoIface *iface)
182
iface->get_name = xfdesktop_thunarx_file_info_get_name;
183
iface->get_uri = xfdesktop_thunarx_file_info_get_uri;
184
iface->get_parent_uri = xfdesktop_thunarx_file_info_get_parent_uri;
185
iface->get_uri_scheme = xfdesktop_thunarx_file_info_get_uri_scheme_file;
186
iface->get_mime_type = xfdesktop_thunarx_file_info_get_mime_type;
187
iface->has_mime_type = xfdesktop_thunarx_file_info_has_mime_type;
188
iface->is_directory = xfdesktop_thunarx_file_info_is_directory;
189
iface->get_file_info = xfdesktop_thunarx_file_info_get_file_info;
190
iface->get_filesystem_info = xfdesktop_thunarx_file_info_get_filesystem_info;
191
iface->get_location = xfdesktop_thunarx_file_info_get_location;
196
xfdesktop_regular_file_icon_invalidate_pixbuf(XfdesktopRegularFileIcon *icon)
198
if(icon->priv->pix) {
199
g_object_unref(G_OBJECT(icon->priv->pix));
200
icon->priv->pix = NULL;
206
xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
209
XfdesktopRegularFileIcon *file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
210
gchar *icon_name = NULL;
211
GdkPixbuf *emblem_pix = NULL;
213
if(size != file_icon->priv->cur_pix_size)
214
xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon);
216
if(!file_icon->priv->pix) {
219
/* create a GFile for the $HOME/.thumbnails/ directory */
220
gchar *thumbnail_dir_path = g_build_filename(xfce_get_homedir(),
221
".thumbnails", NULL);
222
GFile *thumbnail_dir = g_file_new_for_path(thumbnail_dir_path);
224
if(g_file_has_prefix(file_icon->priv->file, thumbnail_dir)) {
225
/* use the filename as custom icon name for thumbnails */
226
icon_name = g_file_get_path(file_icon->priv->file);
227
} else if(xfdesktop_file_utils_is_desktop_file(file_icon->priv->file_info)) {
231
/* try to load the file into memory */
232
if(g_file_load_contents(file_icon->priv->file, NULL, &contents, &length,
235
/* allocate a new key file */
236
GKeyFile *key_file = g_key_file_new();
238
/* try to parse the key file from the contents of the file */
239
if (g_key_file_load_from_data(key_file, contents, length, 0, NULL)) {
240
/* try to determine the custom icon name */
241
icon_name = g_key_file_get_string(key_file,
242
G_KEY_FILE_DESKTOP_GROUP,
243
G_KEY_FILE_DESKTOP_KEY_ICON,
247
/* free key file and in-memory data */
248
g_key_file_free(key_file);
253
/* release thumbnail path */
254
g_object_unref(thumbnail_dir);
255
g_free(thumbnail_dir_path);
257
/* load the symlink emblem if necessary */
258
if(g_file_info_get_attribute_boolean(file_icon->priv->file_info,
259
G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK))
261
GtkIconTheme *itheme = gtk_icon_theme_get_default();
262
gint sym_pix_size = size * 2 / 3;
264
emblem_pix = gtk_icon_theme_load_icon(itheme, EMBLEM_SYMLINK,
265
sym_pix_size, ITHEME_FLAGS,
268
if(gdk_pixbuf_get_width(emblem_pix) != sym_pix_size
269
|| gdk_pixbuf_get_height(emblem_pix) != sym_pix_size)
271
GdkPixbuf *tmp = gdk_pixbuf_scale_simple(emblem_pix,
274
GDK_INTERP_BILINEAR);
275
g_object_unref(emblem_pix);
281
if(file_icon->priv->file_info)
282
gicon = g_file_info_get_icon(file_icon->priv->file_info);
284
file_icon->priv->pix = xfdesktop_file_utils_get_icon(icon_name, gicon,
286
file_icon->priv->pix_opacity);
288
file_icon->priv->cur_pix_size = size;
291
g_object_unref(emblem_pix);
296
return file_icon->priv->pix;
299
static G_CONST_RETURN gchar *
300
xfdesktop_regular_file_icon_peek_label(XfdesktopIcon *icon)
302
XfdesktopRegularFileIcon *regular_file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
304
g_return_val_if_fail(XFDESKTOP_IS_REGULAR_FILE_ICON(icon), NULL);
306
return regular_file_icon->priv->display_name;
310
xfdesktop_regular_file_icon_get_allowed_drag_actions(XfdesktopIcon *icon)
312
GFileInfo *info = xfdesktop_file_icon_peek_file_info(XFDESKTOP_FILE_ICON(icon));
313
GFile *file = xfdesktop_file_icon_peek_file(XFDESKTOP_FILE_ICON(icon));
314
GdkDragAction actions = GDK_ACTION_LINK; /* we can always link */
319
if(g_file_info_get_attribute_boolean(info,
320
G_FILE_ATTRIBUTE_ACCESS_CAN_READ))
322
GFileInfo *parent_info;
325
actions |= GDK_ACTION_COPY;
327
/* we can only move if the parent is writable */
328
parent_file = g_file_get_parent(file);
329
parent_info = g_file_query_info(parent_file,
330
XFDESKTOP_FILE_INFO_NAMESPACE,
331
G_FILE_QUERY_INFO_NONE,
334
if(g_file_info_get_attribute_boolean(parent_info,
335
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
337
actions |= GDK_ACTION_MOVE;
339
g_object_unref(parent_info);
341
g_object_unref(parent_file);
348
xfdesktop_regular_file_icon_get_allowed_drop_actions(XfdesktopIcon *icon)
350
GFileInfo *info = xfdesktop_file_icon_peek_file_info(XFDESKTOP_FILE_ICON(icon));
355
/* if it's executable we can 'copy'. if it's a folder we can do anything
356
* if it's writable. */
357
if(g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) {
358
if(g_file_info_get_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
359
return GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK;
361
if(xfdesktop_file_utils_file_is_executable(info)) {
362
return GDK_ACTION_COPY;
370
xfdesktop_regular_file_icon_do_drop_dest(XfdesktopIcon *icon,
371
XfdesktopIcon *src_icon,
372
GdkDragAction action)
374
XfdesktopRegularFileIcon *regular_file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
375
XfdesktopFileIcon *src_file_icon = XFDESKTOP_FILE_ICON(src_icon);
378
gboolean result = FALSE;
382
g_return_val_if_fail(regular_file_icon && src_file_icon, FALSE);
383
g_return_val_if_fail(xfdesktop_regular_file_icon_get_allowed_drop_actions(icon) != 0,
386
src_file = xfdesktop_file_icon_peek_file(src_file_icon);
388
src_info = xfdesktop_file_icon_peek_file_info(src_file_icon);
392
if(g_file_info_get_file_type(regular_file_icon->priv->file_info) != G_FILE_TYPE_DIRECTORY
393
&& xfdesktop_file_utils_file_is_executable(regular_file_icon->priv->file_info))
397
files.data = src_file;
398
files.prev = files.next = NULL;
400
xfdesktop_file_utils_execute(NULL, regular_file_icon->priv->file, &files,
401
regular_file_icon->priv->gscreen, NULL);
405
GFile *parent, *dest_file = NULL;
408
parent = g_file_get_parent(src_file);
411
g_object_unref(parent);
413
name = g_file_get_basename(src_file);
418
case GDK_ACTION_MOVE:
419
dest_file = g_object_ref(regular_file_icon->priv->file);
421
case GDK_ACTION_COPY:
422
dest_file = g_file_get_child(regular_file_icon->priv->file, name);
424
case GDK_ACTION_LINK:
425
dest_file = g_object_ref(regular_file_icon->priv->file);
428
g_warning("Unsupported drag action: %d", action);
432
xfdesktop_file_utils_transfer_file(action, src_file, dest_file,
433
regular_file_icon->priv->gscreen);
435
g_object_unref(dest_file);
446
static G_CONST_RETURN gchar *
447
xfdesktop_regular_file_icon_peek_tooltip(XfdesktopIcon *icon)
449
XfdesktopRegularFileIcon *regular_file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
451
if(!regular_file_icon->priv->tooltip) {
452
GFileInfo *info = xfdesktop_file_icon_peek_file_info(XFDESKTOP_FILE_ICON(icon));
453
const gchar *content_type;
454
gchar *description, *size_string, *time_string;
460
content_type = g_file_info_get_content_type(info);
461
description = g_content_type_get_description(content_type);
463
size = g_file_info_get_attribute_uint64(info,
464
G_FILE_ATTRIBUTE_STANDARD_SIZE);
465
size_string = g_format_size_for_display(size);
467
mtime = g_file_info_get_attribute_uint64(info,
468
G_FILE_ATTRIBUTE_TIME_MODIFIED);
469
time_string = xfdesktop_file_utils_format_time_for_display(mtime);
471
regular_file_icon->priv->tooltip =
472
g_strdup_printf(_("Type: %s\nSize: %s\nLast modified: %s"),
473
description, size_string, time_string);
480
return regular_file_icon->priv->tooltip;
484
xfdesktop_regular_file_can_write_parent(XfdesktopFileIcon *icon)
486
XfdesktopRegularFileIcon *file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
488
GFileInfo *parent_info;
491
g_return_val_if_fail(file_icon, FALSE);
493
parent_file = g_file_get_parent(file_icon->priv->file);
497
parent_info = g_file_query_info(parent_file,
498
XFDESKTOP_FILE_INFO_NAMESPACE,
499
G_FILE_QUERY_INFO_NONE,
502
g_object_unref(parent_file);
506
writable = g_file_info_get_attribute_boolean(parent_info,
507
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
508
g_object_unref(parent_info);
509
g_object_unref(parent_file);
516
xfdesktop_regular_file_icon_peek_file_info(XfdesktopFileIcon *icon)
518
g_return_val_if_fail(XFDESKTOP_IS_REGULAR_FILE_ICON(icon), NULL);
519
return XFDESKTOP_REGULAR_FILE_ICON(icon)->priv->file_info;
523
xfdesktop_regular_file_icon_peek_filesystem_info(XfdesktopFileIcon *icon)
525
g_return_val_if_fail(XFDESKTOP_IS_REGULAR_FILE_ICON(icon), NULL);
526
return XFDESKTOP_REGULAR_FILE_ICON(icon)->priv->filesystem_info;
530
xfdesktop_regular_file_icon_peek_file(XfdesktopFileIcon *icon)
532
g_return_val_if_fail(XFDESKTOP_IS_REGULAR_FILE_ICON(icon), NULL);
533
return XFDESKTOP_REGULAR_FILE_ICON(icon)->priv->file;
537
xfdesktop_regular_file_icon_update_file_info(XfdesktopFileIcon *icon,
540
XfdesktopRegularFileIcon *regular_file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
541
const gchar *old_display_name;
542
gchar *new_display_name;
544
g_return_if_fail(XFDESKTOP_IS_REGULAR_FILE_ICON(icon));
545
g_return_if_fail(G_IS_FILE_INFO(info));
547
/* release the old file info */
548
if(regular_file_icon->priv->file_info) {
549
g_object_unref(regular_file_icon->priv->file_info);
550
regular_file_icon->priv->file_info = NULL;
553
regular_file_icon->priv->file_info = g_object_ref(info);
555
if(regular_file_icon->priv->filesystem_info)
556
g_object_unref(regular_file_icon->priv->filesystem_info);
558
regular_file_icon->priv->filesystem_info = g_file_query_filesystem_info(regular_file_icon->priv->file,
559
XFDESKTOP_FILESYSTEM_INFO_NAMESPACE,
562
/* get both, old and new display name */
563
old_display_name = regular_file_icon->priv->display_name;
564
new_display_name = xfdesktop_file_utils_get_display_name(regular_file_icon->priv->file,
565
regular_file_icon->priv->file_info);
567
/* check whether the display name has changed with the info update */
568
if(g_strcmp0 (old_display_name, new_display_name) != 0) {
569
/* replace the display name */
570
g_free (regular_file_icon->priv->display_name);
571
regular_file_icon->priv->display_name = new_display_name;
573
/* notify listeners of the label change */
574
xfdesktop_icon_label_changed(XFDESKTOP_ICON(icon));
576
/* no change, release the new display name */
577
g_free (new_display_name);
580
/* invalidate the tooltip */
581
g_free(regular_file_icon->priv->tooltip);
582
regular_file_icon->priv->tooltip = NULL;
584
/* not really easy to check if this changed or not, so just invalidate it */
585
xfdesktop_regular_file_icon_invalidate_pixbuf(regular_file_icon);
586
xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
592
XfdesktopRegularFileIcon *
593
xfdesktop_regular_file_icon_new(GFile *file,
594
GFileInfo *file_info,
597
XfdesktopRegularFileIcon *regular_file_icon;
599
g_return_val_if_fail(G_IS_FILE(file), NULL);
600
g_return_val_if_fail(G_IS_FILE_INFO(file_info), NULL);
601
g_return_val_if_fail(GDK_IS_SCREEN(screen), NULL);
603
regular_file_icon = g_object_new(XFDESKTOP_TYPE_REGULAR_FILE_ICON, NULL);
605
regular_file_icon->priv->file = g_object_ref(file);
606
regular_file_icon->priv->file_info = g_object_ref(file_info);
608
/* set the display name */
609
regular_file_icon->priv->display_name = xfdesktop_file_utils_get_display_name(file,
612
/* query file system information from GIO */
613
regular_file_icon->priv->filesystem_info = g_file_query_filesystem_info(regular_file_icon->priv->file,
614
XFDESKTOP_FILESYSTEM_INFO_NAMESPACE,
617
/* query file information from GIO */
618
regular_file_icon->priv->file_info = g_file_query_info(regular_file_icon->priv->file,
619
XFDESKTOP_FILE_INFO_NAMESPACE,
620
G_FILE_QUERY_INFO_NONE,
623
regular_file_icon->priv->gscreen = screen;
625
g_signal_connect_swapped(G_OBJECT(gtk_icon_theme_get_for_screen(screen)),
627
G_CALLBACK(xfdesktop_regular_file_icon_invalidate_pixbuf),
630
return regular_file_icon;
634
xfdesktop_regular_file_icon_set_pixbuf_opacity(XfdesktopRegularFileIcon *icon,
637
g_return_if_fail(XFDESKTOP_IS_REGULAR_FILE_ICON(icon) && opacity <= 100);
639
if(opacity == icon->priv->pix_opacity)
642
icon->priv->pix_opacity = opacity;
644
xfdesktop_regular_file_icon_invalidate_pixbuf(icon);
645
xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));