Merge lp:~noskcaj/ubuntu/vivid/thunar/1.6.4 into lp:ubuntu/vivid/thunar

Proposed by Jackson Doak on 2015-01-04
Status: Needs review
Proposed branch: lp:~noskcaj/ubuntu/vivid/thunar/1.6.4
Merge into: lp:ubuntu/vivid/thunar
Diff against target: 212897 lines (+58226/-66350)
175 files modified
.pc/02_fix-default-application-selection.patch/thunar/thunar-file.c (+0/-4064)
.pc/applied-patches (+0/-5)
.pc/git-force-toolbr-icons.patch/thunar/thunar-window.c (+0/-3846)
.pc/git-save-keyboard-shortcuts.patch/thunar/thunar-application.c (+0/-2067)
.pc/git-xfdesktop-4.11.patch/plugins/thunar-wallpaper/twp-provider.c (+0/-307)
.pc/gtk3-bookmarks.patch/thunar/thunar-gio-extensions.c (+0/-587)
.pc/gtk3-bookmarks.patch/thunar/thunar-shortcuts-model.c (+0/-2214)
.pc/gtk3-bookmarks.patch/thunar/thunar-util.c (+0/-485)
.pc/menu-icon-tweaks.patch/thunar/thunar-standard-view.c (+9/-2)
.pc/menu-icon-tweaks.patch/thunar/thunar-tree-view.c (+1/-0)
.pc/menu-icon-tweaks.patch/thunar/thunar-window.c (+1/-0)
ChangeLog (+2473/-0)
INSTALL (+3/-3)
Makefile.am (+26/-3)
Makefile.in (+147/-41)
NEWS (+29/-0)
aclocal.m4 (+289/-154)
config.guess (+99/-214)
config.h.in (+0/-3)
config.sub (+33/-24)
configure (+431/-285)
configure.ac (+4/-4)
debian/changelog (+10/-0)
debian/patches/0001-Don-t-copy-templates-but-create-them-bug-8312.patch (+0/-256)
debian/patches/02_fix-default-application-selection.patch (+0/-39)
debian/patches/git-force-toolbr-icons.patch (+0/-18)
debian/patches/git-save-keyboard-shortcuts.patch (+0/-138)
debian/patches/git-xfdesktop-4.11.patch (+0/-188)
debian/patches/gtk3-bookmarks.patch (+0/-80)
debian/patches/series (+0/-5)
debian/thunar.install (+2/-0)
depcomp (+2/-1)
docs/Makefile.am (+1/-2)
docs/Makefile.in (+53/-26)
docs/README.thunarrc (+0/-253)
docs/Thunar.1 (+2/-2)
docs/design/Makefile.in (+46/-17)
docs/papers/Makefile.in (+46/-17)
docs/reference/Makefile.in (+52/-24)
docs/reference/thunarx/Makefile.am (+2/-1)
docs/reference/thunarx/Makefile.in (+134/-75)
docs/reference/thunarx/html/ThunarxFileInfo.html (+798/-571)
docs/reference/thunarx/html/ThunarxMenuProvider.html (+311/-243)
docs/reference/thunarx/html/ThunarxPreferencesProvider.html (+131/-97)
docs/reference/thunarx/html/ThunarxPropertyPage.html (+329/-227)
docs/reference/thunarx/html/ThunarxPropertyPageProvider.html (+148/-115)
docs/reference/thunarx/html/ThunarxProviderFactory.html (+125/-102)
docs/reference/thunarx/html/ThunarxProviderPlugin.html (+654/-490)
docs/reference/thunarx/html/ThunarxRenamer.html (+635/-475)
docs/reference/thunarx/html/ThunarxRenamerProvider.html (+122/-95)
docs/reference/thunarx/html/index.html (+4/-4)
docs/reference/thunarx/html/index.sgml (+70/-40)
docs/reference/thunarx/html/ix01.html (+109/-109)
docs/reference/thunarx/html/style.css (+317/-107)
docs/reference/thunarx/html/thunarx-Variables-and-functions-to-check-the-library-version.html (+208/-170)
docs/reference/thunarx/html/thunarx-abstraction-layer.html (+9/-9)
docs/reference/thunarx/html/thunarx-fundamentals.html (+9/-9)
docs/reference/thunarx/html/thunarx-overview.html (+9/-9)
docs/reference/thunarx/html/thunarx-providers.html (+9/-9)
docs/reference/thunarx/html/thunarx-using-extensions.html (+9/-9)
docs/reference/thunarx/html/thunarx-writing-extensions-advanced-topics.html (+11/-11)
docs/reference/thunarx/html/thunarx-writing-extensions-getting-started.html (+10/-10)
docs/reference/thunarx/html/thunarx-writing-extensions.html (+13/-13)
docs/reference/thunarx/html/thunarx.devhelp2 (+58/-58)
docs/reference/thunarx/version.xml (+1/-1)
examples/Makefile.in (+52/-24)
examples/tex-open-terminal/Makefile.in (+49/-19)
gtk-doc.make (+77/-42)
icons/128x128/Makefile.in (+46/-17)
icons/16x16/Makefile.in (+46/-17)
icons/24x24/Makefile.in (+46/-17)
icons/48x48/Makefile.in (+46/-17)
icons/64x64/Makefile.in (+46/-17)
icons/Makefile.in (+52/-24)
icons/scalable/Makefile.in (+46/-17)
ltmain.sh (+19/-13)
missing (+2/-2)
org.xfce.thunar.policy.in.in (+37/-0)
pixmaps/Makefile.in (+46/-17)
plugins/Makefile.in (+52/-24)
plugins/thunar-apr/Makefile.in (+49/-19)
plugins/thunar-sbr/Makefile.in (+49/-19)
plugins/thunar-sendto-email/Makefile.in (+49/-19)
plugins/thunar-tpa/Makefile.in (+49/-19)
plugins/thunar-tpa/thunar-tpa.c (+9/-11)
plugins/thunar-uca/Makefile.in (+49/-19)
plugins/thunar-wallpaper/Makefile.in (+49/-19)
po/POTFILES.in (+2/-0)
po/ar.po (+511/-807)
po/ast.po (+938/-1327)
po/be.po (+768/-1215)
po/bg.po (+590/-885)
po/bn.po (+602/-854)
po/ca.po (+322/-741)
po/cs.po (+632/-1066)
po/da.po (+520/-901)
po/de.po (+683/-1106)
po/el.po (+717/-984)
po/en_AU.po (+3597/-0)
po/en_GB.po (+544/-927)
po/eo.po (+666/-1129)
po/es.po (+478/-670)
po/et.po (+984/-1409)
po/eu.po (+533/-918)
po/fi.po (+618/-879)
po/fr.po (+723/-1132)
po/gl.po (+617/-1057)
po/he.po (+394/-724)
po/hr.po (+552/-658)
po/hu.po (+417/-570)
po/id.po (+299/-685)
po/is.po (+939/-1426)
po/it.po (+598/-1088)
po/ja.po (+469/-585)
po/kk.po (+436/-791)
po/ko.po (+486/-523)
po/lt.po (+613/-875)
po/lv.po (+621/-1034)
po/ms.po (+3563/-0)
po/nb.po (+632/-1032)
po/nl.po (+359/-784)
po/nn.po (+364/-772)
po/oc.po (+3591/-0)
po/pa.po (+621/-898)
po/pl.po (+557/-967)
po/pt.po (+541/-758)
po/pt_BR.po (+607/-1009)
po/ro.po (+539/-771)
po/ru.po (+328/-504)
po/sk.po (+642/-1058)
po/sq.po (+646/-1072)
po/sr.po (+577/-765)
po/sv.po (+717/-1142)
po/te.po (+720/-834)
po/th.po (+3564/-0)
po/tr.po (+749/-1141)
po/ug.po (+577/-816)
po/uk.po (+542/-903)
po/ur.po (+645/-1036)
po/ur_PK.po (+645/-1036)
po/vi.po (+1027/-1225)
po/zh_CN.po (+543/-675)
po/zh_HK.po (+3551/-0)
po/zh_TW.po (+599/-896)
test-driver (+16/-4)
thunar.appdata.xml.in (+24/-0)
thunar/Makefile.in (+49/-19)
thunar/main.c (+4/-4)
thunar/thunar-create-dialog.c (+1/-1)
thunar/thunar-dialogs.c (+6/-4)
thunar/thunar-dnd.c (+1/-1)
thunar/thunar-file.c (+135/-50)
thunar/thunar-file.h (+141/-139)
thunar/thunar-folder.c (+7/-2)
thunar/thunar-gio-extensions.c (+14/-7)
thunar/thunar-history.c (+2/-0)
thunar/thunar-icon-renderer.c (+43/-2)
thunar/thunar-io-jobs-util.c (+39/-39)
thunar/thunar-list-model.c (+85/-6)
thunar/thunar-preferences-dialog.c (+7/-1)
thunar/thunar-preferences.c (+13/-0)
thunar/thunar-properties-dialog.c (+2/-4)
thunar/thunar-renamer-model.c (+3/-4)
thunar/thunar-session-client.c (+1/-0)
thunar/thunar-size-label.c (+22/-9)
thunar/thunar-standard-view.c (+9/-2)
thunar/thunar-text-renderer.c (+2/-1)
thunar/thunar-thumbnail-cache.c (+128/-128)
thunar/thunar-thumbnailer.c (+2/-0)
thunar/thunar-transfer-job.c (+30/-17)
thunar/thunar-tree-view.c (+1/-0)
thunar/thunar-util.c (+112/-0)
thunar/thunar-util.h (+2/-0)
thunarx/Makefile.in (+50/-20)
thunarx/thunarx-config.h (+1/-1)
To merge this branch: bzr merge lp:~noskcaj/ubuntu/vivid/thunar/1.6.4
Reviewer Review Type Date Requested Status
Daniel Holbach 2015-01-04 Needs Fixing on 2015-01-06
Review via email: mp+245533@code.launchpad.net

Description of the change

New upstream release. Xubuntu 15.04

To post a comment you must log in.
100. By Jackson Doak on 2015-01-04

Install appdata and polkit files in thunar deb

Daniel Holbach (dholbach) wrote :

It'd be really nice if you could explain in d/changelog why the patches are dropped.

review: Needs Fixing
101. By Jackson Doak on 2015-01-06

  02_fix-default-application-selection.patch, fixed upstream

Unmerged revisions

101. By Jackson Doak on 2015-01-06

  02_fix-default-application-selection.patch, fixed upstream

100. By Jackson Doak on 2015-01-04

Install appdata and polkit files in thunar deb

99. By Jackson Doak on 2015-01-04

* New upstream release.
* Dropped patches: git-force-toolbr-icons.patch, gtk3-bookmarks.patch,
  git-save-keyboard-shortcuts.patch, git-xfdesktop-4.11.patch,
  02_fix-default-application-selection.patch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed directory '.pc/02_fix-default-application-selection.patch'
2=== removed directory '.pc/02_fix-default-application-selection.patch/thunar'
3=== removed file '.pc/02_fix-default-application-selection.patch/thunar/thunar-file.c'
4--- .pc/02_fix-default-application-selection.patch/thunar/thunar-file.c 2014-10-30 11:00:02 +0000
5+++ .pc/02_fix-default-application-selection.patch/thunar/thunar-file.c 1970-01-01 00:00:00 +0000
6@@ -1,4064 +0,0 @@
7-/* vi:set et ai sw=2 sts=2 ts=2: */
8-/*-
9- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org>
10- * Copyright (c) 2009-2011 Jannis Pohlmann <jannis@xfce.org>
11- *
12- * This program is free software; you can redistribute it and/or
13- * modify it under the terms of the GNU General Public License as
14- * published by the Free Software Foundation; either version 2 of
15- * the License, or (at your option) any later version.
16- *
17- * This program is distributed in the hope that it will be useful,
18- * but WITHOUT ANY WARRANTY; without even the implied warranty of
19- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20- * GNU General Public License for more details.
21- *
22- * You should have received a copy of the GNU General Public
23- * License along with this program; if not, write to the Free
24- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25- * Boston, MA 02110-1301, USA.
26- */
27-
28-#ifdef HAVE_CONFIG_H
29-#include <config.h>
30-#endif
31-
32-#ifdef HAVE_SYS_TYPES_H
33-#include <sys/types.h>
34-#endif
35-
36-#ifdef HAVE_SYS_STAT_H
37-#include <sys/stat.h>
38-#endif
39-
40-#ifdef HAVE_ERRNO_H
41-#include <errno.h>
42-#endif
43-#ifdef HAVE_MEMORY_H
44-#include <memory.h>
45-#endif
46-#ifdef HAVE_STDLIB_H
47-#include <stdlib.h>
48-#endif
49-#ifdef HAVE_STRING_H
50-#include <string.h>
51-#endif
52-#ifdef HAVE_TIME_H
53-#include <time.h>
54-#endif
55-#ifdef HAVE_UNISTD_H
56-#include <unistd.h>
57-#endif
58-
59-#include <gio/gio.h>
60-#include <libxfce4ui/libxfce4ui.h>
61-
62-#include <thunarx/thunarx.h>
63-
64-#include <thunar/thunar-application.h>
65-#include <thunar/thunar-chooser-dialog.h>
66-#include <thunar/thunar-exec.h>
67-#include <thunar/thunar-file.h>
68-#include <thunar/thunar-file-monitor.h>
69-#include <thunar/thunar-gio-extensions.h>
70-#include <thunar/thunar-gobject-extensions.h>
71-#include <thunar/thunar-private.h>
72-#include <thunar/thunar-user.h>
73-#include <thunar/thunar-util.h>
74-#include <thunar/thunar-dialogs.h>
75-#include <thunar/thunar-icon-factory.h>
76-
77-
78-
79-/* Dump the file cache every X second, set to 0 to disable */
80-#define DUMP_FILE_CACHE 0
81-
82-
83-
84-/* Signal identifiers */
85-enum
86-{
87- DESTROY,
88- LAST_SIGNAL,
89-};
90-
91-
92-
93-static void thunar_file_info_init (ThunarxFileInfoIface *iface);
94-static void thunar_file_dispose (GObject *object);
95-static void thunar_file_finalize (GObject *object);
96-static gchar *thunar_file_info_get_name (ThunarxFileInfo *file_info);
97-static gchar *thunar_file_info_get_uri (ThunarxFileInfo *file_info);
98-static gchar *thunar_file_info_get_parent_uri (ThunarxFileInfo *file_info);
99-static gchar *thunar_file_info_get_uri_scheme (ThunarxFileInfo *file_info);
100-static gchar *thunar_file_info_get_mime_type (ThunarxFileInfo *file_info);
101-static gboolean thunar_file_info_has_mime_type (ThunarxFileInfo *file_info,
102- const gchar *mime_type);
103-static gboolean thunar_file_info_is_directory (ThunarxFileInfo *file_info);
104-static GFileInfo *thunar_file_info_get_file_info (ThunarxFileInfo *file_info);
105-static GFileInfo *thunar_file_info_get_filesystem_info (ThunarxFileInfo *file_info);
106-static GFile *thunar_file_info_get_location (ThunarxFileInfo *file_info);
107-static void thunar_file_info_changed (ThunarxFileInfo *file_info);
108-static gboolean thunar_file_denies_access_permission (const ThunarFile *file,
109- ThunarFileMode usr_permissions,
110- ThunarFileMode grp_permissions,
111- ThunarFileMode oth_permissions);
112-static void thunar_file_monitor (GFileMonitor *monitor,
113- GFile *path,
114- GFile *other_path,
115- GFileMonitorEvent event_type,
116- gpointer user_data);
117-static gboolean thunar_file_load (ThunarFile *file,
118- GCancellable *cancellable,
119- GError **error);
120-static gboolean thunar_file_is_readable (const ThunarFile *file);
121-static gboolean thunar_file_same_filesystem (const ThunarFile *file_a,
122- const ThunarFile *file_b);
123-
124-
125-
126-G_LOCK_DEFINE_STATIC (file_cache_mutex);
127-G_LOCK_DEFINE_STATIC (file_content_type_mutex);
128-
129-
130-
131-static ThunarUserManager *user_manager;
132-static GHashTable *file_cache;
133-static guint32 effective_user_id;
134-static GQuark thunar_file_watch_quark;
135-static guint file_signals[LAST_SIGNAL];
136-
137-
138-
139-#define FLAG_SET_THUMB_STATE(file,new_state) G_STMT_START{ (file)->flags = ((file)->flags & ~THUNAR_FILE_FLAG_THUMB_MASK) | (new_state); }G_STMT_END
140-#define FLAG_GET_THUMB_STATE(file) ((file)->flags & THUNAR_FILE_FLAG_THUMB_MASK)
141-#define FLAG_SET(file,flag) G_STMT_START{ ((file)->flags |= (flag)); }G_STMT_END
142-#define FLAG_UNSET(file,flag) G_STMT_START{ ((file)->flags &= ~(flag)); }G_STMT_END
143-#define FLAG_IS_SET(file,flag) (((file)->flags & (flag)) != 0)
144-
145-#define DEFAULT_CONTENT_TYPE "application/octet-stream"
146-
147-
148-
149-typedef enum
150-{
151- THUNAR_FILE_FLAG_THUMB_MASK = 0x03, /* storage for ThunarFileThumbState */
152- THUNAR_FILE_FLAG_IN_DESTRUCTION = 1 << 2, /* for avoiding recursion during destroy */
153- THUNAR_FILE_FLAG_IS_MOUNTED = 1 << 3, /* whether this file is mounted */
154-}
155-ThunarFileFlags;
156-
157-struct _ThunarFileClass
158-{
159- GObjectClass __parent__;
160-
161- /* signals */
162- void (*destroy) (ThunarFile *file);
163-};
164-
165-struct _ThunarFile
166-{
167- GObject __parent__;
168-
169- /* storage for the file information */
170- GFileInfo *info;
171- GFileType kind;
172- GFile *gfile;
173- gchar *content_type;
174- gchar *icon_name;
175-
176- gchar *custom_icon_name;
177- gchar *display_name;
178- gchar *basename;
179- gchar *thumbnail_path;
180-
181- /* sorting */
182- gchar *collate_key;
183- gchar *collate_key_nocase;
184-
185- /* flags for thumbnail state etc */
186- ThunarFileFlags flags;
187-};
188-
189-typedef struct
190-{
191- GFileMonitor *monitor;
192- guint watch_count;
193-}
194-ThunarFileWatch;
195-
196-typedef struct
197-{
198- ThunarFileGetFunc func;
199- gpointer user_data;
200- GCancellable *cancellable;
201-}
202-ThunarFileGetData;
203-
204-static struct
205-{
206- GUserDirectory type;
207- const gchar *icon_name;
208-}
209-thunar_file_dirs[] =
210-{
211- { G_USER_DIRECTORY_DESKTOP, "user-desktop" },
212- { G_USER_DIRECTORY_DOCUMENTS, "folder-documents" },
213- { G_USER_DIRECTORY_DOWNLOAD, "folder-download" },
214- { G_USER_DIRECTORY_MUSIC, "folder-music" },
215- { G_USER_DIRECTORY_PICTURES, "folder-pictures" },
216- { G_USER_DIRECTORY_PUBLIC_SHARE, "folder-publicshare" },
217- { G_USER_DIRECTORY_TEMPLATES, "folder-templates" },
218- { G_USER_DIRECTORY_VIDEOS, "folder-videos" }
219-};
220-
221-
222-
223-G_DEFINE_TYPE_WITH_CODE (ThunarFile, thunar_file, G_TYPE_OBJECT,
224- G_IMPLEMENT_INTERFACE (THUNARX_TYPE_FILE_INFO, thunar_file_info_init))
225-
226-
227-
228-#ifdef G_ENABLE_DEBUG
229-#ifdef HAVE_ATEXIT
230-static gboolean thunar_file_atexit_registered = FALSE;
231-
232-
233-
234-static void
235-thunar_file_atexit_foreach (gpointer key,
236- gpointer value,
237- gpointer user_data)
238-{
239- gchar *uri;
240-
241- uri = g_file_get_uri (key);
242- g_print ("--> %s (%u)\n", uri, G_OBJECT (value)->ref_count);
243- if (G_OBJECT (key)->ref_count > 2)
244- g_print (" GFile (%u)\n", G_OBJECT (key)->ref_count - 2);
245- g_free (uri);
246-}
247-
248-
249-
250-static void
251-thunar_file_atexit (void)
252-{
253- G_LOCK (file_cache_mutex);
254-
255- if (file_cache == NULL || g_hash_table_size (file_cache) == 0)
256- {
257- G_UNLOCK (file_cache_mutex);
258- return;
259- }
260-
261- g_print ("--- Leaked a total of %u ThunarFile objects:\n",
262- g_hash_table_size (file_cache));
263-
264- g_hash_table_foreach (file_cache, thunar_file_atexit_foreach, NULL);
265-
266- g_print ("\n");
267-
268- G_UNLOCK (file_cache_mutex);
269-}
270-#endif
271-#endif
272-
273-
274-
275-#if DUMP_FILE_CACHE
276-static void
277-thunar_file_cache_dump_foreach (gpointer gfile,
278- gpointer value,
279- gpointer user_data)
280-{
281- gchar *name;
282-
283- name = g_file_get_parse_name (G_FILE (gfile));
284- g_print (" %s (%u)\n", name, G_OBJECT (value)->ref_count);
285- g_free (name);
286-}
287-
288-
289-
290-static gboolean
291-thunar_file_cache_dump (gpointer user_data)
292-{
293- G_LOCK (file_cache_mutex);
294-
295- if (file_cache != NULL)
296- {
297- g_print ("--- %d ThunarFile objects in cache:\n",
298- g_hash_table_size (file_cache));
299-
300- g_hash_table_foreach (file_cache, thunar_file_cache_dump_foreach, NULL);
301-
302- g_print ("\n");
303- }
304-
305- G_UNLOCK (file_cache_mutex);
306-
307- return TRUE;
308-}
309-#endif
310-
311-
312-
313-static void
314-thunar_file_class_init (ThunarFileClass *klass)
315-{
316- GObjectClass *gobject_class;
317-
318-#ifdef G_ENABLE_DEBUG
319-#ifdef HAVE_ATEXIT
320- if (G_UNLIKELY (!thunar_file_atexit_registered))
321- {
322- atexit ((void (*)(void)) thunar_file_atexit);
323- thunar_file_atexit_registered = TRUE;
324- }
325-#endif
326-#endif
327-
328-#if DUMP_FILE_CACHE
329- g_timeout_add_seconds (DUMP_FILE_CACHE, thunar_file_cache_dump, NULL);
330-#endif
331-
332- /* pre-allocate the required quarks */
333- thunar_file_watch_quark = g_quark_from_static_string ("thunar-file-watch");
334-
335- /* grab a reference on the user manager */
336- user_manager = thunar_user_manager_get_default ();
337-
338- /* determine the effective user id of the process */
339- effective_user_id = geteuid ();
340-
341- gobject_class = G_OBJECT_CLASS (klass);
342- gobject_class->dispose = thunar_file_dispose;
343- gobject_class->finalize = thunar_file_finalize;
344-
345- /**
346- * ThunarFile::destroy:
347- * @file : the #ThunarFile instance.
348- *
349- * Emitted when the system notices that the @file
350- * was destroyed.
351- **/
352- file_signals[DESTROY] =
353- g_signal_new (I_("destroy"),
354- G_TYPE_FROM_CLASS (klass),
355- G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
356- G_STRUCT_OFFSET (ThunarFileClass, destroy),
357- NULL, NULL,
358- g_cclosure_marshal_VOID__VOID,
359- G_TYPE_NONE, 0);
360-}
361-
362-
363-
364-static void
365-thunar_file_init (ThunarFile *file)
366-{
367-}
368-
369-
370-
371-static void
372-thunar_file_info_init (ThunarxFileInfoIface *iface)
373-{
374- iface->get_name = thunar_file_info_get_name;
375- iface->get_uri = thunar_file_info_get_uri;
376- iface->get_parent_uri = thunar_file_info_get_parent_uri;
377- iface->get_uri_scheme = thunar_file_info_get_uri_scheme;
378- iface->get_mime_type = thunar_file_info_get_mime_type;
379- iface->has_mime_type = thunar_file_info_has_mime_type;
380- iface->is_directory = thunar_file_info_is_directory;
381- iface->get_file_info = thunar_file_info_get_file_info;
382- iface->get_filesystem_info = thunar_file_info_get_filesystem_info;
383- iface->get_location = thunar_file_info_get_location;
384- iface->changed = thunar_file_info_changed;
385-}
386-
387-
388-
389-static void
390-thunar_file_dispose (GObject *object)
391-{
392- ThunarFile *file = THUNAR_FILE (object);
393-
394- /* check that we don't recurse here */
395- if (!FLAG_IS_SET (file, THUNAR_FILE_FLAG_IN_DESTRUCTION))
396- {
397- /* emit the "destroy" signal */
398- FLAG_SET (file, THUNAR_FILE_FLAG_IN_DESTRUCTION);
399- g_signal_emit (object, file_signals[DESTROY], 0);
400- FLAG_UNSET (file, THUNAR_FILE_FLAG_IN_DESTRUCTION);
401- }
402-
403- (*G_OBJECT_CLASS (thunar_file_parent_class)->dispose) (object);
404-}
405-
406-
407-
408-static void
409-thunar_file_finalize (GObject *object)
410-{
411- ThunarFile *file = THUNAR_FILE (object);
412-
413- /* verify that nobody's watching the file anymore */
414-#ifdef G_ENABLE_DEBUG
415- ThunarFileWatch *file_watch = g_object_get_qdata (G_OBJECT (file), thunar_file_watch_quark);
416- if (file_watch != NULL)
417- {
418- g_error ("Attempt to finalize a ThunarFile, which has an active "
419- "watch count of %d", file_watch->watch_count);
420- }
421-#endif
422-
423- /* drop the entry from the cache */
424- G_LOCK (file_cache_mutex);
425- g_hash_table_remove (file_cache, file->gfile);
426- G_UNLOCK (file_cache_mutex);
427-
428- /* release file info */
429- if (file->info != NULL)
430- g_object_unref (file->info);
431-
432- /* free the custom icon name */
433- g_free (file->custom_icon_name);
434-
435- /* content type info */
436- g_free (file->content_type);
437- g_free (file->icon_name);
438-
439- /* free display name and basename */
440- g_free (file->display_name);
441- g_free (file->basename);
442-
443- /* free collate keys */
444- if (file->collate_key_nocase != file->collate_key)
445- g_free (file->collate_key_nocase);
446- g_free (file->collate_key);
447-
448- /* free the thumbnail path */
449- g_free (file->thumbnail_path);
450-
451- /* release file */
452- g_object_unref (file->gfile);
453-
454- (*G_OBJECT_CLASS (thunar_file_parent_class)->finalize) (object);
455-}
456-
457-
458-
459-static gchar *
460-thunar_file_info_get_name (ThunarxFileInfo *file_info)
461-{
462- return g_strdup (thunar_file_get_basename (THUNAR_FILE (file_info)));
463-}
464-
465-
466-
467-static gchar*
468-thunar_file_info_get_uri (ThunarxFileInfo *file_info)
469-{
470- return thunar_file_dup_uri (THUNAR_FILE (file_info));
471-}
472-
473-
474-
475-static gchar*
476-thunar_file_info_get_parent_uri (ThunarxFileInfo *file_info)
477-{
478- GFile *parent;
479- gchar *uri = NULL;
480-
481- parent = g_file_get_parent (THUNAR_FILE (file_info)->gfile);
482- if (G_LIKELY (parent != NULL))
483- {
484- uri = g_file_get_uri (parent);
485- g_object_unref (parent);
486- }
487-
488- return uri;
489-}
490-
491-
492-
493-static gchar*
494-thunar_file_info_get_uri_scheme (ThunarxFileInfo *file_info)
495-{
496- return g_file_get_uri_scheme (THUNAR_FILE (file_info)->gfile);
497-}
498-
499-
500-
501-static gchar*
502-thunar_file_info_get_mime_type (ThunarxFileInfo *file_info)
503-{
504- return g_strdup (thunar_file_get_content_type (THUNAR_FILE (file_info)));
505-}
506-
507-
508-
509-static gboolean
510-thunar_file_info_has_mime_type (ThunarxFileInfo *file_info,
511- const gchar *mime_type)
512-{
513- if (THUNAR_FILE (file_info)->info == NULL)
514- return FALSE;
515-
516- return g_content_type_is_a (thunar_file_get_content_type (THUNAR_FILE (file_info)), mime_type);
517-}
518-
519-
520-
521-static gboolean
522-thunar_file_info_is_directory (ThunarxFileInfo *file_info)
523-{
524- return thunar_file_is_directory (THUNAR_FILE (file_info));
525-}
526-
527-
528-
529-static GFileInfo *
530-thunar_file_info_get_file_info (ThunarxFileInfo *file_info)
531-{
532- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_info), NULL);
533-
534- if (THUNAR_FILE (file_info)->info != NULL)
535- return g_object_ref (THUNAR_FILE (file_info)->info);
536- else
537- return NULL;
538-}
539-
540-
541-
542-static GFileInfo *
543-thunar_file_info_get_filesystem_info (ThunarxFileInfo *file_info)
544-{
545- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_info), NULL);
546-
547- return g_file_query_filesystem_info (THUNAR_FILE (file_info)->gfile,
548- THUNARX_FILESYSTEM_INFO_NAMESPACE,
549- NULL, NULL);
550-}
551-
552-
553-
554-static GFile *
555-thunar_file_info_get_location (ThunarxFileInfo *file_info)
556-{
557- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_info), NULL);
558- return g_object_ref (THUNAR_FILE (file_info)->gfile);
559-}
560-
561-
562-
563-static void
564-thunar_file_info_changed (ThunarxFileInfo *file_info)
565-{
566- ThunarFile *file = THUNAR_FILE (file_info);
567-
568- _thunar_return_if_fail (THUNAR_IS_FILE (file_info));
569-
570- /* set the new thumbnail state manually, so we only emit file
571- * changed once */
572- FLAG_SET_THUMB_STATE (file, THUNAR_FILE_THUMB_STATE_UNKNOWN);
573-
574- /* tell the file monitor that this file changed */
575- thunar_file_monitor_file_changed (file);
576-}
577-
578-
579-
580-static gboolean
581-thunar_file_denies_access_permission (const ThunarFile *file,
582- ThunarFileMode usr_permissions,
583- ThunarFileMode grp_permissions,
584- ThunarFileMode oth_permissions)
585-{
586- ThunarFileMode mode;
587- ThunarGroup *group;
588- ThunarUser *user;
589- gboolean result;
590- GList *groups;
591- GList *lp;
592-
593- /* query the file mode */
594- mode = thunar_file_get_mode (file);
595-
596- /* query the owner of the file, if we cannot determine
597- * the owner, we can't tell if we're denied to access
598- * the file, so we simply return FALSE then.
599- */
600- user = thunar_file_get_user (file);
601- if (G_UNLIKELY (user == NULL))
602- return FALSE;
603-
604- /* root is allowed to do everything */
605- if (G_UNLIKELY (effective_user_id == 0))
606- return FALSE;
607-
608- if (thunar_user_is_me (user))
609- {
610- /* we're the owner, so the usr permissions must be granted */
611- result = ((mode & usr_permissions) == 0);
612-
613- /* release the user */
614- g_object_unref (G_OBJECT (user));
615- }
616- else
617- {
618- group = thunar_file_get_group (file);
619- if (G_LIKELY (group != NULL))
620- {
621- /* release the file owner */
622- g_object_unref (G_OBJECT (user));
623-
624- /* determine the effective user */
625- user = thunar_user_manager_get_user_by_id (user_manager, effective_user_id);
626- if (G_LIKELY (user != NULL))
627- {
628- /* check the group permissions */
629- groups = thunar_user_get_groups (user);
630- for (lp = groups; lp != NULL; lp = lp->next)
631- if (THUNAR_GROUP (lp->data) == group)
632- {
633- g_object_unref (G_OBJECT (user));
634- g_object_unref (G_OBJECT (group));
635- return ((mode & grp_permissions) == 0);
636- }
637-
638- /* release the effective user */
639- g_object_unref (G_OBJECT (user));
640- }
641-
642- /* release the file group */
643- g_object_unref (G_OBJECT (group));
644- }
645-
646- /* check other permissions */
647- result = ((mode & oth_permissions) == 0);
648- }
649-
650- return result;
651-}
652-
653-
654-
655-static void
656-thunar_file_monitor_update (GFile *path,
657- GFileMonitorEvent event_type)
658-{
659- ThunarFile *file;
660-
661- _thunar_return_if_fail (G_IS_FILE (path));
662- file = thunar_file_cache_lookup (path);
663- if (G_LIKELY (file != NULL))
664- {
665- switch (event_type)
666- {
667- case G_FILE_MONITOR_EVENT_CREATED:
668- case G_FILE_MONITOR_EVENT_CHANGED:
669- case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
670- thunar_file_reload (file);
671- break;
672-
673- case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
674- case G_FILE_MONITOR_EVENT_DELETED:
675- thunar_file_reload (file);
676- break;
677-
678- default:
679- break;
680- }
681- }
682-}
683-
684-
685-
686-static void
687-thunar_file_monitor (GFileMonitor *monitor,
688- GFile *path,
689- GFile *other_path,
690- GFileMonitorEvent event_type,
691- gpointer user_data)
692-{
693- ThunarFile *file = THUNAR_FILE (user_data);
694-
695- _thunar_return_if_fail (G_IS_FILE_MONITOR (monitor));
696- _thunar_return_if_fail (THUNAR_IS_FILE (file));
697-
698- if (G_UNLIKELY (!G_IS_FILE (path) || !g_file_equal (path, file->gfile)))
699- return;
700-
701- if (G_LIKELY (G_IS_FILE (path)))
702- thunar_file_monitor_update (path, event_type);
703-
704- if (G_UNLIKELY (G_IS_FILE (other_path)))
705- thunar_file_monitor_update (other_path, event_type);
706-}
707-
708-
709-
710-static void
711-thunar_file_watch_destroyed (gpointer data)
712-{
713- ThunarFileWatch *file_watch = data;
714-
715- if (G_LIKELY (file_watch->monitor != NULL))
716- {
717- g_file_monitor_cancel (file_watch->monitor);
718- g_object_unref (file_watch->monitor);
719- }
720-
721- g_slice_free (ThunarFileWatch, file_watch);
722-}
723-
724-
725-
726-static void
727-thunar_file_watch_reconnect (ThunarFile *file)
728-{
729- ThunarFileWatch *file_watch;
730-
731- /* recreate the monitor without changing the watch_count for file renames */
732- file_watch = g_object_get_qdata (G_OBJECT (file), thunar_file_watch_quark);
733- if (file_watch != NULL)
734- {
735- /* reset the old monitor */
736- if (G_LIKELY (file_watch->monitor != NULL))
737- {
738- g_file_monitor_cancel (file_watch->monitor);
739- g_object_unref (file_watch->monitor);
740- }
741-
742- /* create a file or directory monitor */
743- file_watch->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
744- if (G_LIKELY (file_watch->monitor != NULL))
745- {
746- /* watch monitor for file changes */
747- g_signal_connect (file_watch->monitor, "changed", G_CALLBACK (thunar_file_monitor), file);
748- }
749- }
750-}
751-
752-
753-
754-static void
755-thunar_file_set_emblem_names_ready (GObject *source_object,
756- GAsyncResult *result,
757- gpointer user_data)
758-{
759- ThunarFile *file = THUNAR_FILE (user_data);
760- GError *error = NULL;
761-
762- if (!g_file_set_attributes_finish (G_FILE (source_object), result, NULL, &error))
763- {
764- g_warning ("Failed to set metadata: %s", error->message);
765- g_error_free (error);
766-
767- g_file_info_remove_attribute (file->info, "metadata::emblems");
768- }
769-
770- thunar_file_changed (file);
771-}
772-
773-
774-
775-static void
776-thunar_file_info_clear (ThunarFile *file)
777-{
778- _thunar_return_if_fail (THUNAR_IS_FILE (file));
779-
780- /* release the current file info */
781- if (file->info != NULL)
782- {
783- g_object_unref (file->info);
784- file->info = NULL;
785- }
786-
787- /* unset */
788- file->kind = G_FILE_TYPE_UNKNOWN;
789-
790- /* free the custom icon name */
791- g_free (file->custom_icon_name);
792- file->custom_icon_name = NULL;
793-
794- /* free display name and basename */
795- g_free (file->display_name);
796- file->display_name = NULL;
797-
798- g_free (file->basename);
799- file->basename = NULL;
800-
801- /* content type */
802- g_free (file->content_type);
803- file->content_type = NULL;
804- g_free (file->icon_name);
805- file->icon_name = NULL;
806-
807- /* free collate keys */
808- if (file->collate_key_nocase != file->collate_key)
809- g_free (file->collate_key_nocase);
810- file->collate_key_nocase = NULL;
811-
812- g_free (file->collate_key);
813- file->collate_key = NULL;
814-
815- /* free thumbnail path */
816- g_free (file->thumbnail_path);
817- file->thumbnail_path = NULL;
818-
819- /* assume the file is mounted by default */
820- FLAG_SET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
821-
822- /* set thumb state to unknown */
823- FLAG_SET_THUMB_STATE (file, THUNAR_FILE_THUMB_STATE_UNKNOWN);
824-}
825-
826-
827-
828-static void
829-thunar_file_info_reload (ThunarFile *file,
830- GCancellable *cancellable)
831-{
832- const gchar *target_uri;
833- GKeyFile *key_file;
834- gchar *p;
835- const gchar *display_name;
836- gboolean is_secure = FALSE;
837- gchar *casefold;
838- gchar *path;
839-
840- _thunar_return_if_fail (THUNAR_IS_FILE (file));
841- _thunar_return_if_fail (file->info == NULL || G_IS_FILE_INFO (file->info));
842-
843- if (G_LIKELY (file->info != NULL))
844- {
845- /* this is requesed so often, cache it */
846- file->kind = g_file_info_get_file_type (file->info);
847-
848- if (file->kind == G_FILE_TYPE_MOUNTABLE)
849- {
850- target_uri = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
851- if (target_uri != NULL
852- && !g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT))
853- FLAG_SET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
854- else
855- FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
856- }
857- }
858-
859- /* determine the basename */
860- file->basename = g_file_get_basename (file->gfile);
861- _thunar_assert (file->basename != NULL);
862-
863- /* problematic files with content type reading */
864- if (strcmp (file->basename, "kmsg") == 0
865- && g_file_is_native (file->gfile))
866- {
867- path = g_file_get_path (file->gfile);
868- if (g_strcmp0 (path, "/proc/kmsg") == 0)
869- file->content_type = g_strdup (DEFAULT_CONTENT_TYPE);
870- g_free (path);
871- }
872-
873- /* check if this file is a desktop entry */
874- if (thunar_file_is_desktop_file (file, &is_secure) && is_secure)
875- {
876- /* determine the custom icon and display name for .desktop files */
877-
878- /* query a key file for the .desktop file */
879- key_file = thunar_g_file_query_key_file (file->gfile, cancellable, NULL);
880- if (key_file != NULL)
881- {
882- /* read the icon name from the .desktop file */
883- file->custom_icon_name = g_key_file_get_string (key_file,
884- G_KEY_FILE_DESKTOP_GROUP,
885- G_KEY_FILE_DESKTOP_KEY_ICON,
886- NULL);
887-
888- if (G_UNLIKELY (exo_str_is_empty (file->custom_icon_name)))
889- {
890- /* make sure we set null if the string is empty else the assertion in
891- * thunar_icon_factory_lookup_icon() will fail */
892- g_free (file->custom_icon_name);
893- file->custom_icon_name = NULL;
894- }
895- else
896- {
897- /* drop any suffix (e.g. '.png') from themed icons */
898- if (!g_path_is_absolute (file->custom_icon_name))
899- {
900- p = strrchr (file->custom_icon_name, '.');
901- if (p != NULL)
902- *p = '\0';
903- }
904- }
905-
906- /* read the display name from the .desktop file (will be overwritten later
907- * if it's undefined here) */
908- file->display_name = g_key_file_get_locale_string (key_file,
909- G_KEY_FILE_DESKTOP_GROUP,
910- G_KEY_FILE_DESKTOP_KEY_NAME,
911- NULL, NULL);
912-
913- /* drop the name if it's empty or has invalid encoding */
914- if (exo_str_is_empty (file->display_name)
915- || !g_utf8_validate (file->display_name, -1, NULL))
916- {
917- g_free (file->display_name);
918- file->display_name = NULL;
919- }
920-
921- /* free the key file */
922- g_key_file_free (key_file);
923- }
924- }
925-
926- /* determine the display name */
927- if (file->display_name == NULL)
928- {
929- if (G_LIKELY (file->info != NULL))
930- {
931- display_name = g_file_info_get_display_name (file->info);
932- if (G_LIKELY (display_name != NULL))
933- {
934- if (strcmp (display_name, "/") == 0)
935- file->display_name = g_strdup (_("File System"));
936- else
937- file->display_name = g_strdup (display_name);
938- }
939- }
940-
941- /* faccl back to a name for the gfile */
942- if (file->display_name == NULL)
943- file->display_name = thunar_g_file_get_display_name (file->gfile);
944- }
945-
946- /* create case sensitive collation key */
947- file->collate_key = g_utf8_collate_key_for_filename (file->display_name, -1);
948-
949- /* lowercase the display name */
950- casefold = g_utf8_casefold (file->display_name, -1);
951-
952- /* if the lowercase name is equal, only peek the already hash key */
953- if (casefold != NULL && strcmp (casefold, file->display_name) != 0)
954- file->collate_key_nocase = g_utf8_collate_key_for_filename (casefold, -1);
955- else
956- file->collate_key_nocase = file->collate_key;
957-
958- /* cleanup */
959- g_free (casefold);
960-}
961-
962-
963-
964-static void
965-thunar_file_get_async_finish (GObject *object,
966- GAsyncResult *result,
967- gpointer user_data)
968-{
969- ThunarFileGetData *data = user_data;
970- ThunarFile *file;
971- GFileInfo *file_info;
972- GError *error = NULL;
973- GFile *location = G_FILE (object);
974-
975- _thunar_return_if_fail (G_IS_FILE (location));
976- _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
977-
978- /* finish querying the file information */
979- file_info = g_file_query_info_finish (location, result, &error);
980-
981- /* allocate a new file object */
982- file = g_object_new (THUNAR_TYPE_FILE, NULL);
983- file->gfile = g_object_ref (location);
984-
985- /* reset the file */
986- thunar_file_info_clear (file);
987-
988- /* set the file information */
989- file->info = file_info;
990-
991- /* update the file from the information */
992- thunar_file_info_reload (file, data->cancellable);
993-
994- /* update the mounted info */
995- if (error != NULL
996- && error->domain == G_IO_ERROR
997- && error->code == G_IO_ERROR_NOT_MOUNTED)
998- {
999- FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
1000- g_clear_error (&error);
1001- }
1002-
1003- /* insert the file into the cache */
1004- G_LOCK (file_cache_mutex);
1005-#ifdef G_ENABLE_DEBUG
1006- /* check if there is no instance created in the meantime */
1007- _thunar_assert (g_hash_table_lookup (file_cache, file->gfile) == NULL);
1008-#endif
1009- g_hash_table_insert (file_cache, g_object_ref (file->gfile), file);
1010- G_UNLOCK (file_cache_mutex);
1011-
1012- /* pass the loaded file and possible errors to the return function */
1013- (data->func) (location, file, error, data->user_data);
1014-
1015- /* release the file, see description in ThunarFileGetFunc */
1016- g_object_unref (file);
1017-
1018- /* free the error, if there is any */
1019- if (error != NULL)
1020- g_error_free (error);
1021-
1022- /* release the get data */
1023- if (data->cancellable != NULL)
1024- g_object_unref (data->cancellable);
1025- g_slice_free (ThunarFileGetData, data);
1026-}
1027-
1028-
1029-
1030-/**
1031- * thunar_file_load:
1032- * @file : a #ThunarFile.
1033- * @cancellable : a #GCancellable.
1034- * @error : return location for errors or %NULL.
1035- *
1036- * Loads all information about the file. As this is a possibly
1037- * blocking call, it can be cancelled using @cancellable.
1038- *
1039- * If loading the file fails or the operation is cancelled,
1040- * @error will be set.
1041- *
1042- * Return value: %TRUE on success, %FALSE on error or interruption.
1043- **/
1044-static gboolean
1045-thunar_file_load (ThunarFile *file,
1046- GCancellable *cancellable,
1047- GError **error)
1048-{
1049- GError *err = NULL;
1050-
1051- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
1052- _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1053- _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1054- _thunar_return_val_if_fail (G_IS_FILE (file->gfile), FALSE);
1055-
1056- /* reset the file */
1057- thunar_file_info_clear (file);
1058-
1059- /* query a new file info */
1060- file->info = g_file_query_info (file->gfile,
1061- THUNARX_FILE_INFO_NAMESPACE,
1062- G_FILE_QUERY_INFO_NONE,
1063- cancellable, &err);
1064-
1065- /* update the file from the information */
1066- thunar_file_info_reload (file, cancellable);
1067-
1068- /* update the mounted info */
1069- if (err != NULL
1070- && err->domain == G_IO_ERROR
1071- && err->code == G_IO_ERROR_NOT_MOUNTED)
1072- {
1073- FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
1074- g_clear_error (&err);
1075- }
1076-
1077- if (err != NULL)
1078- {
1079- g_propagate_error (error, err);
1080- return FALSE;
1081- }
1082- else
1083- {
1084- return TRUE;
1085- }
1086-}
1087-
1088-
1089-
1090-/**
1091- * thunar_file_get:
1092- * @file : a #GFile.
1093- * @error : return location for errors.
1094- *
1095- * Looks up the #ThunarFile referred to by @file. This function may return a
1096- * ThunarFile even though the file doesn't actually exist. This is the case
1097- * with remote URIs (like SFTP) for instance, if they are not mounted.
1098- *
1099- * The caller is responsible to call g_object_unref()
1100- * when done with the returned object.
1101- *
1102- * Return value: the #ThunarFile for @file or %NULL on errors.
1103- **/
1104-ThunarFile*
1105-thunar_file_get (GFile *gfile,
1106- GError **error)
1107-{
1108- ThunarFile *file;
1109-
1110- _thunar_return_val_if_fail (G_IS_FILE (gfile), NULL);
1111-
1112- /* check if we already have a cached version of that file */
1113- file = thunar_file_cache_lookup (gfile);
1114- if (G_UNLIKELY (file != NULL))
1115- {
1116- /* take a reference for the caller */
1117- g_object_ref (file);
1118- }
1119- else
1120- {
1121- /* allocate a new object */
1122- file = g_object_new (THUNAR_TYPE_FILE, NULL);
1123- file->gfile = g_object_ref (gfile);
1124-
1125- if (thunar_file_load (file, NULL, error))
1126- {
1127- /* setup lock until the file is inserted */
1128- G_LOCK (file_cache_mutex);
1129-
1130- /* insert the file into the cache */
1131- g_hash_table_insert (file_cache, g_object_ref (file->gfile), file);
1132-
1133- /* done inserting in the cache */
1134- G_UNLOCK (file_cache_mutex);
1135- }
1136- else
1137- {
1138- /* failed loading, destroy the file */
1139- g_object_unref (file);
1140-
1141- /* make sure we return NULL */
1142- file = NULL;
1143- }
1144- }
1145-
1146- return file;
1147-}
1148-
1149-
1150-/**
1151- * thunar_file_get_with_info:
1152- * @uri : an URI or an absolute filename.
1153- * @info : #GFileInfo to use when loading the info.
1154- * @not_mounted : if the file is mounted.
1155- *
1156- * Looks up the #ThunarFile referred to by @file. This function may return a
1157- * ThunarFile even though the file doesn't actually exist. This is the case
1158- * with remote URIs (like SFTP) for instance, if they are not mounted.
1159- *
1160- * This function does not use g_file_query_info() to get the info,
1161- * but takes a reference on the @info,
1162- *
1163- * The caller is responsible to call g_object_unref()
1164- * when done with the returned object.
1165- *
1166- * Return value: the #ThunarFile for @file or %NULL on errors.
1167- **/
1168-ThunarFile *
1169-thunar_file_get_with_info (GFile *gfile,
1170- GFileInfo *info,
1171- gboolean not_mounted)
1172-{
1173- ThunarFile *file;
1174-
1175- _thunar_return_val_if_fail (G_IS_FILE (gfile), NULL);
1176- _thunar_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1177-
1178- /* check if we already have a cached version of that file */
1179- file = thunar_file_cache_lookup (gfile);
1180- if (G_UNLIKELY (file != NULL))
1181- {
1182- /* take a reference for the caller */
1183- g_object_ref (file);
1184- }
1185- else
1186- {
1187- /* allocate a new object */
1188- file = g_object_new (THUNAR_TYPE_FILE, NULL);
1189- file->gfile = g_object_ref (gfile);
1190-
1191- /* reset the file */
1192- thunar_file_info_clear (file);
1193-
1194- /* set the passed info */
1195- file->info = g_object_ref (info);
1196-
1197- /* update the file from the information */
1198- thunar_file_info_reload (file, NULL);
1199-
1200- /* update the mounted info */
1201- if (not_mounted)
1202- FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
1203-
1204- /* setup lock until the file is inserted */
1205- G_LOCK (file_cache_mutex);
1206-
1207- /* insert the file into the cache */
1208- g_hash_table_insert (file_cache, g_object_ref (file->gfile), file);
1209-
1210- /* done inserting in the cache */
1211- G_UNLOCK (file_cache_mutex);
1212- }
1213-
1214- return file;
1215-}
1216-
1217-
1218-
1219-
1220-
1221-/**
1222- * thunar_file_get_for_uri:
1223- * @uri : an URI or an absolute filename.
1224- * @error : return location for errors or %NULL.
1225- *
1226- * Convenience wrapper function for thunar_file_get_for_path(), as its
1227- * often required to determine a #ThunarFile for a given @uri.
1228- *
1229- * The caller is responsible to free the returned object using
1230- * g_object_unref() when no longer needed.
1231- *
1232- * Return value: the #ThunarFile for the given @uri or %NULL if
1233- * unable to determine.
1234- **/
1235-ThunarFile*
1236-thunar_file_get_for_uri (const gchar *uri,
1237- GError **error)
1238-{
1239- ThunarFile *file;
1240- GFile *path;
1241-
1242- _thunar_return_val_if_fail (uri != NULL, NULL);
1243- _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL);
1244-
1245- path = g_file_new_for_commandline_arg (uri);
1246- file = thunar_file_get (path, error);
1247- g_object_unref (path);
1248-
1249- return file;
1250-}
1251-
1252-
1253-
1254-/**
1255- * thunar_file_get_async:
1256- **/
1257-void
1258-thunar_file_get_async (GFile *location,
1259- GCancellable *cancellable,
1260- ThunarFileGetFunc func,
1261- gpointer user_data)
1262-{
1263- ThunarFile *file;
1264- ThunarFileGetData *data;
1265-
1266- _thunar_return_if_fail (G_IS_FILE (location));
1267- _thunar_return_if_fail (func != NULL);
1268-
1269- /* check if we already have a cached version of that file */
1270- file = thunar_file_cache_lookup (location);
1271- if (G_UNLIKELY (file != NULL))
1272- {
1273- /* call the return function with the file from the cache */
1274- (func) (location, file, NULL, user_data);
1275- }
1276- else
1277- {
1278- /* allocate get data */
1279- data = g_slice_new0 (ThunarFileGetData);
1280- data->user_data = user_data;
1281- data->func = func;
1282- if (cancellable != NULL)
1283- data->cancellable = g_object_ref (cancellable);
1284-
1285- /* load the file information asynchronously */
1286- g_file_query_info_async (location,
1287- THUNARX_FILE_INFO_NAMESPACE,
1288- G_FILE_QUERY_INFO_NONE,
1289- G_PRIORITY_DEFAULT,
1290- cancellable,
1291- thunar_file_get_async_finish,
1292- data);
1293- }
1294-}
1295-
1296-
1297-
1298-/**
1299- * thunar_file_get_file:
1300- * @file : a #ThunarFile instance.
1301- *
1302- * Returns the #GFile that refers to the location of @file.
1303- *
1304- * The returned #GFile is owned by @file and must not be released
1305- * with g_object_unref().
1306- *
1307- * Return value: the #GFile corresponding to @file.
1308- **/
1309-GFile *
1310-thunar_file_get_file (const ThunarFile *file)
1311-{
1312- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
1313- _thunar_return_val_if_fail (G_IS_FILE (file->gfile), NULL);
1314- return file->gfile;
1315-}
1316-
1317-
1318-
1319-/**
1320- * thunar_file_get_info:
1321- * @file : a #ThunarFile instance.
1322- *
1323- * Returns the #GFileInfo for @file.
1324- *
1325- * Note, that there's no reference taken for the caller on the
1326- * returned #GFileInfo, so if you need the object for a longer
1327- * perioud, you'll need to take a reference yourself using the
1328- * g_object_ref() method.
1329- *
1330- * Return value: the #GFileInfo for @file or %NULL.
1331- **/
1332-GFileInfo *
1333-thunar_file_get_info (const ThunarFile *file)
1334-{
1335- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
1336- _thunar_return_val_if_fail (file->info == NULL || G_IS_FILE_INFO (file->info), NULL);
1337- return file->info;
1338-}
1339-
1340-
1341-
1342-/**
1343- * thunar_file_get_parent:
1344- * @file : a #ThunarFile instance.
1345- * @error : return location for errors.
1346- *
1347- * Determines the parent #ThunarFile for @file. If @file has no parent or
1348- * the user is not allowed to open the parent folder of @file, %NULL will
1349- * be returned and @error will be set to point to a #GError that
1350- * describes the cause. Else, the #ThunarFile will be returned, and
1351- * the caller must call g_object_unref() on it.
1352- *
1353- * You may want to call thunar_file_has_parent() first to
1354- * determine whether @file has a parent.
1355- *
1356- * Return value: the parent #ThunarFile or %NULL.
1357- **/
1358-ThunarFile*
1359-thunar_file_get_parent (const ThunarFile *file,
1360- GError **error)
1361-{
1362- ThunarFile *parent = NULL;
1363- GFile *parent_file;
1364-
1365- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
1366- _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL);
1367-
1368- parent_file = g_file_get_parent (file->gfile);
1369-
1370- if (parent_file == NULL)
1371- {
1372- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, _("The root folder has no parent"));
1373- return NULL;
1374- }
1375-
1376- parent = thunar_file_get (parent_file, error);
1377- g_object_unref (parent_file);
1378-
1379- return parent;
1380-}
1381-
1382-
1383-
1384-/**
1385- * thunar_file_check_loaded:
1386- * @file : a #ThunarFile instance.
1387- *
1388- * Check if @file has its information loaded, if not, try this once else
1389- * return %FALSE.
1390- *
1391- * Return value: %TRUE on success, else %FALSE.
1392- **/
1393-gboolean
1394-thunar_file_check_loaded (ThunarFile *file)
1395-{
1396- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
1397-
1398- if (G_UNLIKELY (file->info == NULL))
1399- thunar_file_load (file, NULL, NULL);
1400-
1401- return (file->info != NULL);
1402-}
1403-
1404-
1405-
1406-/**
1407- * thunar_file_execute:
1408- * @file : a #ThunarFile instance.
1409- * @working_directory : the working directory used to resolve relative filenames
1410- * in @file_list.
1411- * @parent : %NULL, a #GdkScreen or #GtkWidget.
1412- * @file_list : the list of #GFile<!---->s to supply to @file on execution.
1413- * @error : return location for errors or %NULL.
1414- *
1415- * Tries to execute @file on the specified @screen. If @file is executable
1416- * and could have been spawned successfully, %TRUE is returned, else %FALSE
1417- * will be returned and @error will be set to point to the error location.
1418- *
1419- * Return value: %TRUE on success, else %FALSE.
1420- **/
1421-gboolean
1422-thunar_file_execute (ThunarFile *file,
1423- GFile *working_directory,
1424- gpointer parent,
1425- GList *file_list,
1426- GError **error)
1427-{
1428- gboolean snotify = FALSE;
1429- gboolean terminal;
1430- gboolean result = FALSE;
1431- GKeyFile *key_file;
1432- GError *err = NULL;
1433- GFile *file_parent;
1434- gchar *icon_name = NULL;
1435- gchar *name;
1436- gchar *type;
1437- gchar *url;
1438- gchar *location;
1439- gchar *escaped_location;
1440- gchar **argv = NULL;
1441- gchar *exec;
1442- gchar *directory = NULL;
1443- gboolean is_secure = FALSE;
1444-
1445- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
1446- _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1447-
1448- location = thunar_g_file_get_location (file->gfile);
1449-
1450- if (thunar_file_is_desktop_file (file, &is_secure))
1451- {
1452- /* parse file first, even if it is insecure */
1453- key_file = thunar_g_file_query_key_file (file->gfile, NULL, &err);
1454- if (key_file == NULL)
1455- {
1456- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
1457- _("Failed to parse the desktop file: %s"), err->message);
1458- g_error_free (err);
1459- return FALSE;
1460- }
1461-
1462- type = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TYPE, NULL);
1463- if (G_LIKELY (exo_str_is_equal (type, "Application")))
1464- {
1465- exec = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
1466- if (G_LIKELY (exec != NULL))
1467- {
1468- /* if the .desktop file is not secure, ask user what to do */
1469- if (is_secure || thunar_dialogs_show_insecure_program (parent, _("Untrusted application launcher"), file, exec))
1470- {
1471- /* parse other fields */
1472- name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL, NULL);
1473- icon_name = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, NULL);
1474- directory = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_PATH, NULL);
1475- terminal = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TERMINAL, NULL);
1476- snotify = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY, NULL);
1477-
1478- result = thunar_exec_parse (exec, file_list, icon_name, name, location, terminal, NULL, &argv, error);
1479-
1480- g_free (name);
1481- }
1482- else
1483- {
1484- /* fall-through to free value and leave without execution */
1485- result = TRUE;
1486- }
1487-
1488- g_free (exec);
1489- }
1490- else
1491- {
1492- /* TRANSLATORS: `Exec' is a field name in a .desktop file. Don't translate it. */
1493- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
1494- _("No Exec field specified"));
1495- }
1496- }
1497- else if (exo_str_is_equal (type, "Link"))
1498- {
1499- url = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_URL, NULL);
1500- if (G_LIKELY (url != NULL))
1501- {
1502- /* if the .desktop file is not secure, ask user what to do */
1503- if (is_secure || thunar_dialogs_show_insecure_program (parent, _("Untrusted link launcher"), file, url))
1504- {
1505- /* pass the URL to the webbrowser, this could be a bit strange,
1506- * but then at least we are on the secure side */
1507- argv = g_new (gchar *, 3);
1508- argv[0] = g_strdup ("exo-open");
1509- argv[1] = url;
1510- argv[2] = NULL;
1511- }
1512-
1513- result = TRUE;
1514- }
1515- else
1516- {
1517- /* TRANSLATORS: `URL' is a field name in a .desktop file. Don't translate it. */
1518- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
1519- _("No URL field specified"));
1520- }
1521- }
1522- else
1523- {
1524- g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid desktop file"));
1525- }
1526-
1527- g_free (type);
1528- g_key_file_free (key_file);
1529- }
1530- else
1531- {
1532- /* fake the Exec line */
1533- escaped_location = g_shell_quote (location);
1534- exec = g_strconcat (escaped_location, " %F", NULL);
1535- result = thunar_exec_parse (exec, file_list, NULL, NULL, NULL, FALSE, NULL, &argv, error);
1536- g_free (escaped_location);
1537- g_free (exec);
1538- }
1539-
1540- if (G_LIKELY (result && argv != NULL))
1541- {
1542- /* use other directory if the Path from the desktop file was not set */
1543- if (G_LIKELY (directory == NULL))
1544- {
1545- /* determine the working directory */
1546- if (G_LIKELY (working_directory != NULL))
1547- {
1548- /* copy the working directory provided to this method */
1549- directory = g_file_get_path (working_directory);
1550- }
1551- else if (file_list != NULL)
1552- {
1553- /* use the directory of the first list item */
1554- file_parent = g_file_get_parent (file_list->data);
1555- directory = (file_parent != NULL) ? thunar_g_file_get_location (file_parent) : NULL;
1556- g_object_unref (file_parent);
1557- }
1558- else
1559- {
1560- /* use the directory of the executable file */
1561- parent = g_file_get_parent (file->gfile);
1562- directory = (parent != NULL) ? thunar_g_file_get_location (parent) : NULL;
1563- g_object_unref (parent);
1564- }
1565- }
1566-
1567- /* execute the command */
1568- result = xfce_spawn_on_screen (thunar_util_parse_parent (parent, NULL),
1569- directory, argv, NULL, G_SPAWN_SEARCH_PATH,
1570- snotify, gtk_get_current_event_time (), icon_name, error);
1571- }
1572-
1573- /* clean up */
1574- g_strfreev (argv);
1575- g_free (location);
1576- g_free (directory);
1577- g_free (icon_name);
1578-
1579- return result;
1580-}
1581-
1582-
1583-
1584-/**
1585- * thunar_file_launch:
1586- * @file : a #ThunarFile instance.
1587- * @parent : a #GtkWidget or a #GdkScreen on which to launch the @file.
1588- * May also be %NULL in which case the default #GdkScreen will
1589- * be used.
1590- * @startup_id : startup id for the new window (send over for dbus) or %NULL.
1591- * @error : return location for errors or %NULL.
1592- *
1593- * If @file is an executable file, tries to execute it. Else if @file is
1594- * a directory, opens a new #ThunarWindow to display the directory. Else,
1595- * the default handler for @file is determined and run.
1596- *
1597- * The @parent can be either a #GtkWidget or a #GdkScreen, on which to
1598- * launch the @file. If @parent is a #GtkWidget, the chooser dialog (if
1599- * no default application is available for @file) will be transient for
1600- * @parent. Else if @parent is a #GdkScreen it specifies the screen on
1601- * which to launch @file.
1602- *
1603- * Return value: %TRUE on success, else %FALSE.
1604- **/
1605-gboolean
1606-thunar_file_launch (ThunarFile *file,
1607- gpointer parent,
1608- const gchar *startup_id,
1609- GError **error)
1610-{
1611- GdkAppLaunchContext *context;
1612- ThunarApplication *application;
1613- GAppInfo *app_info;
1614- gboolean succeed;
1615- GList path_list;
1616- GdkScreen *screen;
1617-
1618- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
1619- _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1620- _thunar_return_val_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent), FALSE);
1621-
1622- screen = thunar_util_parse_parent (parent, NULL);
1623-
1624- /* check if we have a folder here */
1625- if (thunar_file_is_directory (file))
1626- {
1627- application = thunar_application_get ();
1628- thunar_application_open_window (application, file, screen, startup_id);
1629- g_object_unref (G_OBJECT (application));
1630- return TRUE;
1631- }
1632-
1633- /* check if we should execute the file */
1634- if (thunar_file_is_executable (file))
1635- return thunar_file_execute (file, NULL, parent, NULL, error);
1636-
1637- /* determine the default application to open the file */
1638- /* TODO We should probably add a cancellable argument to thunar_file_launch() */
1639- app_info = thunar_file_get_default_handler (THUNAR_FILE (file));
1640-
1641- /* display the application chooser if no application is defined for this file
1642- * type yet */
1643- if (G_UNLIKELY (app_info == NULL))
1644- {
1645- thunar_show_chooser_dialog (parent, file, TRUE);
1646- return TRUE;
1647- }
1648-
1649- /* HACK: check if we're not trying to launch another file manager again, possibly
1650- * ourselfs which will end in a loop */
1651- if (g_strcmp0 (g_app_info_get_id (app_info), "exo-file-manager.desktop") == 0
1652- || g_strcmp0 (g_app_info_get_id (app_info), "Thunar.desktop") == 0
1653- || g_strcmp0 (g_app_info_get_name (app_info), "exo-file-manager") == 0)
1654- {
1655- g_object_unref (G_OBJECT (app_info));
1656- thunar_show_chooser_dialog (parent, file, TRUE);
1657- return TRUE;
1658- }
1659-
1660- /* fake a path list */
1661- path_list.data = file->gfile;
1662- path_list.next = path_list.prev = NULL;
1663-
1664- /* create a launch context */
1665- context = gdk_app_launch_context_new ();
1666- gdk_app_launch_context_set_screen (context, screen);
1667- gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());
1668-
1669- /* otherwise try to execute the application */
1670- succeed = g_app_info_launch (app_info, &path_list, G_APP_LAUNCH_CONTEXT (context), error);
1671-
1672- /* destroy the launch context */
1673- g_object_unref (context);
1674-
1675- /* release the handler reference */
1676- g_object_unref (G_OBJECT (app_info));
1677-
1678- return succeed;
1679-}
1680-
1681-
1682-
1683-/**
1684- * thunar_file_rename:
1685- * @file : a #ThunarFile instance.
1686- * @name : the new file name in UTF-8 encoding.
1687- * @error : return location for errors or %NULL.
1688- *
1689- * Tries to rename @file to the new @name. If @file cannot be renamed,
1690- * %FALSE will be returned and @error will be set accordingly. Else, if
1691- * the operation succeeds, %TRUE will be returned, and @file will have
1692- * a new URI and a new display name.
1693- *
1694- * When offering a rename action in the user interface, the implementation
1695- * should first check whether the file is available, using the
1696- * thunar_file_is_renameable() method.
1697- *
1698- * Return value: %TRUE on success, else %FALSE.
1699- **/
1700-gboolean
1701-thunar_file_rename (ThunarFile *file,
1702- const gchar *name,
1703- GCancellable *cancellable,
1704- gboolean called_from_job,
1705- GError **error)
1706-{
1707- ThunarApplication *application;
1708- ThunarThumbnailCache *thumbnail_cache;
1709- GKeyFile *key_file;
1710- GError *err = NULL;
1711- GFile *previous_file;
1712- GFile *renamed_file;
1713- gboolean is_secure;
1714- const gchar * const *languages;
1715- guint i;
1716- gboolean name_set = FALSE;
1717-
1718- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
1719- _thunar_return_val_if_fail (g_utf8_validate (name, -1, NULL), FALSE);
1720- _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
1721- _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1722-
1723- /* check if this file is a desktop entry */
1724- if (thunar_file_is_desktop_file (file, &is_secure)
1725- && is_secure)
1726- {
1727- /* try to load the desktop entry into a key file */
1728- key_file = thunar_g_file_query_key_file (file->gfile, cancellable, &err);
1729- if (key_file == NULL)
1730- {
1731- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL,
1732- _("Failed to parse the desktop file: %s"), err->message);
1733- g_error_free (err);
1734- return FALSE;
1735- }
1736-
1737- /* check if we can set the language name */
1738- languages = g_get_language_names ();
1739- if (languages != NULL)
1740- {
1741- for (i = 0; !name_set && languages[i] != NULL; i++)
1742- {
1743- /* skip C language */
1744- if (g_ascii_strcasecmp (languages[i], "C") == 0)
1745- continue;
1746-
1747- /* change the translated Name field of the desktop entry */
1748- g_key_file_set_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP,
1749- G_KEY_FILE_DESKTOP_KEY_NAME,
1750- languages[i], name);
1751-
1752- /* done */
1753- name_set = TRUE;
1754- }
1755- }
1756-
1757- if (!name_set)
1758- {
1759- /* change the Name field of the desktop entry */
1760- g_key_file_set_string (key_file, G_KEY_FILE_DESKTOP_GROUP,
1761- G_KEY_FILE_DESKTOP_KEY_NAME, name);
1762- }
1763-
1764- /* write the changes back to the file */
1765- if (thunar_g_file_write_key_file (file->gfile, key_file, cancellable, &err))
1766- {
1767- /* reload file information */
1768- thunar_file_load (file, NULL, NULL);
1769-
1770- if (!called_from_job)
1771- {
1772- /* tell the associated folder that the file was renamed */
1773- thunarx_file_info_renamed (THUNARX_FILE_INFO (file));
1774-
1775- /* notify everybody that the file has changed */
1776- thunar_file_changed (file);
1777- }
1778-
1779- /* release the key file and return with success */
1780- g_key_file_free (key_file);
1781- return TRUE;
1782- }
1783- else
1784- {
1785- /* propagate the error message and return with failure */
1786- g_propagate_error (error, err);
1787- g_key_file_free (key_file);
1788- return FALSE;
1789- }
1790- }
1791- else
1792- {
1793- /* remember the previous file */
1794- previous_file = g_object_ref (file->gfile);
1795-
1796- /* try to rename the file */
1797- renamed_file = g_file_set_display_name (file->gfile, name, cancellable, error);
1798-
1799- /* notify the thumbnail cache that we can now also move the thumbnail */
1800- application = thunar_application_get ();
1801- thumbnail_cache = thunar_application_get_thumbnail_cache (application);
1802- thunar_thumbnail_cache_move_file (thumbnail_cache, previous_file, renamed_file);
1803- g_object_unref (thumbnail_cache);
1804- g_object_unref (application);
1805-
1806- /* check if we succeeded */
1807- if (renamed_file != NULL)
1808- {
1809- /* set the new file */
1810- file->gfile = renamed_file;
1811-
1812- /* reload file information */
1813- thunar_file_load (file, NULL, NULL);
1814-
1815- /* need to re-register the monitor handle for the new uri */
1816- thunar_file_watch_reconnect (file);
1817-
1818- G_LOCK (file_cache_mutex);
1819-
1820- /* drop the previous entry from the cache */
1821- g_hash_table_remove (file_cache, previous_file);
1822-
1823- /* drop the reference on the previous file */
1824- g_object_unref (previous_file);
1825-
1826- /* insert the new entry */
1827- g_hash_table_insert (file_cache, g_object_ref (file->gfile), file);
1828-
1829- G_UNLOCK (file_cache_mutex);
1830-
1831- if (!called_from_job)
1832- {
1833- /* tell the associated folder that the file was renamed */
1834- thunarx_file_info_renamed (THUNARX_FILE_INFO (file));
1835-
1836- /* emit the file changed signal */
1837- thunar_file_changed (file);
1838- }
1839-
1840- return TRUE;
1841- }
1842- else
1843- {
1844- g_object_unref (previous_file);
1845-
1846- return FALSE;
1847- }
1848- }
1849-}
1850-
1851-
1852-
1853-/**
1854- * thunar_file_accepts_drop:
1855- * @file : a #ThunarFile instance.
1856- * @file_list : the list of #GFile<!---->s that will be droppped.
1857- * @context : the current #GdkDragContext, which is used for the drop.
1858- * @suggested_action_return : return location for the suggested #GdkDragAction or %NULL.
1859- *
1860- * Checks whether @file can accept @path_list for the given @context and
1861- * returns the #GdkDragAction<!---->s that can be used or 0 if no actions
1862- * apply.
1863- *
1864- * If any #GdkDragAction<!---->s apply and @suggested_action_return is not
1865- * %NULL, the suggested #GdkDragAction for this drop will be stored to the
1866- * location pointed to by @suggested_action_return.
1867- *
1868- * Return value: the #GdkDragAction<!---->s supported for the drop or
1869- * 0 if no drop is possible.
1870- **/
1871-GdkDragAction
1872-thunar_file_accepts_drop (ThunarFile *file,
1873- GList *file_list,
1874- GdkDragContext *context,
1875- GdkDragAction *suggested_action_return)
1876-{
1877- GdkDragAction suggested_action;
1878- GdkDragAction actions;
1879- ThunarFile *ofile;
1880- GFile *parent_file;
1881- GList *lp;
1882- guint n;
1883-
1884- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0);
1885- _thunar_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), 0);
1886-
1887- /* we can never drop an empty list */
1888- if (G_UNLIKELY (file_list == NULL))
1889- return 0;
1890-
1891- /* default to whatever GTK+ thinks for the suggested action */
1892- suggested_action = context->suggested_action;
1893-
1894- /* check if we have a writable directory here or an executable file */
1895- if (thunar_file_is_directory (file) && thunar_file_is_writable (file))
1896- {
1897- /* determine the possible actions */
1898- actions = context->actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
1899-
1900- /* cannot create symbolic links in the trash or copy to the trash */
1901- if (thunar_file_is_trashed (file))
1902- actions &= ~(GDK_ACTION_COPY | GDK_ACTION_LINK);
1903-
1904- /* check up to 100 of the paths (just in case somebody tries to
1905- * drag around his music collection with 5000 files).
1906- */
1907- for (lp = file_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n)
1908- {
1909- /* we cannot drop a file on itself */
1910- if (G_UNLIKELY (g_file_equal (file->gfile, lp->data)))
1911- return 0;
1912-
1913- /* check whether source and destination are the same */
1914- parent_file = g_file_get_parent (lp->data);
1915- if (G_LIKELY (parent_file != NULL))
1916- {
1917- if (g_file_equal (file->gfile, parent_file))
1918- {
1919- g_object_unref (parent_file);
1920- return 0;
1921- }
1922- else
1923- g_object_unref (parent_file);
1924- }
1925-
1926- /* copy/move/link within the trash not possible */
1927- if (G_UNLIKELY (thunar_g_file_is_trashed (lp->data) && thunar_file_is_trashed (file)))
1928- return 0;
1929- }
1930-
1931- /* if the source offers both copy and move and the GTK+ suggested action is copy, try to be smart telling whether
1932- * we should copy or move by default by checking whether the source and target are on the same disk.
1933- */
1934- if ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE)) != 0
1935- && (suggested_action == GDK_ACTION_COPY))
1936- {
1937- /* default to move as suggested action */
1938- suggested_action = GDK_ACTION_MOVE;
1939-
1940- /* check for up to 100 files, for the reason state above */
1941- for (lp = file_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n)
1942- {
1943- /* dropping from the trash always suggests move */
1944- if (G_UNLIKELY (thunar_g_file_is_trashed (lp->data)))
1945- break;
1946-
1947- /* determine the cached version of the source file */
1948- ofile = thunar_file_cache_lookup (lp->data);
1949-
1950- /* we have only move if we know the source and both the source and the target
1951- * are on the same disk, and the source file is owned by the current user.
1952- */
1953- if (ofile == NULL
1954- || !thunar_file_same_filesystem (file, ofile)
1955- || (ofile->info != NULL
1956- && g_file_info_get_attribute_uint32 (ofile->info,
1957- G_FILE_ATTRIBUTE_UNIX_UID) != effective_user_id))
1958- {
1959- /* default to copy and get outa here */
1960- suggested_action = GDK_ACTION_COPY;
1961- break;
1962- }
1963- }
1964- }
1965- }
1966- else if (thunar_file_is_executable (file))
1967- {
1968- /* determine the possible actions */
1969- actions = context->actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE);
1970- }
1971- else
1972- return 0;
1973-
1974- /* determine the preferred action based on the context */
1975- if (G_LIKELY (suggested_action_return != NULL))
1976- {
1977- /* determine a working action */
1978- if (G_LIKELY ((suggested_action & actions) != 0))
1979- *suggested_action_return = suggested_action;
1980- else if ((actions & GDK_ACTION_ASK) != 0)
1981- *suggested_action_return = GDK_ACTION_ASK;
1982- else if ((actions & GDK_ACTION_COPY) != 0)
1983- *suggested_action_return = GDK_ACTION_COPY;
1984- else if ((actions & GDK_ACTION_LINK) != 0)
1985- *suggested_action_return = GDK_ACTION_LINK;
1986- else if ((actions & GDK_ACTION_MOVE) != 0)
1987- *suggested_action_return = GDK_ACTION_MOVE;
1988- else
1989- *suggested_action_return = GDK_ACTION_PRIVATE;
1990- }
1991-
1992- /* yeppa, we can drop here */
1993- return actions;
1994-}
1995-
1996-
1997-
1998-/**
1999- * thunar_file_get_date:
2000- * @file : a #ThunarFile instance.
2001- * @date_type : the kind of date you are interested in.
2002- *
2003- * Queries the given @date_type from @file and returns the result.
2004- *
2005- * Return value: the time for @file of the given @date_type.
2006- **/
2007-guint64
2008-thunar_file_get_date (const ThunarFile *file,
2009- ThunarFileDateType date_type)
2010-{
2011- const gchar *attribute;
2012-
2013- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0);
2014-
2015- if (file->info == NULL)
2016- return 0;
2017-
2018- switch (date_type)
2019- {
2020- case THUNAR_FILE_DATE_ACCESSED:
2021- attribute = G_FILE_ATTRIBUTE_TIME_ACCESS;
2022- break;
2023- case THUNAR_FILE_DATE_CHANGED:
2024- attribute = G_FILE_ATTRIBUTE_TIME_CHANGED;
2025- break;
2026- case THUNAR_FILE_DATE_MODIFIED:
2027- attribute = G_FILE_ATTRIBUTE_TIME_MODIFIED;
2028- break;
2029- default:
2030- _thunar_assert_not_reached ();
2031- }
2032-
2033- return g_file_info_get_attribute_uint64 (file->info, attribute);
2034-}
2035-
2036-
2037-
2038-/**
2039- * thunar_file_get_date_string:
2040- * @file : a #ThunarFile instance.
2041- * @date_type : the kind of date you are interested to know about @file.
2042- * @date_style : the style used to format the date.
2043- *
2044- * Tries to determine the @date_type of @file, and if @file supports the
2045- * given @date_type, it'll be formatted as string and returned. The
2046- * caller is responsible for freeing the string using the g_free()
2047- * function.
2048- *
2049- * Return value: the @date_type of @file formatted as string.
2050- **/
2051-gchar*
2052-thunar_file_get_date_string (const ThunarFile *file,
2053- ThunarFileDateType date_type,
2054- ThunarDateStyle date_style)
2055-{
2056- return thunar_util_humanize_file_time (thunar_file_get_date (file, date_type), date_style);
2057-}
2058-
2059-
2060-
2061-/**
2062- * thunar_file_get_mode_string:
2063- * @file : a #ThunarFile instance.
2064- *
2065- * Returns the mode of @file as text. You'll need to free
2066- * the result using g_free() when you're done with it.
2067- *
2068- * Return value: the mode of @file as string.
2069- **/
2070-gchar*
2071-thunar_file_get_mode_string (const ThunarFile *file)
2072-{
2073- ThunarFileMode mode;
2074- GFileType kind;
2075- gchar *text;
2076-
2077- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2078-
2079- kind = thunar_file_get_kind (file);
2080- mode = thunar_file_get_mode (file);
2081- text = g_new (gchar, 11);
2082-
2083- /* file type */
2084- /* TODO earlier versions of Thunar had 'P' for ports and
2085- * 'D' for doors. Do we still need those? */
2086- switch (kind)
2087- {
2088- case G_FILE_TYPE_SYMBOLIC_LINK: text[0] = 'l'; break;
2089- case G_FILE_TYPE_REGULAR: text[0] = '-'; break;
2090- case G_FILE_TYPE_DIRECTORY: text[0] = 'd'; break;
2091- case G_FILE_TYPE_SPECIAL:
2092- case G_FILE_TYPE_UNKNOWN:
2093- default:
2094- if (S_ISCHR (mode))
2095- text[0] = 'c';
2096- else if (S_ISSOCK (mode))
2097- text[0] = 's';
2098- else if (S_ISFIFO (mode))
2099- text[0] = 'f';
2100- else if (S_ISBLK (mode))
2101- text[0] = 'b';
2102- else
2103- text[0] = ' ';
2104- }
2105-
2106- /* permission flags */
2107- text[1] = (mode & THUNAR_FILE_MODE_USR_READ) ? 'r' : '-';
2108- text[2] = (mode & THUNAR_FILE_MODE_USR_WRITE) ? 'w' : '-';
2109- text[3] = (mode & THUNAR_FILE_MODE_USR_EXEC) ? 'x' : '-';
2110- text[4] = (mode & THUNAR_FILE_MODE_GRP_READ) ? 'r' : '-';
2111- text[5] = (mode & THUNAR_FILE_MODE_GRP_WRITE) ? 'w' : '-';
2112- text[6] = (mode & THUNAR_FILE_MODE_GRP_EXEC) ? 'x' : '-';
2113- text[7] = (mode & THUNAR_FILE_MODE_OTH_READ) ? 'r' : '-';
2114- text[8] = (mode & THUNAR_FILE_MODE_OTH_WRITE) ? 'w' : '-';
2115- text[9] = (mode & THUNAR_FILE_MODE_OTH_EXEC) ? 'x' : '-';
2116-
2117- /* special flags */
2118- if (G_UNLIKELY (mode & THUNAR_FILE_MODE_SUID))
2119- text[3] = 's';
2120- if (G_UNLIKELY (mode & THUNAR_FILE_MODE_SGID))
2121- text[6] = 's';
2122- if (G_UNLIKELY (mode & THUNAR_FILE_MODE_STICKY))
2123- text[9] = 't';
2124-
2125- text[10] = '\0';
2126-
2127- return text;
2128-}
2129-
2130-
2131-
2132-/**
2133- * thunar_file_get_size_string:
2134- * @file : a #ThunarFile instance.
2135- *
2136- * Returns the size of the file as text in a human readable
2137- * format. You'll need to free the result using g_free()
2138- * if you're done with it.
2139- *
2140- * Return value: the size of @file in a human readable
2141- * format.
2142- **/
2143-gchar *
2144-thunar_file_get_size_string (const ThunarFile *file)
2145-{
2146- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2147- return g_format_size (thunar_file_get_size (file));
2148-}
2149-
2150-
2151-
2152-/**
2153- * thunar_file_get_volume:
2154- * @file : a #ThunarFile instance.
2155- *
2156- * Attempts to determine the #GVolume on which @file is located. If @file cannot
2157- * determine it's volume, then %NULL will be returned. Else a #GVolume instance
2158- * is returned which has to be released by the caller using g_object_unref().
2159- *
2160- * Return value: the #GVolume for @file or %NULL.
2161- **/
2162-GVolume*
2163-thunar_file_get_volume (const ThunarFile *file)
2164-{
2165- GVolume *volume = NULL;
2166- GMount *mount;
2167-
2168- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2169-
2170- /* TODO make this function call asynchronous */
2171- mount = g_file_find_enclosing_mount (file->gfile, NULL, NULL);
2172- if (mount != NULL)
2173- {
2174- volume = g_mount_get_volume (mount);
2175- g_object_unref (mount);
2176- }
2177-
2178- return volume;
2179-}
2180-
2181-
2182-
2183-/**
2184- * thunar_file_get_group:
2185- * @file : a #ThunarFile instance.
2186- *
2187- * Determines the #ThunarGroup for @file. If there's no
2188- * group associated with @file or if the system is unable to
2189- * determine the group, %NULL will be returned.
2190- *
2191- * The caller is responsible for freeing the returned object
2192- * using g_object_unref().
2193- *
2194- * Return value: the #ThunarGroup for @file or %NULL.
2195- **/
2196-ThunarGroup *
2197-thunar_file_get_group (const ThunarFile *file)
2198-{
2199- guint32 gid;
2200-
2201- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2202-
2203- /* TODO what are we going to do on non-UNIX systems? */
2204- gid = g_file_info_get_attribute_uint32 (file->info,
2205- G_FILE_ATTRIBUTE_UNIX_GID);
2206-
2207- return thunar_user_manager_get_group_by_id (user_manager, gid);
2208-}
2209-
2210-
2211-
2212-/**
2213- * thunar_file_get_user:
2214- * @file : a #ThunarFile instance.
2215- *
2216- * Determines the #ThunarUser for @file. If there's no
2217- * user associated with @file or if the system is unable
2218- * to determine the user, %NULL will be returned.
2219- *
2220- * The caller is responsible for freeing the returned object
2221- * using g_object_unref().
2222- *
2223- * Return value: the #ThunarUser for @file or %NULL.
2224- **/
2225-ThunarUser*
2226-thunar_file_get_user (const ThunarFile *file)
2227-{
2228- guint32 uid;
2229-
2230- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2231-
2232- /* TODO what are we going to do on non-UNIX systems? */
2233- uid = g_file_info_get_attribute_uint32 (file->info,
2234- G_FILE_ATTRIBUTE_UNIX_UID);
2235-
2236- return thunar_user_manager_get_user_by_id (user_manager, uid);
2237-}
2238-
2239-
2240-
2241-/**
2242- * thunar_file_get_content_type:
2243- * @file : a #ThunarFile.
2244- *
2245- * Returns the content type of @file.
2246- *
2247- * Return value: content type of @file.
2248- **/
2249-const gchar *
2250-thunar_file_get_content_type (ThunarFile *file)
2251-{
2252- GFileInfo *info;
2253- GError *err = NULL;
2254- const gchar *content_type = NULL;
2255-
2256- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2257-
2258- if (G_UNLIKELY (file->content_type == NULL))
2259- {
2260- G_LOCK (file_content_type_mutex);
2261-
2262- /* make sure we weren't waiting for a lock */
2263- if (G_UNLIKELY (file->content_type != NULL))
2264- goto bailout;
2265-
2266- /* make sure this is not loaded in the general info */
2267- _thunar_assert (file->info == NULL
2268- || !g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE));
2269-
2270- if (G_UNLIKELY (file->kind == G_FILE_TYPE_DIRECTORY))
2271- {
2272- /* this we known for sure */
2273- file->content_type = g_strdup ("inode/directory");
2274- }
2275- else
2276- {
2277- /* async load the content-type */
2278- info = g_file_query_info (file->gfile,
2279- G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
2280- G_FILE_QUERY_INFO_NONE,
2281- NULL, &err);
2282-
2283- if (G_LIKELY (info != NULL))
2284- {
2285- /* store the new content type */
2286- content_type = g_file_info_get_content_type (info);
2287- if (G_UNLIKELY (content_type != NULL))
2288- file->content_type = g_strdup (content_type);
2289- g_object_unref (G_OBJECT (info));
2290- }
2291- else
2292- {
2293- g_warning ("Content type loading failed for %s: %s",
2294- thunar_file_get_display_name (file),
2295- err->message);
2296- g_error_free (err);
2297- }
2298-
2299- /* always provide a fallback */
2300- if (file->content_type == NULL)
2301- file->content_type = g_strdup (DEFAULT_CONTENT_TYPE);
2302- }
2303-
2304- bailout:
2305-
2306- G_UNLOCK (file_content_type_mutex);
2307- }
2308-
2309- return file->content_type;
2310-}
2311-
2312-
2313-
2314-gboolean
2315-thunar_file_load_content_type (ThunarFile *file)
2316-{
2317- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), TRUE);
2318-
2319- if (file->content_type != NULL)
2320- return FALSE;
2321-
2322- thunar_file_get_content_type (file);
2323-
2324- return TRUE;
2325-}
2326-
2327-
2328-
2329-/**
2330- * thunar_file_get_symlink_target:
2331- * @file : a #ThunarFile.
2332- *
2333- * Returns the path of the symlink target or %NULL if the @file
2334- * is not a symlink.
2335- *
2336- * Return value: path of the symlink target or %NULL.
2337- **/
2338-const gchar *
2339-thunar_file_get_symlink_target (const ThunarFile *file)
2340-{
2341- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2342-
2343- if (file->info == NULL)
2344- return NULL;
2345-
2346- return g_file_info_get_symlink_target (file->info);
2347-}
2348-
2349-
2350-
2351-/**
2352- * thunar_file_get_basename:
2353- * @file : a #ThunarFile.
2354- *
2355- * Returns the basename of the @file in UTF-8 encoding.
2356- *
2357- * Return value: UTF-8 encoded basename of the @file.
2358- **/
2359-const gchar *
2360-thunar_file_get_basename (const ThunarFile *file)
2361-{
2362- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2363- return file->basename;
2364-}
2365-
2366-
2367-
2368-/**
2369- * thunar_file_is_symlink:
2370- * @file : a #ThunarFile.
2371- *
2372- * Returns %TRUE if @file is a symbolic link.
2373- *
2374- * Return value: %TRUE if @file is a symbolic link.
2375- **/
2376-gboolean
2377-thunar_file_is_symlink (const ThunarFile *file)
2378-{
2379- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2380-
2381- if (file->info == NULL)
2382- return FALSE;
2383-
2384- return g_file_info_get_is_symlink (file->info);
2385-}
2386-
2387-
2388-
2389-/**
2390- * thunar_file_get_size:
2391- * @file : a #ThunarFile instance.
2392- *
2393- * Tries to determine the size of @file in bytes and
2394- * returns the size.
2395- *
2396- * Return value: the size of @file in bytes.
2397- **/
2398-guint64
2399-thunar_file_get_size (const ThunarFile *file)
2400-{
2401- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0);
2402-
2403- if (file->info == NULL)
2404- return 0;
2405-
2406- return g_file_info_get_size (file->info);
2407-}
2408-
2409-
2410-
2411-/**
2412- * thunar_file_get_default_handler:
2413- * @file : a #ThunarFile instance.
2414- *
2415- * Returns the default #GAppInfo for @file or %NULL if there is none.
2416- *
2417- * The caller is responsible to free the returned #GAppInfo using
2418- * g_object_unref().
2419- *
2420- * Return value: Default #GAppInfo for @file or %NULL if there is none.
2421- **/
2422-GAppInfo *
2423-thunar_file_get_default_handler (const ThunarFile *file)
2424-{
2425- const gchar *content_type;
2426- GAppInfo *app_info = NULL;
2427- gboolean must_support_uris = FALSE;
2428- gchar *path;
2429-
2430- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2431-
2432- content_type = thunar_file_get_content_type (THUNAR_FILE (file));
2433- if (content_type != NULL)
2434- {
2435- path = g_file_get_path (file->gfile);
2436- must_support_uris = (path == NULL);
2437- g_free (path);
2438-
2439- app_info = g_app_info_get_default_for_type (content_type, must_support_uris);
2440- }
2441-
2442- if (app_info == NULL)
2443- app_info = g_file_query_default_handler (file->gfile, NULL, NULL);
2444-
2445- return app_info;
2446-}
2447-
2448-
2449-
2450-/**
2451- * thunar_file_get_kind:
2452- * @file : a #ThunarFile instance.
2453- *
2454- * Returns the kind of @file.
2455- *
2456- * Return value: the kind of @file.
2457- **/
2458-GFileType
2459-thunar_file_get_kind (const ThunarFile *file)
2460-{
2461- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), G_FILE_TYPE_UNKNOWN);
2462- return file->kind;
2463-}
2464-
2465-
2466-
2467-GFile *
2468-thunar_file_get_target_location (const ThunarFile *file)
2469-{
2470- const gchar *uri;
2471-
2472- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2473-
2474- if (file->info == NULL)
2475- return g_object_ref (file->gfile);
2476-
2477- uri = g_file_info_get_attribute_string (file->info,
2478- G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
2479-
2480- return (uri != NULL) ? g_file_new_for_uri (uri) : NULL;
2481-}
2482-
2483-
2484-
2485-/**
2486- * thunar_file_get_mode:
2487- * @file : a #ThunarFile instance.
2488- *
2489- * Returns the permission bits of @file.
2490- *
2491- * Return value: the permission bits of @file.
2492- **/
2493-ThunarFileMode
2494-thunar_file_get_mode (const ThunarFile *file)
2495-{
2496- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0);
2497-
2498- if (file->info == NULL)
2499- return 0;
2500-
2501- if (g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_UNIX_MODE))
2502- return g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_MODE);
2503- else
2504- return thunar_file_is_directory (file) ? 0777 : 0666;
2505-}
2506-
2507-
2508-
2509-gboolean
2510-thunar_file_is_mounted (const ThunarFile *file)
2511-{
2512- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2513- return FLAG_IS_SET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
2514-}
2515-
2516-
2517-
2518-gboolean
2519-thunar_file_exists (const ThunarFile *file)
2520-{
2521- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2522- return g_file_query_exists (file->gfile, NULL);
2523-}
2524-
2525-
2526-
2527-/**
2528- * thunar_file_is_directory:
2529- * @file : a #ThunarFile instance.
2530- *
2531- * Checks whether @file refers to a directory.
2532- *
2533- * Return value: %TRUE if @file is a directory.
2534- **/
2535-gboolean
2536-thunar_file_is_directory (const ThunarFile *file)
2537-{
2538- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2539- return file->kind == G_FILE_TYPE_DIRECTORY;
2540-}
2541-
2542-
2543-
2544-/**
2545- * thunar_file_is_shortcut:
2546- * @file : a #ThunarFile instance.
2547- *
2548- * Checks whether @file refers to a shortcut to something else.
2549- *
2550- * Return value: %TRUE if @file is a shortcut.
2551- **/
2552-gboolean
2553-thunar_file_is_shortcut (const ThunarFile *file)
2554-{
2555- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2556- return file->kind == G_FILE_TYPE_SHORTCUT;
2557-}
2558-
2559-
2560-
2561-/**
2562- * thunar_file_is_mountable:
2563- * @file : a #ThunarFile instance.
2564- *
2565- * Checks whether @file refers to a mountable file/directory.
2566- *
2567- * Return value: %TRUE if @file is a mountable file/directory.
2568- **/
2569-gboolean
2570-thunar_file_is_mountable (const ThunarFile *file)
2571-{
2572- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2573- return file->kind == G_FILE_TYPE_MOUNTABLE;
2574-}
2575-
2576-
2577-
2578-/**
2579- * thunar_file_is_local:
2580- * @file : a #ThunarFile instance.
2581- *
2582- * Returns %TRUE if @file is a local file with the
2583- * file:// URI scheme.
2584- *
2585- * Return value: %TRUE if @file is local.
2586- **/
2587-gboolean
2588-thunar_file_is_local (const ThunarFile *file)
2589-{
2590- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2591- return g_file_has_uri_scheme (file->gfile, "file");
2592-}
2593-
2594-
2595-
2596-/**
2597- * thunar_file_is_parent:
2598- * @file : a #ThunarFile instance.
2599- * @child : another #ThunarFile instance.
2600- *
2601- * Determines whether @file is the parent directory of @child.
2602- *
2603- * Return value: %TRUE if @file is the parent of @child.
2604- **/
2605-gboolean
2606-thunar_file_is_parent (const ThunarFile *file,
2607- const ThunarFile *child)
2608-{
2609- gboolean is_parent = FALSE;
2610- GFile *parent;
2611-
2612- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2613- _thunar_return_val_if_fail (THUNAR_IS_FILE (child), FALSE);
2614-
2615- parent = g_file_get_parent (child->gfile);
2616- if (parent != NULL)
2617- {
2618- is_parent = g_file_equal (file->gfile, parent);
2619- g_object_unref (parent);
2620- }
2621-
2622- return is_parent;
2623-}
2624-
2625-
2626-
2627-/**
2628- * thunar_file_is_ancestor:
2629- * @file : a #ThunarFile instance.
2630- * @ancestor : another #GFile instance.
2631- *
2632- * Determines whether @file is somewhere inside @ancestor,
2633- * possibly with intermediate folders.
2634- *
2635- * Return value: %TRUE if @ancestor contains @file as a
2636- * child, grandchild, great grandchild, etc.
2637- **/
2638-gboolean
2639-thunar_file_is_gfile_ancestor (const ThunarFile *file,
2640- GFile *ancestor)
2641-{
2642- gboolean is_ancestor = FALSE;
2643- GFile *current = NULL;
2644- GFile *tmp;
2645-
2646- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2647- _thunar_return_val_if_fail (G_IS_FILE (ancestor), FALSE);
2648-
2649- for (current = g_object_ref (file->gfile);
2650- is_ancestor == FALSE && current != NULL;
2651- tmp = g_file_get_parent (current), g_object_unref (current), current = tmp)
2652- {
2653- if (G_UNLIKELY (g_file_equal (current, ancestor)))
2654- is_ancestor = TRUE;
2655- }
2656-
2657- if (current != NULL)
2658- g_object_unref (current);
2659-
2660- return is_ancestor;
2661-}
2662-
2663-
2664-
2665-/**
2666- * thunar_file_is_ancestor:
2667- * @file : a #ThunarFile instance.
2668- * @ancestor : another #ThunarFile instance.
2669- *
2670- * Determines whether @file is somewhere inside @ancestor,
2671- * possibly with intermediate folders.
2672- *
2673- * Return value: %TRUE if @ancestor contains @file as a
2674- * child, grandchild, great grandchild, etc.
2675- **/
2676-gboolean
2677-thunar_file_is_ancestor (const ThunarFile *file,
2678- const ThunarFile *ancestor)
2679-{
2680- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2681- _thunar_return_val_if_fail (THUNAR_IS_FILE (ancestor), FALSE);
2682-
2683- return thunar_file_is_gfile_ancestor (file, ancestor->gfile);
2684-}
2685-
2686-
2687-
2688-/**
2689- * thunar_file_is_executable:
2690- * @file : a #ThunarFile instance.
2691- *
2692- * Determines whether the owner of the current process is allowed
2693- * to execute the @file (or enter the directory refered to by
2694- * @file). On UNIX it also returns %TRUE if @file refers to a
2695- * desktop entry.
2696- *
2697- * Return value: %TRUE if @file can be executed.
2698- **/
2699-gboolean
2700-thunar_file_is_executable (const ThunarFile *file)
2701-{
2702- gboolean can_execute = FALSE;
2703- const gchar *content_type;
2704-
2705- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2706-
2707- if (file->info == NULL)
2708- return FALSE;
2709-
2710- if (g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))
2711- {
2712- /* get the content type of the file */
2713- content_type = thunar_file_get_content_type (THUNAR_FILE (file));
2714- if (G_LIKELY (content_type != NULL))
2715- {
2716-#ifdef G_OS_WIN32
2717- /* check for .exe, .bar or .com */
2718- can_execute = g_content_type_can_be_executable (content_type);
2719-#else
2720- /* check if the content type is save to execute, we don't use
2721- * g_content_type_can_be_executable() for unix because it also returns
2722- * true for "text/plain" and we don't want that */
2723- if (g_content_type_is_a (content_type, "application/x-executable")
2724- || g_content_type_is_a (content_type, "application/x-shellscript"))
2725- {
2726- can_execute = TRUE;
2727- }
2728-#endif
2729- }
2730- }
2731-
2732- return can_execute || thunar_file_is_desktop_file (file, NULL);
2733-}
2734-
2735-
2736-
2737-/**
2738- * thunar_file_is_readable:
2739- * @file : a #ThunarFile instance.
2740- *
2741- * Determines whether the owner of the current process is allowed
2742- * to read the @file.
2743- *
2744- * Return value: %TRUE if @file can be read.
2745- **/
2746-static gboolean
2747-thunar_file_is_readable (const ThunarFile *file)
2748-{
2749- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2750-
2751- if (file->info == NULL)
2752- return FALSE;
2753-
2754- if (!g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ))
2755- return TRUE;
2756-
2757- return g_file_info_get_attribute_boolean (file->info,
2758- G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
2759-}
2760-
2761-
2762-
2763-/**
2764- * thunar_file_is_writable:
2765- * @file : a #ThunarFile instance.
2766- *
2767- * Determines whether the owner of the current process is allowed
2768- * to write the @file.
2769- *
2770- * Return value: %TRUE if @file can be read.
2771- **/
2772-gboolean
2773-thunar_file_is_writable (const ThunarFile *file)
2774-{
2775- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2776-
2777- if (file->info == NULL)
2778- return FALSE;
2779-
2780- if (!g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
2781- return TRUE;
2782-
2783- return g_file_info_get_attribute_boolean (file->info,
2784- G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
2785-}
2786-
2787-
2788-
2789-/**
2790- * thunar_file_is_hidden:
2791- * @file : a #ThunarFile instance.
2792- *
2793- * Checks whether @file can be considered a hidden file.
2794- *
2795- * Return value: %TRUE if @file is a hidden file, else %FALSE.
2796- **/
2797-gboolean
2798-thunar_file_is_hidden (const ThunarFile *file)
2799-{
2800- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2801-
2802- if (file->info == NULL)
2803- return FALSE;
2804-
2805- return g_file_info_get_is_hidden (file->info)
2806- || g_file_info_get_is_backup (file->info);
2807-}
2808-
2809-
2810-
2811-/**
2812- * thunar_file_is_home:
2813- * @file : a #ThunarFile.
2814- *
2815- * Checks whether @file refers to the users home directory.
2816- *
2817- * Return value: %TRUE if @file is the users home directory.
2818- **/
2819-gboolean
2820-thunar_file_is_home (const ThunarFile *file)
2821-{
2822- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2823- return thunar_g_file_is_home (file->gfile);
2824-}
2825-
2826-
2827-
2828-/**
2829- * thunar_file_is_regular:
2830- * @file : a #ThunarFile.
2831- *
2832- * Checks whether @file refers to a regular file.
2833- *
2834- * Return value: %TRUE if @file is a regular file.
2835- **/
2836-gboolean
2837-thunar_file_is_regular (const ThunarFile *file)
2838-{
2839- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2840- return file->kind == G_FILE_TYPE_REGULAR;
2841-}
2842-
2843-
2844-
2845-/**
2846- * thunar_file_is_trashed:
2847- * @file : a #ThunarFile instance.
2848- *
2849- * Returns %TRUE if @file is a local file that resides in
2850- * the trash bin.
2851- *
2852- * Return value: %TRUE if @file is in the trash, or
2853- * the trash folder itself.
2854- **/
2855-gboolean
2856-thunar_file_is_trashed (const ThunarFile *file)
2857-{
2858- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2859- return thunar_g_file_is_trashed (file->gfile);
2860-}
2861-
2862-
2863-
2864-/**
2865- * thunar_file_is_desktop_file:
2866- * @file : a #ThunarFile.
2867- * @is_secure : if %NULL do a simple check, else it will set this boolean
2868- * to indicate if the desktop file is safe see bug #5012
2869- * for more info.
2870- *
2871- * Returns %TRUE if @file is a .desktop file. The @is_secure return value
2872- * will tell if the .desktop file is also secure.
2873- *
2874- * Return value: %TRUE if @file is a .desktop file.
2875- **/
2876-gboolean
2877-thunar_file_is_desktop_file (const ThunarFile *file,
2878- gboolean *is_secure)
2879-{
2880- const gchar * const *data_dirs;
2881- guint n;
2882- gchar *path;
2883-
2884- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2885-
2886- if (file->info == NULL)
2887- return FALSE;
2888-
2889- /* only allow regular files with a .desktop extension */
2890- if (!g_str_has_suffix (file->basename, ".desktop")
2891- || file->kind != G_FILE_TYPE_REGULAR)
2892- return FALSE;
2893-
2894- /* don't check more if not needed */
2895- if (is_secure == NULL)
2896- return TRUE;
2897-
2898- /* desktop files outside xdg directories need to be executable for security reasons */
2899- if (g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))
2900- {
2901- /* has +x */
2902- *is_secure = TRUE;
2903- }
2904- else
2905- {
2906- /* assume the file is not safe */
2907- *is_secure = FALSE;
2908-
2909- /* deskopt files in xdg directories are also fine... */
2910- if (g_file_is_native (thunar_file_get_file (file)))
2911- {
2912- data_dirs = g_get_system_data_dirs ();
2913- if (G_LIKELY (data_dirs != NULL))
2914- {
2915- path = g_file_get_path (thunar_file_get_file (file));
2916- for (n = 0; data_dirs[n] != NULL; n++)
2917- {
2918- if (g_str_has_prefix (path, data_dirs[n]))
2919- {
2920- /* has known prefix, can launch without problems */
2921- *is_secure = TRUE;
2922- break;
2923- }
2924- }
2925- g_free (path);
2926- }
2927- }
2928- }
2929-
2930- return TRUE;
2931-}
2932-
2933-
2934-
2935-/**
2936- * thunar_file_get_display_name:
2937- * @file : a #ThunarFile instance.
2938- *
2939- * Returns the @file name in the UTF-8 encoding, which is
2940- * suitable for displaying the file name in the GUI.
2941- *
2942- * Return value: the @file name suitable for display.
2943- **/
2944-const gchar *
2945-thunar_file_get_display_name (const ThunarFile *file)
2946-{
2947- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
2948- return file->display_name;
2949-}
2950-
2951-
2952-
2953-/**
2954- * thunar_file_get_deletion_date:
2955- * @file : a #ThunarFile instance.
2956- * @date_style : the style used to format the date.
2957- *
2958- * Returns the deletion date of the @file if the @file
2959- * is located in the trash. Otherwise %NULL will be
2960- * returned.
2961- *
2962- * The caller is responsible to free the returned string
2963- * using g_free() when no longer needed.
2964- *
2965- * Return value: the deletion date of @file if @file is
2966- * in the trash, %NULL otherwise.
2967- **/
2968-gchar*
2969-thunar_file_get_deletion_date (const ThunarFile *file,
2970- ThunarDateStyle date_style)
2971-{
2972- const gchar *date;
2973- time_t deletion_time;
2974-
2975- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
2976- _thunar_return_val_if_fail (G_IS_FILE_INFO (file->info), NULL);
2977-
2978- date = g_file_info_get_attribute_string (file->info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE);
2979- if (G_UNLIKELY (date == NULL))
2980- return NULL;
2981-
2982- /* try to parse the DeletionDate (RFC 3339 string) */
2983- deletion_time = thunar_util_time_from_rfc3339 (date);
2984-
2985- /* humanize the time value */
2986- return thunar_util_humanize_file_time (deletion_time, date_style);
2987-}
2988-
2989-
2990-
2991-/**
2992- * thunar_file_get_original_path:
2993- * @file : a #ThunarFile instance.
2994- *
2995- * Returns the original path of the @file if the @file
2996- * is located in the trash. Otherwise %NULL will be
2997- * returned.
2998- *
2999- * Return value: the original path of @file if @file is
3000- * in the trash, %NULL otherwise.
3001- **/
3002-const gchar *
3003-thunar_file_get_original_path (const ThunarFile *file)
3004-{
3005- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
3006-
3007- if (file->info == NULL)
3008- return NULL;
3009-
3010- return g_file_info_get_attribute_byte_string (file->info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH);
3011-}
3012-
3013-
3014-
3015-/**
3016- * thunar_file_get_item_count:
3017- * @file : a #ThunarFile instance.
3018- *
3019- * Returns the number of items in the trash, if @file refers to the
3020- * trash root directory. Otherwise returns 0.
3021- *
3022- * Return value: number of files in the trash if @file is the trash
3023- * root dir, 0 otherwise.
3024- **/
3025-guint32
3026-thunar_file_get_item_count (const ThunarFile *file)
3027-{
3028- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0);
3029-
3030- if (file->info == NULL)
3031- return 0;
3032-
3033- return g_file_info_get_attribute_uint32 (file->info,
3034- G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT);
3035-}
3036-
3037-
3038-
3039-/**
3040- * thunar_file_is_chmodable:
3041- * @file : a #ThunarFile instance.
3042- *
3043- * Determines whether the owner of the current process is allowed
3044- * to changed the file mode of @file.
3045- *
3046- * Return value: %TRUE if the mode of @file can be changed.
3047- **/
3048-gboolean
3049-thunar_file_is_chmodable (const ThunarFile *file)
3050-{
3051- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
3052-
3053- /* we can only change the mode if we the euid is
3054- * a) equal to the file owner id
3055- * or
3056- * b) the super-user id
3057- * and the file is not in the trash.
3058- */
3059- if (file->info == NULL)
3060- {
3061- return (effective_user_id == 0 && !thunar_file_is_trashed (file));
3062- }
3063- else
3064- {
3065- return ((effective_user_id == 0
3066- || effective_user_id == g_file_info_get_attribute_uint32 (file->info,
3067- G_FILE_ATTRIBUTE_UNIX_UID))
3068- && !thunar_file_is_trashed (file));
3069- }
3070-}
3071-
3072-
3073-
3074-/**
3075- * thunar_file_is_renameable:
3076- * @file : a #ThunarFile instance.
3077- *
3078- * Determines whether @file can be renamed using
3079- * #thunar_file_rename(). Note that the return
3080- * value is just a guess and #thunar_file_rename()
3081- * may fail even if this method returns %TRUE.
3082- *
3083- * Return value: %TRUE if @file can be renamed.
3084- **/
3085-gboolean
3086-thunar_file_is_renameable (const ThunarFile *file)
3087-{
3088- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
3089-
3090- if (file->info == NULL)
3091- return FALSE;
3092-
3093- return g_file_info_get_attribute_boolean (file->info,
3094- G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME);
3095-}
3096-
3097-
3098-
3099-gboolean
3100-thunar_file_can_be_trashed (const ThunarFile *file)
3101-{
3102- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
3103-
3104- if (file->info == NULL)
3105- return FALSE;
3106-
3107- return g_file_info_get_attribute_boolean (file->info,
3108- G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
3109-}
3110-
3111-
3112-
3113-/**
3114- * thunar_file_get_emblem_names:
3115- * @file : a #ThunarFile instance.
3116- *
3117- * Determines the names of the emblems that should be displayed for
3118- * @file. The returned list is owned by the caller, but the list
3119- * items - the name strings - are owned by @file. So the caller
3120- * must call g_list_free(), but don't g_free() the list items.
3121- *
3122- * Note that the strings contained in the returned list are
3123- * not garantied to exist over the next iteration of the main
3124- * loop. So in case you need the list of emblem names for
3125- * a longer time, you'll need to take a copy of the strings.
3126- *
3127- * Return value: the names of the emblems for @file.
3128- **/
3129-GList*
3130-thunar_file_get_emblem_names (ThunarFile *file)
3131-{
3132- guint32 uid;
3133- gchar **emblem_names;
3134- GList *emblems = NULL;
3135-
3136- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
3137-
3138- /* leave if there is no info */
3139- if (file->info == NULL)
3140- return NULL;
3141-
3142- /* determine the custom emblems */
3143- emblem_names = g_file_info_get_attribute_stringv (file->info, "metadata::emblems");
3144- if (G_UNLIKELY (emblem_names != NULL))
3145- {
3146- for (; *emblem_names != NULL; ++emblem_names)
3147- emblems = g_list_append (emblems, *emblem_names);
3148- }
3149-
3150- if (thunar_file_is_symlink (file))
3151- emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_SYMBOLIC_LINK);
3152-
3153- /* determine the user ID of the file owner */
3154- /* TODO what are we going to do here on non-UNIX systems? */
3155- uid = file->info != NULL
3156- ? g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_UID)
3157- : 0;
3158-
3159- /* we add "cant-read" if either (a) the file is not readable or (b) a directory, that lacks the
3160- * x-bit, see http://bugzilla.xfce.org/show_bug.cgi?id=1408 for the details about this change.
3161- */
3162- if (!thunar_file_is_readable (file)
3163- || (thunar_file_is_directory (file)
3164- && thunar_file_denies_access_permission (file, THUNAR_FILE_MODE_USR_EXEC,
3165- THUNAR_FILE_MODE_GRP_EXEC,
3166- THUNAR_FILE_MODE_OTH_EXEC)))
3167- {
3168- emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_CANT_READ);
3169- }
3170- else if (G_UNLIKELY (uid == effective_user_id && !thunar_file_is_writable (file)))
3171- {
3172- /* we own the file, but we cannot write to it, that's why we mark it as "cant-write", so
3173- * users won't be surprised when opening the file in a text editor, but are unable to save.
3174- */
3175- emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_CANT_WRITE);
3176- }
3177-
3178- return emblems;
3179-}
3180-
3181-
3182-
3183-/**
3184- * thunar_file_set_emblem_names:
3185- * @file : a #ThunarFile instance.
3186- * @emblem_names : a #GList of emblem names.
3187- *
3188- * Sets the custom emblem name list of @file to @emblem_names
3189- * and stores them in the @file<!---->s metadata.
3190- **/
3191-void
3192-thunar_file_set_emblem_names (ThunarFile *file,
3193- GList *emblem_names)
3194-{
3195- GList *lp;
3196- gchar **emblems = NULL;
3197- gint n;
3198- GFileInfo *info;
3199-
3200- _thunar_return_if_fail (THUNAR_IS_FILE (file));
3201- _thunar_return_if_fail (G_IS_FILE_INFO (file->info));
3202-
3203- /* allocate a zero-terminated array for the emblem names */
3204- emblems = g_new0 (gchar *, g_list_length (emblem_names) + 1);
3205-
3206- /* turn the emblem_names list into a zero terminated array */
3207- for (lp = emblem_names, n = 0; lp != NULL; lp = lp->next)
3208- {
3209- /* skip special emblems */
3210- if (strcmp (lp->data, THUNAR_FILE_EMBLEM_NAME_SYMBOLIC_LINK) == 0
3211- || strcmp (lp->data, THUNAR_FILE_EMBLEM_NAME_CANT_READ) == 0
3212- || strcmp (lp->data, THUNAR_FILE_EMBLEM_NAME_CANT_WRITE) == 0
3213- || strcmp (lp->data, THUNAR_FILE_EMBLEM_NAME_DESKTOP) == 0)
3214- continue;
3215-
3216- /* add the emblem to our list */
3217- emblems[n++] = g_strdup (lp->data);
3218- }
3219-
3220- /* set the value in the current info */
3221- if (n == 0)
3222- g_file_info_remove_attribute (file->info, "metadata::emblems");
3223- else
3224- g_file_info_set_attribute_stringv (file->info, "metadata::emblems", emblems);
3225-
3226- /* set meta data to the daemon */
3227- info = g_file_info_new ();
3228- g_file_info_set_attribute_stringv (info, "metadata::emblems", emblems);
3229- g_file_set_attributes_async (file->gfile, info,
3230- G_FILE_QUERY_INFO_NONE,
3231- G_PRIORITY_DEFAULT,
3232- NULL,
3233- thunar_file_set_emblem_names_ready,
3234- file);
3235- g_object_unref (G_OBJECT (info));
3236-
3237- g_strfreev (emblems);
3238-}
3239-
3240-
3241-
3242-/**
3243- * thunar_file_set_custom_icon:
3244- * @file : a #ThunarFile instance.
3245- * @custom_icon : the new custom icon for the @file.
3246- * @error : return location for errors or %NULL.
3247- *
3248- * Tries to change the custom icon of the .desktop file referred
3249- * to by @file. If that fails, %FALSE is returned and the
3250- * @error is set accordingly.
3251- *
3252- * Return value: %TRUE if the icon of @file was changed, %FALSE otherwise.
3253- **/
3254-gboolean
3255-thunar_file_set_custom_icon (ThunarFile *file,
3256- const gchar *custom_icon,
3257- GError **error)
3258-{
3259- GKeyFile *key_file;
3260-
3261- _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
3262- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
3263- _thunar_return_val_if_fail (custom_icon != NULL, FALSE);
3264-
3265- key_file = thunar_g_file_query_key_file (file->gfile, NULL, error);
3266-
3267- if (key_file == NULL)
3268- return FALSE;
3269-
3270- g_key_file_set_string (key_file, G_KEY_FILE_DESKTOP_GROUP,
3271- G_KEY_FILE_DESKTOP_KEY_ICON, custom_icon);
3272-
3273- if (thunar_g_file_write_key_file (file->gfile, key_file, NULL, error))
3274- {
3275- /* tell everybody that we have changed */
3276- thunar_file_changed (file);
3277-
3278- g_key_file_free (key_file);
3279- return TRUE;
3280- }
3281- else
3282- {
3283- g_key_file_free (key_file);
3284- return FALSE;
3285- }
3286-}
3287-
3288-
3289-/**
3290- * thunar_file_is_desktop:
3291- * @file : a #ThunarFile.
3292- *
3293- * Checks whether @file refers to the users desktop directory.
3294- *
3295- * Return value: %TRUE if @file is the users desktop directory.
3296- **/
3297-gboolean
3298-thunar_file_is_desktop (const ThunarFile *file)
3299-{
3300- GFile *desktop;
3301- gboolean is_desktop = FALSE;
3302-
3303- desktop = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
3304- is_desktop = g_file_equal (file->gfile, desktop);
3305- g_object_unref (desktop);
3306-
3307- return is_desktop;
3308-}
3309-
3310-
3311-
3312-const gchar *
3313-thunar_file_get_thumbnail_path (ThunarFile *file)
3314-{
3315- GChecksum *checksum;
3316- gchar *basename;
3317- gchar *uri;
3318-
3319- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
3320-
3321- /* if the thumbstate is known to be not there, return null */
3322- if (thunar_file_get_thumb_state (file) == THUNAR_FILE_THUMB_STATE_NONE)
3323- return NULL;
3324-
3325- if (G_UNLIKELY (file->thumbnail_path == NULL))
3326- {
3327- checksum = g_checksum_new (G_CHECKSUM_MD5);
3328- if (G_LIKELY (checksum != NULL))
3329- {
3330- uri = thunar_file_dup_uri (file);
3331- g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
3332- g_free (uri);
3333-
3334- basename = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
3335- g_checksum_free (checksum);
3336-
3337- file->thumbnail_path = g_build_filename (xfce_get_homedir (), ".thumbnails",
3338- "normal", basename, NULL);
3339-
3340- g_free (basename);
3341- }
3342- }
3343-
3344- return file->thumbnail_path;
3345-}
3346-
3347-
3348-
3349-/**
3350- * thunar_file_get_thumb_state:
3351- * @file : a #ThunarFile.
3352- *
3353- * Returns the current #ThunarFileThumbState for @file. This
3354- * method is intended to be used by #ThunarIconFactory only.
3355- *
3356- * Return value: the #ThunarFileThumbState for @file.
3357- **/
3358-ThunarFileThumbState
3359-thunar_file_get_thumb_state (const ThunarFile *file)
3360-{
3361- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), THUNAR_FILE_THUMB_STATE_UNKNOWN);
3362- return FLAG_GET_THUMB_STATE (file);
3363-}
3364-
3365-
3366-
3367-/**
3368- * thunar_file_set_thumb_state:
3369- * @file : a #ThunarFile.
3370- * @thumb_state : the new #ThunarFileThumbState.
3371- *
3372- * Sets the #ThunarFileThumbState for @file to @thumb_state.
3373- * This will cause a "file-changed" signal to be emitted from
3374- * #ThunarFileMonitor.
3375- **/
3376-void
3377-thunar_file_set_thumb_state (ThunarFile *file,
3378- ThunarFileThumbState state)
3379-{
3380- _thunar_return_if_fail (THUNAR_IS_FILE (file));
3381-
3382- /* check if the state changes */
3383- if (thunar_file_get_thumb_state (file) == state)
3384- return;
3385-
3386- /* set the new thumbnail state */
3387- FLAG_SET_THUMB_STATE (file, state);
3388-
3389- /* remove path if the type is not supported */
3390- if (state == THUNAR_FILE_THUMB_STATE_NONE
3391- && file->thumbnail_path != NULL)
3392- {
3393- g_free (file->thumbnail_path);
3394- file->thumbnail_path = NULL;
3395- }
3396-
3397- /* if the file has a thumbnail, reload it */
3398- if (state == THUNAR_FILE_THUMB_STATE_READY)
3399- thunar_file_monitor_file_changed (file);
3400-}
3401-
3402-
3403-
3404-/**
3405- * thunar_file_get_custom_icon:
3406- * @file : a #ThunarFile instance.
3407- *
3408- * Queries the custom icon from @file if any, else %NULL is returned.
3409- * The custom icon can be either a themed icon name or an absolute path
3410- * to an icon file in the local file system.
3411- *
3412- * Return value: the custom icon for @file or %NULL.
3413- **/
3414-const gchar *
3415-thunar_file_get_custom_icon (const ThunarFile *file)
3416-{
3417- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
3418- return file->custom_icon_name;
3419-}
3420-
3421-
3422-
3423-/**
3424- * thunar_file_get_preview_icon:
3425- * @file : a #ThunarFile instance.
3426- *
3427- * Returns the preview icon for @file if any, else %NULL is returned.
3428- *
3429- * Return value: the custom icon for @file or %NULL, the GIcon is owner
3430- * by the file, so do not unref it.
3431- **/
3432-GIcon *
3433-thunar_file_get_preview_icon (const ThunarFile *file)
3434-{
3435- GObject *icon;
3436-
3437- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
3438- _thunar_return_val_if_fail (G_IS_FILE_INFO (file->info), NULL);
3439-
3440- icon = g_file_info_get_attribute_object (file->info, G_FILE_ATTRIBUTE_PREVIEW_ICON);
3441- if (G_LIKELY (icon != NULL))
3442- return G_ICON (icon);
3443-
3444- return NULL;
3445-}
3446-
3447-
3448-
3449-GFilesystemPreviewType
3450-thunar_file_get_preview_type (const ThunarFile *file)
3451-{
3452- GFilesystemPreviewType preview;
3453- GFileInfo *info;
3454-
3455- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), G_FILESYSTEM_PREVIEW_TYPE_NEVER);
3456- _thunar_return_val_if_fail (G_IS_FILE (file->gfile), G_FILESYSTEM_PREVIEW_TYPE_NEVER);
3457-
3458- info = g_file_query_filesystem_info (file->gfile, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, NULL, NULL);
3459- if (G_LIKELY (info != NULL))
3460- {
3461- preview = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW);
3462- g_object_unref (G_OBJECT (info));
3463- }
3464- else
3465- {
3466- /* assume we don't know */
3467- preview = G_FILESYSTEM_PREVIEW_TYPE_NEVER;
3468- }
3469-
3470- return preview;
3471-}
3472-
3473-
3474-
3475-static const gchar *
3476-thunar_file_get_icon_name_for_state (const gchar *icon_name,
3477- ThunarFileIconState icon_state)
3478-{
3479- if (exo_str_is_empty (icon_name))
3480- return NULL;
3481-
3482- /* check if we have an accept icon for the icon we found */
3483- if (icon_state != THUNAR_FILE_ICON_STATE_DEFAULT
3484- && (strcmp (icon_name, "inode-directory") == 0
3485- || strcmp (icon_name, "folder") == 0))
3486- {
3487- if (icon_state == THUNAR_FILE_ICON_STATE_DROP)
3488- return "folder-drag-accept";
3489- else if (icon_state == THUNAR_FILE_ICON_STATE_OPEN)
3490- return "folder-open";
3491- }
3492-
3493- return icon_name;
3494-}
3495-
3496-
3497-
3498-/**
3499- * thunar_file_get_icon_name:
3500- * @file : a #ThunarFile instance.
3501- * @icon_state : the state of the @file<!---->s icon we are interested in.
3502- * @icon_theme : the #GtkIconTheme on which to lookup up the icon name.
3503- *
3504- * Returns the name of the icon that can be used to present @file, based
3505- * on the given @icon_state and @icon_theme.
3506- *
3507- * Return value: the icon name for @file in @icon_theme.
3508- **/
3509-const gchar *
3510-thunar_file_get_icon_name (ThunarFile *file,
3511- ThunarFileIconState icon_state,
3512- GtkIconTheme *icon_theme)
3513-{
3514- GFile *icon_file;
3515- GIcon *icon = NULL;
3516- const gchar * const *names;
3517- gchar *icon_name = NULL;
3518- gchar *path;
3519- const gchar *special_names[] = { NULL, "folder", NULL };
3520- guint i;
3521- const gchar *special_dir;
3522- GFileInfo *fileinfo;
3523-
3524- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
3525- _thunar_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
3526-
3527- /* return cached name */
3528- if (G_LIKELY (file->icon_name != NULL))
3529- return thunar_file_get_icon_name_for_state (file->icon_name, icon_state);
3530-
3531- /* the system root folder has a special icon */
3532- if (thunar_file_is_directory (file))
3533- {
3534- if (G_LIKELY (thunar_file_is_local (file)))
3535- {
3536- path = g_file_get_path (file->gfile);
3537- if (G_LIKELY (path != NULL))
3538- {
3539- if (strcmp (path, G_DIR_SEPARATOR_S) == 0)
3540- *special_names = "drive-harddisk";
3541- else if (strcmp (path, xfce_get_homedir ()) == 0)
3542- *special_names = "user-home";
3543- else
3544- {
3545- for (i = 0; i < G_N_ELEMENTS (thunar_file_dirs); i++)
3546- {
3547- special_dir = g_get_user_special_dir (thunar_file_dirs[i].type);
3548- if (special_dir != NULL
3549- && strcmp (path, special_dir) == 0)
3550- {
3551- *special_names = thunar_file_dirs[i].icon_name;
3552- break;
3553- }
3554- }
3555- }
3556-
3557- g_free (path);
3558- }
3559- }
3560- else if (!thunar_file_has_parent (file))
3561- {
3562- if (g_file_has_uri_scheme (file->gfile, "trash"))
3563- {
3564- special_names[0] = thunar_file_get_item_count (file) > 0 ? "user-trash-full" : "user-trash";
3565- special_names[1] = "user-trash";
3566- }
3567- else if (g_file_has_uri_scheme (file->gfile, "recent"))
3568- {
3569- special_names[0] = "document-open-recent";
3570- }
3571- else if (g_file_has_uri_scheme (file->gfile, "computer"))
3572- {
3573- special_names[0] = "computer";
3574- }
3575- }
3576-
3577- if (*special_names != NULL)
3578- {
3579- names = special_names;
3580- goto check_names;
3581- }
3582- }
3583- else if (thunar_file_is_mountable (file))
3584- {
3585- /* query the icon (computer:// backend) */
3586- fileinfo = g_file_query_info (file->gfile,
3587- G_FILE_ATTRIBUTE_STANDARD_ICON,
3588- G_FILE_QUERY_INFO_NONE, NULL, NULL);
3589- if (G_LIKELY (fileinfo != NULL))
3590- {
3591- /* take the icon from the info */
3592- icon = g_file_info_get_icon (fileinfo);
3593- if (G_LIKELY (icon != NULL))
3594- g_object_ref (icon);
3595-
3596- /* release */
3597- g_object_unref (G_OBJECT (fileinfo));
3598-
3599- if (G_LIKELY (icon != NULL))
3600- goto check_icon;
3601- }
3602- }
3603-
3604- /* try again later */
3605- if (file->info == NULL)
3606- return NULL;
3607-
3608- /* lookup for content type, just like gio does for local files */
3609- icon = g_content_type_get_icon (thunar_file_get_content_type (file));
3610- if (G_LIKELY (icon != NULL))
3611- {
3612- check_icon:
3613-
3614- if (G_IS_THEMED_ICON (icon))
3615- {
3616- names = g_themed_icon_get_names (G_THEMED_ICON (icon));
3617-
3618- check_names:
3619-
3620- if (G_LIKELY (names != NULL))
3621- {
3622- for (i = 0; names[i] != NULL; ++i)
3623- if (*names[i] != '(' /* see gnome bug 688042 */
3624- && gtk_icon_theme_has_icon (icon_theme, names[i]))
3625- {
3626- icon_name = g_strdup (names[i]);
3627- break;
3628- }
3629- }
3630- }
3631- else if (G_IS_FILE_ICON (icon))
3632- {
3633- icon_file = g_file_icon_get_file (G_FILE_ICON (icon));
3634- if (icon_file != NULL)
3635- icon_name = g_file_get_path (icon_file);
3636- }
3637-
3638- if (G_LIKELY (icon != NULL))
3639- g_object_unref (icon);
3640- }
3641-
3642- /* store new name, or empty string to avoid recursion */
3643- if (G_LIKELY (icon_name != NULL))
3644- file->icon_name = icon_name;
3645- else
3646- file->icon_name = g_strdup ("");
3647-
3648- return thunar_file_get_icon_name_for_state (file->icon_name, icon_state);
3649-}
3650-
3651-
3652-
3653-/**
3654- * thunar_file_watch:
3655- * @file : a #ThunarFile instance.
3656- *
3657- * Tells @file to watch itself for changes. Not all #ThunarFile
3658- * implementations must support this, but if a #ThunarFile
3659- * implementation implements the thunar_file_watch() method,
3660- * it must also implement the thunar_file_unwatch() method.
3661- *
3662- * The #ThunarFile base class implements automatic "ref
3663- * counting" for watches, that says, you can call thunar_file_watch()
3664- * multiple times, but the virtual method will be invoked only
3665- * once. This also means that you MUST call thunar_file_unwatch()
3666- * for every thunar_file_watch() invokation, else the application
3667- * will abort.
3668- **/
3669-void
3670-thunar_file_watch (ThunarFile *file)
3671-{
3672- ThunarFileWatch *file_watch;
3673-
3674- _thunar_return_if_fail (THUNAR_IS_FILE (file));
3675-
3676- file_watch = g_object_get_qdata (G_OBJECT (file), thunar_file_watch_quark);
3677- if (file_watch == NULL)
3678- {
3679- file_watch = g_slice_new (ThunarFileWatch);
3680- file_watch->watch_count = 1;
3681-
3682- /* create a file or directory monitor */
3683- file_watch->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
3684- if (G_LIKELY (file_watch->monitor != NULL))
3685- {
3686- /* watch monitor for file changes */
3687- g_signal_connect (file_watch->monitor, "changed", G_CALLBACK (thunar_file_monitor), file);
3688- }
3689-
3690- /* attach to file */
3691- g_object_set_qdata_full (G_OBJECT (file), thunar_file_watch_quark, file_watch, thunar_file_watch_destroyed);
3692- }
3693- else
3694- {
3695- /* increase watch count */
3696- _thunar_return_if_fail (G_IS_FILE_MONITOR (file_watch->monitor));
3697- file_watch->watch_count++;
3698- }
3699-}
3700-
3701-
3702-
3703-/**
3704- * thunar_file_unwatch:
3705- * @file : a #ThunarFile instance.
3706- *
3707- * See thunar_file_watch() for a description of how watching
3708- * #ThunarFile<!---->s works.
3709- **/
3710-void
3711-thunar_file_unwatch (ThunarFile *file)
3712-{
3713- ThunarFileWatch *file_watch;
3714-
3715- _thunar_return_if_fail (THUNAR_IS_FILE (file));
3716-
3717- file_watch = g_object_get_qdata (G_OBJECT (file), thunar_file_watch_quark);
3718- if (file_watch != NULL)
3719- {
3720- /* remove if this was the last ref */
3721- if (--file_watch->watch_count == 0)
3722- g_object_set_qdata (G_OBJECT (file), thunar_file_watch_quark, NULL);
3723- }
3724- else
3725- {
3726- _thunar_assert_not_reached ();
3727- }
3728-}
3729-
3730-
3731-
3732-/**
3733- * thunar_file_reload:
3734- * @file : a #ThunarFile instance.
3735- *
3736- * Tells @file to reload its internal state, e.g. by reacquiring
3737- * the file info from the underlying media.
3738- *
3739- * You must be able to handle the case that @file is
3740- * destroyed during the reload call.
3741- **/
3742-void
3743-thunar_file_reload (ThunarFile *file)
3744-{
3745- _thunar_return_if_fail (THUNAR_IS_FILE (file));
3746-
3747- /* clear file pxmap cache */
3748- thunar_icon_factory_clear_pixmap_cache (file);
3749-
3750- if (!thunar_file_load (file, NULL, NULL))
3751- {
3752- /* destroy the file if we cannot query any file information */
3753- thunar_file_destroy (file);
3754- return;
3755- }
3756-
3757- /* ... and tell others */
3758- thunar_file_changed (file);
3759-
3760-}
3761-
3762-
3763-
3764-/**
3765- * thunar_file_destroy:
3766- * @file : a #ThunarFile instance.
3767- *
3768- * Emits the ::destroy signal notifying all reference holders
3769- * that they should release their references to the @file.
3770- *
3771- * This method is very similar to what gtk_object_destroy()
3772- * does for #GtkObject<!---->s.
3773- **/
3774-void
3775-thunar_file_destroy (ThunarFile *file)
3776-{
3777- _thunar_return_if_fail (THUNAR_IS_FILE (file));
3778-
3779- if (!FLAG_IS_SET (file, THUNAR_FILE_FLAG_IN_DESTRUCTION))
3780- {
3781- /* take an additional reference on the file, as the file-destroyed
3782- * invocation may already release the last reference.
3783- */
3784- g_object_ref (G_OBJECT (file));
3785-
3786- /* tell the file monitor that this file was destroyed */
3787- thunar_file_monitor_file_destroyed (file);
3788-
3789- /* run the dispose handler */
3790- g_object_run_dispose (G_OBJECT (file));
3791-
3792- /* release our reference */
3793- g_object_unref (G_OBJECT (file));
3794- }
3795-}
3796-
3797-
3798-
3799-/**
3800- * thunar_file_compare_by_name:
3801- * @file_a : the first #ThunarFile.
3802- * @file_b : the second #ThunarFile.
3803- * @case_sensitive : whether the comparison should be case-sensitive.
3804- *
3805- * Compares @file_a and @file_b by their display names. If @case_sensitive
3806- * is %TRUE the comparison will be case-sensitive.
3807- *
3808- * Return value: -1 if @file_a should be sorted before @file_b, 1 if
3809- * @file_b should be sorted before @file_a, 0 if equal.
3810- **/
3811-gint
3812-thunar_file_compare_by_name (const ThunarFile *file_a,
3813- const ThunarFile *file_b,
3814- gboolean case_sensitive)
3815-{
3816- gint result = 0;
3817-
3818-#ifdef G_ENABLE_DEBUG
3819- /* probably too expensive to do the instance check every time
3820- * this function is called, so only for debugging builds.
3821- */
3822- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_a), 0);
3823- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_b), 0);
3824-#endif
3825-
3826- /* case insensitive checking */
3827- if (G_LIKELY (!case_sensitive))
3828- result = strcmp (file_a->collate_key_nocase, file_b->collate_key_nocase);
3829-
3830- /* fall-back to case sensitive */
3831- if (result == 0)
3832- result = strcmp (file_a->collate_key, file_b->collate_key);
3833-
3834- /* this happens in the trash */
3835- if (result == 0)
3836- {
3837- result = g_strcmp0 (thunar_file_get_original_path (file_a),
3838- thunar_file_get_original_path (file_b));
3839- }
3840-
3841- return result;
3842-}
3843-
3844-
3845-
3846-static gboolean
3847-thunar_file_same_filesystem (const ThunarFile *file_a,
3848- const ThunarFile *file_b)
3849-{
3850- const gchar *filesystem_id_a;
3851- const gchar *filesystem_id_b;
3852-
3853- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_a), FALSE);
3854- _thunar_return_val_if_fail (THUNAR_IS_FILE (file_b), FALSE);
3855-
3856- /* return false if we have no information about one of the files */
3857- if (file_a->info == NULL || file_b->info == NULL)
3858- return FALSE;
3859-
3860- /* determine the filesystem IDs */
3861- filesystem_id_a = g_file_info_get_attribute_string (file_a->info,
3862- G_FILE_ATTRIBUTE_ID_FILESYSTEM);
3863-
3864- filesystem_id_b = g_file_info_get_attribute_string (file_b->info,
3865- G_FILE_ATTRIBUTE_ID_FILESYSTEM);
3866-
3867- /* compare the filesystem IDs */
3868- return exo_str_is_equal (filesystem_id_a, filesystem_id_b);
3869-}
3870-
3871-
3872-
3873-/**
3874- * thunar_file_cache_lookup:
3875- * @file : a #GFile.
3876- *
3877- * Looks up the #ThunarFile for @file in the internal file
3878- * cache and returns the file present for @file in the
3879- * cache or %NULL if no #ThunarFile is cached for @file.
3880- *
3881- * Note that no reference is taken for the caller.
3882- *
3883- * This method should not be used but in very rare cases.
3884- * Consider using thunar_file_get() instead.
3885- *
3886- * Return value: the #ThunarFile for @file in the internal
3887- * cache, or %NULL.
3888- **/
3889-ThunarFile *
3890-thunar_file_cache_lookup (const GFile *file)
3891-{
3892- ThunarFile *cached_file;
3893-
3894- _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
3895-
3896- G_LOCK (file_cache_mutex);
3897-
3898- /* allocate the ThunarFile cache on-demand */
3899- if (G_UNLIKELY (file_cache == NULL))
3900- {
3901- file_cache = g_hash_table_new_full (g_file_hash,
3902- (GEqualFunc) g_file_equal,
3903- (GDestroyNotify) g_object_unref,
3904- NULL);
3905- }
3906-
3907- cached_file = g_hash_table_lookup (file_cache, file);
3908-
3909- G_UNLOCK (file_cache_mutex);
3910-
3911- return cached_file;
3912-}
3913-
3914-
3915-
3916-gchar *
3917-thunar_file_cached_display_name (const GFile *file)
3918-{
3919- ThunarFile *cached_file;
3920- gchar *display_name;
3921-
3922- /* check if we have a ThunarFile for it in the cache (usually is the case) */
3923- cached_file = thunar_file_cache_lookup (file);
3924- if (cached_file != NULL)
3925- {
3926- /* determine the display name of the file */
3927- display_name = g_strdup (thunar_file_get_display_name (cached_file));
3928- }
3929- else
3930- {
3931- /* determine something a hopefully good approximation of the display name */
3932- display_name = thunar_g_file_get_display_name (G_FILE (file));
3933- }
3934-
3935- return display_name;
3936-}
3937-
3938-
3939-
3940-static gint
3941-compare_app_infos (gconstpointer a,
3942- gconstpointer b)
3943-{
3944- return g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b)) ? 0 : 1;
3945-}
3946-
3947-
3948-
3949-/**
3950- * thunar_file_list_get_applications:
3951- * @file_list : a #GList of #ThunarFile<!---->s.
3952- *
3953- * Returns the #GList of #GAppInfo<!---->s that can be used to open
3954- * all #ThunarFile<!---->s in the given @file_list.
3955- *
3956- * The caller is responsible to free the returned list using something like:
3957- * <informalexample><programlisting>
3958- * g_list_free_full (list, g_object_unref);
3959- * </programlisting></informalexample>
3960- *
3961- * Return value: the list of #GAppInfo<!---->s that can be used to open all
3962- * items in the @file_list.
3963- **/
3964-GList*
3965-thunar_file_list_get_applications (GList *file_list)
3966-{
3967- GList *applications = NULL;
3968- GList *list;
3969- GList *next;
3970- GList *ap;
3971- GList *lp;
3972- const gchar *previous_type = NULL;
3973- const gchar *current_type;
3974-
3975- /* determine the set of applications that can open all files */
3976- for (lp = file_list; lp != NULL; lp = lp->next)
3977- {
3978- current_type = thunar_file_get_content_type (lp->data);
3979-
3980- /* no need to check anything if this file has the same mimetype as the previous file */
3981- if (current_type != NULL && previous_type != NULL)
3982- if (G_LIKELY (g_content_type_equals (previous_type, current_type)))
3983- continue;
3984-
3985- /* store the previous type */
3986- previous_type = current_type;
3987-
3988- /* determine the list of applications that can open this file */
3989- if (G_UNLIKELY (current_type != NULL))
3990- list = g_app_info_get_all_for_type (current_type);
3991- else
3992- list = NULL;
3993-
3994- if (G_UNLIKELY (applications == NULL))
3995- {
3996- /* first file, so just use the applications list */
3997- applications = list;
3998- }
3999- else
4000- {
4001- /* keep only the applications that are also present in list */
4002- for (ap = applications; ap != NULL; ap = next)
4003- {
4004- /* grab a pointer on the next application */
4005- next = ap->next;
4006-
4007- /* check if the application is present in list */
4008- if (g_list_find_custom (list, ap->data, compare_app_infos) == NULL)
4009- {
4010- /* drop our reference on the application */
4011- g_object_unref (G_OBJECT (ap->data));
4012-
4013- /* drop this application from the list */
4014- applications = g_list_delete_link (applications, ap);
4015- }
4016- }
4017-
4018- /* release the list of applications for this file */
4019- g_list_free_full (list, g_object_unref);
4020- }
4021-
4022- /* check if the set is still not empty */
4023- if (G_LIKELY (applications == NULL))
4024- break;
4025- }
4026-
4027- /* remove hidden applications */
4028- for (ap = applications; ap != NULL; ap = next)
4029- {
4030- /* grab a pointer on the next application */
4031- next = ap->next;
4032-
4033- if (!thunar_g_app_info_should_show (ap->data))
4034- {
4035- /* drop our reference on the application */
4036- g_object_unref (G_OBJECT (ap->data));
4037-
4038- /* drop this application from the list */
4039- applications = g_list_delete_link (applications, ap);
4040- }
4041- }
4042-
4043- return applications;
4044-}
4045-
4046-
4047-
4048-/**
4049- * thunar_file_list_to_thunar_g_file_list:
4050- * @file_list : a #GList of #ThunarFile<!---->s.
4051- *
4052- * Transforms the @file_list to a #GList of #GFile<!---->s for
4053- * the #ThunarFile<!---->s contained within @file_list.
4054- *
4055- * The caller is responsible to free the returned list using
4056- * thunar_g_file_list_free() when no longer needed.
4057- *
4058- * Return value: the list of #GFile<!---->s for @file_list.
4059- **/
4060-GList*
4061-thunar_file_list_to_thunar_g_file_list (GList *file_list)
4062-{
4063- GList *list = NULL;
4064- GList *lp;
4065-
4066- for (lp = g_list_last (file_list); lp != NULL; lp = lp->prev)
4067- list = g_list_prepend (list, g_object_ref (THUNAR_FILE (lp->data)->gfile));
4068-
4069- return list;
4070-}
4071
4072=== modified file '.pc/applied-patches'
4073--- .pc/applied-patches 2014-10-31 07:27:27 +0000
4074+++ .pc/applied-patches 2015-01-06 18:59:01 +0000
4075@@ -1,7 +1,2 @@
4076 01_support-non-multiarch-modules.patch
4077-02_fix-default-application-selection.patch
4078-git-xfdesktop-4.11.patch
4079-gtk3-bookmarks.patch
4080-git-save-keyboard-shortcuts.patch
4081 menu-icon-tweaks.patch
4082-git-force-toolbr-icons.patch
4083
4084=== removed directory '.pc/git-force-toolbr-icons.patch'
4085=== removed directory '.pc/git-force-toolbr-icons.patch/thunar'
4086=== removed file '.pc/git-force-toolbr-icons.patch/thunar/thunar-window.c'
4087--- .pc/git-force-toolbr-icons.patch/thunar/thunar-window.c 2014-04-05 08:22:40 +0000
4088+++ .pc/git-force-toolbr-icons.patch/thunar/thunar-window.c 1970-01-01 00:00:00 +0000
4089@@ -1,3846 +0,0 @@
4090-/* vi:set et ai sw=2 sts=2 ts=2: */
4091-/*-
4092- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org>
4093- * Copyright (c) 2009-2011 Jannis Pohlmann <jannis@xfce.org>
4094- *
4095- * This program is free software; you can redistribute it and/or
4096- * modify it under the terms of the GNU General Public License as
4097- * published by the Free Software Foundation; either version 2 of
4098- * the License, or (at your option) any later version.
4099- *
4100- * This program is distributed in the hope that it will be useful,
4101- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4102- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4103- * GNU General Public License for more details.
4104- *
4105- * You should have received a copy of the GNU General Public
4106- * License along with this program; if not, write to the Free
4107- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
4108- * Boston, MA 02110-1301, USA.
4109- */
4110-
4111-#ifdef HAVE_CONFIG_H
4112-#include <config.h>
4113-#endif
4114-
4115-#ifdef HAVE_UNISTD_H
4116-#include <unistd.h>
4117-#endif
4118-#ifdef HAVE_LOCALE_H
4119-#include <locale.h>
4120-#endif
4121-
4122-#include <gdk/gdkkeysyms.h>
4123-#include <libxfce4ui/libxfce4ui.h>
4124-
4125-#include <thunar/thunar-application.h>
4126-#include <thunar/thunar-browser.h>
4127-#include <thunar/thunar-clipboard-manager.h>
4128-#include <thunar/thunar-compact-view.h>
4129-#include <thunar/thunar-details-view.h>
4130-#include <thunar/thunar-dialogs.h>
4131-#include <thunar/thunar-shortcuts-pane.h>
4132-#include <thunar/thunar-gio-extensions.h>
4133-#include <thunar/thunar-gobject-extensions.h>
4134-#include <thunar/thunar-gtk-extensions.h>
4135-#include <thunar/thunar-icon-view.h>
4136-#include <thunar/thunar-launcher.h>
4137-#include <thunar/thunar-location-buttons.h>
4138-#include <thunar/thunar-location-dialog.h>
4139-#include <thunar/thunar-location-entry.h>
4140-#include <thunar/thunar-marshal.h>
4141-#include <thunar/thunar-pango-extensions.h>
4142-#include <thunar/thunar-preferences-dialog.h>
4143-#include <thunar/thunar-preferences.h>
4144-#include <thunar/thunar-private.h>
4145-#include <thunar/thunar-util.h>
4146-#include <thunar/thunar-statusbar.h>
4147-#include <thunar/thunar-stock.h>
4148-#include <thunar/thunar-trash-action.h>
4149-#include <thunar/thunar-tree-pane.h>
4150-#include <thunar/thunar-window.h>
4151-#include <thunar/thunar-window-ui.h>
4152-#include <thunar/thunar-device-monitor.h>
4153-
4154-#include <glib.h>
4155-
4156-
4157-
4158-/* Property identifiers */
4159-enum
4160-{
4161- PROP_0,
4162- PROP_CURRENT_DIRECTORY,
4163- PROP_SHOW_HIDDEN,
4164- PROP_UI_MANAGER,
4165- PROP_ZOOM_LEVEL,
4166-};
4167-
4168-/* Signal identifiers */
4169-enum
4170-{
4171- BACK,
4172- RELOAD,
4173- TOGGLE_SIDEPANE,
4174- TOGGLE_MENUBAR,
4175- ZOOM_IN,
4176- ZOOM_OUT,
4177- ZOOM_RESET,
4178- TAB_CHANGE,
4179- LAST_SIGNAL,
4180-};
4181-
4182-
4183-
4184-static void thunar_window_dispose (GObject *object);
4185-static void thunar_window_finalize (GObject *object);
4186-static void thunar_window_get_property (GObject *object,
4187- guint prop_id,
4188- GValue *value,
4189- GParamSpec *pspec);
4190-static void thunar_window_set_property (GObject *object,
4191- guint prop_id,
4192- const GValue *value,
4193- GParamSpec *pspec);
4194-static gboolean thunar_window_back (ThunarWindow *window);
4195-static gboolean thunar_window_reload (ThunarWindow *window);
4196-static gboolean thunar_window_toggle_sidepane (ThunarWindow *window);
4197-static gboolean thunar_window_toggle_menubar (ThunarWindow *window);
4198-static void thunar_window_toggle_menubar_deactivate (GtkWidget *menubar,
4199- ThunarWindow *window);
4200-static gboolean thunar_window_zoom_in (ThunarWindow *window);
4201-static gboolean thunar_window_zoom_out (ThunarWindow *window);
4202-static gboolean thunar_window_zoom_reset (ThunarWindow *window);
4203-static gboolean thunar_window_tab_change (ThunarWindow *window,
4204- gint nth);
4205-static void thunar_window_realize (GtkWidget *widget);
4206-static void thunar_window_unrealize (GtkWidget *widget);
4207-static gboolean thunar_window_configure_event (GtkWidget *widget,
4208- GdkEventConfigure *event);
4209-static void thunar_window_notebook_switch_page (GtkWidget *notebook,
4210- GtkWidget *page,
4211- guint page_num,
4212- ThunarWindow *window);
4213-static void thunar_window_notebook_page_added (GtkWidget *notebook,
4214- GtkWidget *page,
4215- guint page_num,
4216- ThunarWindow *window);
4217-static void thunar_window_notebook_page_removed (GtkWidget *notebook,
4218- GtkWidget *page,
4219- guint page_num,
4220- ThunarWindow *window);
4221-static gboolean thunar_window_notebook_button_press_event (GtkWidget *notebook,
4222- GdkEventButton *event,
4223- ThunarWindow *window);
4224-static gboolean thunar_window_notebook_popup_menu (GtkWidget *notebook,
4225- ThunarWindow *window);
4226-static gpointer thunar_window_notebook_create_window (GtkWidget *notebook,
4227- GtkWidget *page,
4228- gint x,
4229- gint y,
4230- ThunarWindow *window);
4231-static void thunar_window_notebook_insert (ThunarWindow *window,
4232- ThunarFile *directory);
4233-static void thunar_window_merge_custom_preferences (ThunarWindow *window);
4234-static gboolean thunar_window_bookmark_merge (gpointer user_data);
4235-static void thunar_window_merge_go_actions (ThunarWindow *window);
4236-static void thunar_window_install_location_bar (ThunarWindow *window,
4237- GType type);
4238-static void thunar_window_install_sidepane (ThunarWindow *window,
4239- GType type);
4240-static void thunar_window_start_open_location (ThunarWindow *window,
4241- const gchar *initial_text);
4242-static void thunar_window_action_open_new_tab (GtkAction *action,
4243- ThunarWindow *window);
4244-static void thunar_window_action_open_new_window (GtkAction *action,
4245- ThunarWindow *window);
4246-static void thunar_window_action_empty_trash (GtkAction *action,
4247- ThunarWindow *window);
4248-static void thunar_window_action_detach_tab (GtkAction *action,
4249- ThunarWindow *window);
4250-static void thunar_window_action_close_all_windows (GtkAction *action,
4251- ThunarWindow *window);
4252-static void thunar_window_action_close_tab (GtkAction *action,
4253- ThunarWindow *window);
4254-static void thunar_window_action_close_window (GtkAction *action,
4255- ThunarWindow *window);
4256-static void thunar_window_action_preferences (GtkAction *action,
4257- ThunarWindow *window);
4258-static void thunar_window_action_reload (GtkAction *action,
4259- ThunarWindow *window);
4260-static void thunar_window_action_pathbar_changed (GtkToggleAction *action,
4261- ThunarWindow *window);
4262-static void thunar_window_action_toolbar_changed (GtkToggleAction *action,
4263- ThunarWindow *window);
4264-static void thunar_window_action_shortcuts_changed (GtkToggleAction *action,
4265- ThunarWindow *window);
4266-static void thunar_window_action_tree_changed (GtkToggleAction *action,
4267- ThunarWindow *window);
4268-static void thunar_window_action_statusbar_changed (GtkToggleAction *action,
4269- ThunarWindow *window);
4270-static void thunar_window_action_menubar_changed (GtkToggleAction *action,
4271- ThunarWindow *window);
4272-static void thunar_window_action_zoom_in (GtkAction *action,
4273- ThunarWindow *window);
4274-static void thunar_window_action_zoom_out (GtkAction *action,
4275- ThunarWindow *window);
4276-static void thunar_window_action_zoom_reset (GtkAction *action,
4277- ThunarWindow *window);
4278-static void thunar_window_action_view_changed (GtkRadioAction *action,
4279- GtkRadioAction *current,
4280- ThunarWindow *window);
4281-static void thunar_window_action_go_up (GtkAction *action,
4282- ThunarWindow *window);
4283-static void thunar_window_action_open_home (GtkAction *action,
4284- ThunarWindow *window);
4285-static void thunar_window_action_open_desktop (GtkAction *action,
4286- ThunarWindow *window);
4287-static void thunar_window_action_open_templates (GtkAction *action,
4288- ThunarWindow *window);
4289-static void thunar_window_action_open_file_system (GtkAction *action,
4290- ThunarWindow *window);
4291-static void thunar_window_action_open_trash (GtkAction *action,
4292- ThunarWindow *window);
4293-static void thunar_window_action_open_network (GtkAction *action,
4294- ThunarWindow *window);
4295-static void thunar_window_action_open_bookmark (GtkAction *action,
4296- ThunarWindow *window);
4297-static void thunar_window_action_open_location (GtkAction *action,
4298- ThunarWindow *window);
4299-static void thunar_window_action_contents (GtkAction *action,
4300- ThunarWindow *window);
4301-static void thunar_window_action_about (GtkAction *action,
4302- ThunarWindow *window);
4303-static void thunar_window_action_show_hidden (GtkToggleAction *action,
4304- ThunarWindow *window);
4305-static void thunar_window_current_directory_changed (ThunarFile *current_directory,
4306- ThunarWindow *window);
4307-static void thunar_window_connect_proxy (GtkUIManager *manager,
4308- GtkAction *action,
4309- GtkWidget *proxy,
4310- ThunarWindow *window);
4311-static void thunar_window_disconnect_proxy (GtkUIManager *manager,
4312- GtkAction *action,
4313- GtkWidget *proxy,
4314- ThunarWindow *window);
4315-static void thunar_window_menu_item_selected (GtkWidget *menu_item,
4316- ThunarWindow *window);
4317-static void thunar_window_menu_item_deselected (GtkWidget *menu_item,
4318- ThunarWindow *window);
4319-static void thunar_window_update_custom_actions (ThunarView *view,
4320- GParamSpec *pspec,
4321- ThunarWindow *window);
4322-static void thunar_window_notify_loading (ThunarView *view,
4323- GParamSpec *pspec,
4324- ThunarWindow *window);
4325-static void thunar_window_device_pre_unmount (ThunarDeviceMonitor *device_monitor,
4326- ThunarDevice *device,
4327- GFile *root_file,
4328- ThunarWindow *window);
4329-static void thunar_window_device_changed (ThunarDeviceMonitor *device_monitor,
4330- ThunarDevice *device,
4331- ThunarWindow *window);
4332-static gboolean thunar_window_merge_idle (gpointer user_data);
4333-static void thunar_window_merge_idle_destroy (gpointer user_data);
4334-static gboolean thunar_window_save_paned (ThunarWindow *window);
4335-static gboolean thunar_window_save_geometry_timer (gpointer user_data);
4336-static void thunar_window_save_geometry_timer_destroy (gpointer user_data);
4337-static void thunar_window_set_zoom_level (ThunarWindow *window,
4338- ThunarZoomLevel zoom_level);
4339-
4340-
4341-
4342-struct _ThunarWindowClass
4343-{
4344- GtkWindowClass __parent__;
4345-
4346- /* internal action signals */
4347- gboolean (*back) (ThunarWindow *window);
4348- gboolean (*reload) (ThunarWindow *window);
4349- gboolean (*toggle_sidepane) (ThunarWindow *window);
4350- gboolean (*toggle_menubar) (ThunarWindow *window);
4351- gboolean (*zoom_in) (ThunarWindow *window);
4352- gboolean (*zoom_out) (ThunarWindow *window);
4353- gboolean (*zoom_reset) (ThunarWindow *window);
4354- gboolean (*tab_change) (ThunarWindow *window,
4355- gint idx);
4356-};
4357-
4358-struct _ThunarWindow
4359-{
4360- GtkWindow __parent__;
4361-
4362- /* support for custom preferences actions */
4363- ThunarxProviderFactory *provider_factory;
4364- guint custom_preferences_merge_id;
4365-
4366- /* UI manager merge ID for go menu actions */
4367- guint go_items_actions_merge_id;
4368-
4369- /* UI manager merge ID for the bookmark actions */
4370- guint bookmark_items_actions_merge_id;
4371- GtkActionGroup *bookmark_action_group;
4372- GFile *bookmark_file;
4373- GFileMonitor *bookmark_monitor;
4374- guint bookmark_reload_idle_id;
4375-
4376- ThunarClipboardManager *clipboard;
4377-
4378- ThunarPreferences *preferences;
4379-
4380- ThunarIconFactory *icon_factory;
4381-
4382- GtkActionGroup *action_group;
4383- GtkUIManager *ui_manager;
4384-
4385- /* to be able to change folder on "device-pre-unmount" if required */
4386- ThunarDeviceMonitor *device_monitor;
4387-
4388- /* closures for the menu_item_selected()/menu_item_deselected() callbacks */
4389- GClosure *menu_item_selected_closure;
4390- GClosure *menu_item_deselected_closure;
4391-
4392- /* custom menu actions for the file menu */
4393- GtkActionGroup *custom_actions;
4394- guint custom_merge_id;
4395-
4396- GtkWidget *table;
4397- GtkWidget *menubar;
4398- GtkWidget *spinner;
4399- GtkWidget *paned;
4400- GtkWidget *sidepane;
4401- GtkWidget *view_box;
4402- GtkWidget *notebook;
4403- GtkWidget *view;
4404- GtkWidget *statusbar;
4405-
4406- GType view_type;
4407- GSList *view_bindings;
4408-
4409- /* support for two different styles of location bars */
4410- GtkWidget *location_bar;
4411- GtkWidget *location_toolbar;
4412-
4413- ThunarLauncher *launcher;
4414-
4415- ThunarFile *current_directory;
4416-
4417- /* zoom-level support */
4418- ThunarZoomLevel zoom_level;
4419-
4420- /* menu merge idle source */
4421- guint merge_idle_id;
4422-
4423- /* support to remember window geometry */
4424- guint save_geometry_timer_id;
4425-
4426- /* support to toggle side pane using F9,
4427- * see the toggle_sidepane() function.
4428- */
4429- GType toggle_sidepane_type;
4430-};
4431-
4432-
4433-
4434-static GtkActionEntry action_entries[] =
4435-{
4436- { "file-menu", NULL, N_ ("_File"), NULL, },
4437- { "new-tab", "tab-new", N_ ("New _Tab"), "<control>T", N_ ("Open a new tab for the displayed location"), G_CALLBACK (thunar_window_action_open_new_tab), },
4438- { "new-window", "window-new", N_ ("New _Window"), "<control>N", N_ ("Open a new Thunar window for the displayed location"), G_CALLBACK (thunar_window_action_open_new_window), },
4439- { "sendto-menu", NULL, N_ ("_Send To"), NULL, },
4440- { "empty-trash", NULL, N_ ("_Empty Trash"), NULL, N_ ("Delete all files and folders in the Trash"), G_CALLBACK (thunar_window_action_empty_trash), },
4441- { "detach-tab", NULL, N_ ("Detac_h Tab"), NULL, N_ ("Open current folder in a new window"), G_CALLBACK (thunar_window_action_detach_tab), },
4442- { "close-all-windows", NULL, N_ ("Close _All Windows"), "<control><shift>W", N_ ("Close all Thunar windows"), G_CALLBACK (thunar_window_action_close_all_windows), },
4443- { "close-tab", GTK_STOCK_CLOSE, N_ ("C_lose Tab"), "<control>W", N_ ("Close this folder"), G_CALLBACK (thunar_window_action_close_tab), },
4444- { "close-window", GTK_STOCK_QUIT, N_ ("_Close Window"), "<control>Q", N_ ("Close this window"), G_CALLBACK (thunar_window_action_close_window), },
4445- { "edit-menu", NULL, N_ ("_Edit"), NULL, },
4446- { "preferences", GTK_STOCK_PREFERENCES, N_ ("Pr_eferences..."), NULL, N_ ("Edit Thunars Preferences"), G_CALLBACK (thunar_window_action_preferences), },
4447- { "view-menu", NULL, N_ ("_View"), NULL, },
4448- { "reload", GTK_STOCK_REFRESH, N_ ("_Reload"), "<control>R", N_ ("Reload the current folder"), G_CALLBACK (thunar_window_action_reload), },
4449- { "view-location-selector-menu", NULL, N_ ("_Location Selector"), NULL, },
4450- { "view-side-pane-menu", NULL, N_ ("_Side Pane"), NULL, },
4451- { "zoom-in", GTK_STOCK_ZOOM_IN, N_ ("Zoom I_n"), "<control>plus", N_ ("Show the contents in more detail"), G_CALLBACK (thunar_window_action_zoom_in), },
4452- { "zoom-out", GTK_STOCK_ZOOM_OUT, N_ ("Zoom _Out"), "<control>minus", N_ ("Show the contents in less detail"), G_CALLBACK (thunar_window_action_zoom_out), },
4453- { "zoom-reset", GTK_STOCK_ZOOM_100, N_ ("Normal Si_ze"), "<control>0", N_ ("Show the contents at the normal size"), G_CALLBACK (thunar_window_action_zoom_reset), },
4454- { "go-menu", NULL, N_ ("_Go"), NULL, },
4455- { "open-parent", GTK_STOCK_GO_UP, N_ ("Open _Parent"), "<alt>Up", N_ ("Open the parent folder"), G_CALLBACK (thunar_window_action_go_up), },
4456- { "open-home", GTK_STOCK_HOME, N_ ("_Home"), "<alt>Home", N_ ("Go to the home folder"), G_CALLBACK (thunar_window_action_open_home), },
4457- { "open-desktop", THUNAR_STOCK_DESKTOP, N_ ("Desktop"), NULL, N_ ("Go to the desktop folder"), G_CALLBACK (thunar_window_action_open_desktop), },
4458- { "open-file-system", GTK_STOCK_HARDDISK, N_ ("File System"), NULL, N_ ("Browse the file system"), G_CALLBACK (thunar_window_action_open_file_system), },
4459- { "open-network", GTK_STOCK_NETWORK, N_("B_rowse Network"), NULL, N_ ("Browse local network connections"), G_CALLBACK (thunar_window_action_open_network), },
4460- { "open-templates", THUNAR_STOCK_TEMPLATES, N_("T_emplates"), NULL, N_ ("Go to the templates folder"), G_CALLBACK (thunar_window_action_open_templates), },
4461- { "open-location", NULL, N_ ("_Open Location..."), "<control>L", N_ ("Specify a location to open"), G_CALLBACK (thunar_window_action_open_location), },
4462- { "help-menu", NULL, N_ ("_Help"), NULL, },
4463- { "contents", GTK_STOCK_HELP, N_ ("_Contents"), "F1", N_ ("Display Thunar user manual"), G_CALLBACK (thunar_window_action_contents), },
4464- { "about", GTK_STOCK_ABOUT, N_ ("_About"), NULL, N_ ("Display information about Thunar"), G_CALLBACK (thunar_window_action_about), },
4465-};
4466-
4467-static const GtkToggleActionEntry toggle_action_entries[] =
4468-{
4469- { "show-hidden", NULL, N_ ("Show _Hidden Files"), "<control>H", N_ ("Toggles the display of hidden files in the current window"), G_CALLBACK (thunar_window_action_show_hidden), FALSE, },
4470- { "view-location-selector-pathbar", NULL, N_ ("_Pathbar Style"), NULL, N_ ("Modern approach with buttons that correspond to folders"), G_CALLBACK (thunar_window_action_pathbar_changed), FALSE, },
4471- { "view-location-selector-toolbar", NULL, N_ ("_Toolbar Style"), NULL, N_ ("Traditional approach with location bar and navigation buttons"), G_CALLBACK (thunar_window_action_toolbar_changed), FALSE, },
4472- { "view-side-pane-shortcuts", NULL, N_ ("_Shortcuts"), "<control>B", N_ ("Toggles the visibility of the shortcuts pane"), G_CALLBACK (thunar_window_action_shortcuts_changed), FALSE, },
4473- { "view-side-pane-tree", NULL, N_ ("_Tree"), "<control>E", N_ ("Toggles the visibility of the tree pane"), G_CALLBACK (thunar_window_action_tree_changed), FALSE, },
4474- { "view-statusbar", NULL, N_ ("St_atusbar"), NULL, N_ ("Change the visibility of this window's statusbar"), G_CALLBACK (thunar_window_action_statusbar_changed), FALSE, },
4475- { "view-menubar", NULL, N_ ("_Menubar"), "<control>M", N_ ("Change the visibility of this window's menubar"), G_CALLBACK (thunar_window_action_menubar_changed), TRUE, },
4476-};
4477-
4478-
4479-
4480-static guint window_signals[LAST_SIGNAL];
4481-
4482-
4483-
4484-G_DEFINE_TYPE_WITH_CODE (ThunarWindow, thunar_window, GTK_TYPE_WINDOW,
4485- G_IMPLEMENT_INTERFACE (THUNAR_TYPE_BROWSER, NULL))
4486-
4487-
4488-
4489-static void
4490-thunar_window_class_init (ThunarWindowClass *klass)
4491-{
4492- GtkWidgetClass *gtkwidget_class;
4493- GtkBindingSet *binding_set;
4494- GObjectClass *gobject_class;
4495- guint i;
4496-
4497- gobject_class = G_OBJECT_CLASS (klass);
4498- gobject_class->dispose = thunar_window_dispose;
4499- gobject_class->finalize = thunar_window_finalize;
4500- gobject_class->get_property = thunar_window_get_property;
4501- gobject_class->set_property = thunar_window_set_property;
4502-
4503- gtkwidget_class = GTK_WIDGET_CLASS (klass);
4504- gtkwidget_class->realize = thunar_window_realize;
4505- gtkwidget_class->unrealize = thunar_window_unrealize;
4506- gtkwidget_class->configure_event = thunar_window_configure_event;
4507-
4508- klass->back = thunar_window_back;
4509- klass->reload = thunar_window_reload;
4510- klass->toggle_sidepane = thunar_window_toggle_sidepane;
4511- klass->toggle_menubar = thunar_window_toggle_menubar;
4512- klass->zoom_in = thunar_window_zoom_in;
4513- klass->zoom_out = thunar_window_zoom_out;
4514- klass->zoom_reset = thunar_window_zoom_reset;
4515- klass->tab_change = thunar_window_tab_change;
4516-
4517- /**
4518- * ThunarWindow:current-directory:
4519- *
4520- * The directory currently displayed within this #ThunarWindow
4521- * or %NULL.
4522- **/
4523- g_object_class_install_property (gobject_class,
4524- PROP_CURRENT_DIRECTORY,
4525- g_param_spec_object ("current-directory",
4526- "current-directory",
4527- "current-directory",
4528- THUNAR_TYPE_FILE,
4529- EXO_PARAM_READWRITE));
4530-
4531- /**
4532- * ThunarWindow:show-hidden:
4533- *
4534- * Whether to show hidden files in the current window.
4535- **/
4536- g_object_class_install_property (gobject_class,
4537- PROP_SHOW_HIDDEN,
4538- g_param_spec_boolean ("show-hidden",
4539- "show-hidden",
4540- "show-hidden",
4541- FALSE,
4542- EXO_PARAM_READABLE));
4543-
4544- /**
4545- * ThunarWindow:ui-manager:
4546- *
4547- * The #GtkUIManager used for this #ThunarWindow. This property
4548- * can only be read and is garantied to always contain a valid
4549- * #GtkUIManager instance (thus it's never %NULL).
4550- **/
4551- g_object_class_install_property (gobject_class,
4552- PROP_UI_MANAGER,
4553- g_param_spec_object ("ui-manager",
4554- "ui-manager",
4555- "ui-manager",
4556- GTK_TYPE_UI_MANAGER,
4557- EXO_PARAM_READABLE));
4558-
4559- /**
4560- * ThunarWindow:zoom-level:
4561- *
4562- * The #ThunarZoomLevel applied to the #ThunarView currently
4563- * shown within this window.
4564- **/
4565- g_object_class_install_property (gobject_class,
4566- PROP_ZOOM_LEVEL,
4567- g_param_spec_enum ("zoom-level",
4568- "zoom-level",
4569- "zoom-level",
4570- THUNAR_TYPE_ZOOM_LEVEL,
4571- THUNAR_ZOOM_LEVEL_NORMAL,
4572- EXO_PARAM_READWRITE));
4573-
4574- /**
4575- * ThunarWindow::back:
4576- * @window : a #ThunarWindow instance.
4577- *
4578- * Emitted whenever the user requests to go to the
4579- * previous visited folder. This is an internal
4580- * signal used to bind the action to keys.
4581- **/
4582- window_signals[BACK] =
4583- g_signal_new (I_("back"),
4584- G_TYPE_FROM_CLASS (klass),
4585- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4586- G_STRUCT_OFFSET (ThunarWindowClass, back),
4587- g_signal_accumulator_true_handled, NULL,
4588- _thunar_marshal_BOOLEAN__VOID,
4589- G_TYPE_BOOLEAN, 0);
4590-
4591- /**
4592- * ThunarWindow::reload:
4593- * @window : a #ThunarWindow instance.
4594- *
4595- * Emitted whenever the user requests to reload the contents
4596- * of the currently displayed folder. This is an internal
4597- * signal used to bind the action to keys.
4598- **/
4599- window_signals[RELOAD] =
4600- g_signal_new (I_("reload"),
4601- G_TYPE_FROM_CLASS (klass),
4602- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4603- G_STRUCT_OFFSET (ThunarWindowClass, reload),
4604- g_signal_accumulator_true_handled, NULL,
4605- _thunar_marshal_BOOLEAN__VOID,
4606- G_TYPE_BOOLEAN, 0);
4607-
4608- /**
4609- * ThunarWindow::toggle-sidepane:
4610- * @window : a #ThunarWindow instance.
4611- *
4612- * Emitted whenever the user toggles the visibility of the
4613- * sidepane. This is an internal signal used to bind the
4614- * action to keys.
4615- **/
4616- window_signals[TOGGLE_SIDEPANE] =
4617- g_signal_new (I_("toggle-sidepane"),
4618- G_TYPE_FROM_CLASS (klass),
4619- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4620- G_STRUCT_OFFSET (ThunarWindowClass, toggle_sidepane),
4621- g_signal_accumulator_true_handled, NULL,
4622- _thunar_marshal_BOOLEAN__VOID,
4623- G_TYPE_BOOLEAN, 0);
4624-
4625- /**
4626- * ThunarWindow::toggle-sidepane:
4627- * @window : a #ThunarWindow instance.
4628- *
4629- * Emitted whenever the user toggles the visibility of the
4630- * sidepane. This is an internal signal used to bind the
4631- * action to keys.
4632- **/
4633- window_signals[TOGGLE_MENUBAR] =
4634- g_signal_new (I_("toggle-menubar"),
4635- G_TYPE_FROM_CLASS (klass),
4636- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4637- G_STRUCT_OFFSET (ThunarWindowClass, toggle_menubar),
4638- g_signal_accumulator_true_handled, NULL,
4639- _thunar_marshal_BOOLEAN__VOID,
4640- G_TYPE_BOOLEAN, 0);
4641-
4642- /**
4643- * ThunarWindow::zoom-in:
4644- * @window : a #ThunarWindow instance.
4645- *
4646- * Emitted whenever the user requests to zoom in. This
4647- * is an internal signal used to bind the action to keys.
4648- **/
4649- window_signals[ZOOM_IN] =
4650- g_signal_new (I_("zoom-in"),
4651- G_TYPE_FROM_CLASS (klass),
4652- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4653- G_STRUCT_OFFSET (ThunarWindowClass, zoom_in),
4654- g_signal_accumulator_true_handled, NULL,
4655- _thunar_marshal_BOOLEAN__VOID,
4656- G_TYPE_BOOLEAN, 0);
4657-
4658- /**
4659- * ThunarWindow::zoom-out:
4660- * @window : a #ThunarWindow instance.
4661- *
4662- * Emitted whenever the user requests to zoom out. This
4663- * is an internal signal used to bind the action to keys.
4664- **/
4665- window_signals[ZOOM_OUT] =
4666- g_signal_new (I_("zoom-out"),
4667- G_TYPE_FROM_CLASS (klass),
4668- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4669- G_STRUCT_OFFSET (ThunarWindowClass, zoom_out),
4670- g_signal_accumulator_true_handled, NULL,
4671- _thunar_marshal_BOOLEAN__VOID,
4672- G_TYPE_BOOLEAN, 0);
4673-
4674- /**
4675- * ThunarWindow::zoom-reset:
4676- * @window : a #ThunarWindow instance.
4677- *
4678- * Emitted whenever the user requests reset the zoom level.
4679- * This is an internal signal used to bind the action to keys.
4680- **/
4681- window_signals[ZOOM_RESET] =
4682- g_signal_new (I_("zoom-reset"),
4683- G_TYPE_FROM_CLASS (klass),
4684- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4685- G_STRUCT_OFFSET (ThunarWindowClass, zoom_reset),
4686- g_signal_accumulator_true_handled, NULL,
4687- _thunar_marshal_BOOLEAN__VOID,
4688- G_TYPE_BOOLEAN, 0);
4689-
4690- /**
4691- * ThunarWindow::tab-chage:
4692- * @window : a #ThunarWindow instance.
4693- * @idx : tab index,
4694- *
4695- * Emitted whenever the user uses a Alt+N combination to
4696- * switch tabs.
4697- **/
4698- window_signals[TAB_CHANGE] =
4699- g_signal_new (I_("tab-change"),
4700- G_TYPE_FROM_CLASS (klass),
4701- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4702- G_STRUCT_OFFSET (ThunarWindowClass, tab_change),
4703- g_signal_accumulator_true_handled, NULL,
4704- _thunar_marshal_BOOLEAN__INT,
4705- G_TYPE_BOOLEAN, 1,
4706- G_TYPE_INT);
4707-
4708- /* setup the key bindings for the windows */
4709- binding_set = gtk_binding_set_by_class (klass);
4710- gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "back", 0);
4711- gtk_binding_entry_add_signal (binding_set, GDK_F5, 0, "reload", 0);
4712- gtk_binding_entry_add_signal (binding_set, GDK_F9, 0, "toggle-sidepane", 0);
4713- gtk_binding_entry_add_signal (binding_set, GDK_F10, 0, "toggle-menubar", 0);
4714- gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_CONTROL_MASK, "zoom-in", 0);
4715- gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_CONTROL_MASK, "zoom-out", 0);
4716- gtk_binding_entry_add_signal (binding_set, GDK_KP_0, GDK_CONTROL_MASK, "zoom-reset", 0);
4717- gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, GDK_CONTROL_MASK, "zoom-reset", 0);
4718-
4719- /* setup the key bindings for Alt+N */
4720- for (i = 0; i < 10; i++)
4721- {
4722- gtk_binding_entry_add_signal (binding_set, GDK_0 + i, GDK_MOD1_MASK,
4723- "tab-change", 1, G_TYPE_UINT, i - 1);
4724- }
4725-}
4726-
4727-
4728-
4729-static inline gint
4730-view_type2index (GType type)
4731-{
4732- /* this necessary for platforms where sizeof(GType) != sizeof(gint),
4733- * see http://bugzilla.xfce.org/show_bug.cgi?id=2726 for details.
4734- */
4735- if (sizeof (GType) == sizeof (gint))
4736- {
4737- /* no need to map anything */
4738- return (gint) type;
4739- }
4740- else
4741- {
4742- /* map from types to unique indices */
4743- if (G_LIKELY (type == THUNAR_TYPE_COMPACT_VIEW))
4744- return 0;
4745- else if (type == THUNAR_TYPE_DETAILS_VIEW)
4746- return 1;
4747- else
4748- return 2;
4749- }
4750-}
4751-
4752-
4753-
4754-static inline GType
4755-view_index2type (gint idx)
4756-{
4757- /* this necessary for platforms where sizeof(GType) != sizeof(gint),
4758- * see http://bugzilla.xfce.org/show_bug.cgi?id=2726 for details.
4759- */
4760- if (sizeof (GType) == sizeof (gint))
4761- {
4762- /* no need to map anything */
4763- return (GType) idx;
4764- }
4765- else
4766- {
4767- /* map from indices to unique types */
4768- switch (idx)
4769- {
4770- case 0: return THUNAR_TYPE_COMPACT_VIEW;
4771- case 1: return THUNAR_TYPE_DETAILS_VIEW;
4772- default: return THUNAR_TYPE_ICON_VIEW;
4773- }
4774- }
4775-}
4776-
4777-
4778-
4779-static void
4780-thunar_window_init (ThunarWindow *window)
4781-{
4782- GtkRadioAction *radio_action;
4783- GtkAccelGroup *accel_group;
4784- GtkWidget *label;
4785- GtkWidget *infobar;
4786- GtkWidget *item;
4787- GtkAction *action;
4788- gboolean last_show_hidden;
4789- gboolean last_menubar_visible;
4790- GSList *group;
4791- gchar *last_location_bar;
4792- gchar *last_side_pane;
4793- GType type;
4794- gint last_separator_position;
4795- gint last_window_width;
4796- gint last_window_height;
4797- gboolean last_window_maximized;
4798- gboolean last_statusbar_visible;
4799- GtkRcStyle *style;
4800-
4801- /* unset the view type */
4802- window->view_type = G_TYPE_NONE;
4803-
4804- /* grab a reference on the provider factory */
4805- window->provider_factory = thunarx_provider_factory_get_default ();
4806-
4807- /* grab a reference on the preferences */
4808- window->preferences = thunar_preferences_get ();
4809-
4810- /* get all properties for init */
4811- g_object_get (G_OBJECT (window->preferences),
4812- "last-show-hidden", &last_show_hidden,
4813- "last-window-width", &last_window_width,
4814- "last-window-height", &last_window_height,
4815- "last-window-maximized", &last_window_maximized,
4816- "last-menubar-visible", &last_menubar_visible,
4817- "last-separator-position", &last_separator_position,
4818- "last-location-bar", &last_location_bar,
4819- "last-side-pane", &last_side_pane,
4820- "last-statusbar-visible", &last_statusbar_visible,
4821- NULL);
4822-
4823- /* connect to the volume monitor */
4824- window->device_monitor = thunar_device_monitor_get ();
4825- g_signal_connect (window->device_monitor, "device-pre-unmount", G_CALLBACK (thunar_window_device_pre_unmount), window);
4826- g_signal_connect (window->device_monitor, "device-removed", G_CALLBACK (thunar_window_device_changed), window);
4827- g_signal_connect (window->device_monitor, "device-changed", G_CALLBACK (thunar_window_device_changed), window);
4828-
4829- /* allocate a closure for the menu_item_selected() callback */
4830- window->menu_item_selected_closure = g_cclosure_new_object (G_CALLBACK (thunar_window_menu_item_selected), G_OBJECT (window));
4831- g_closure_ref (window->menu_item_selected_closure);
4832- g_closure_sink (window->menu_item_selected_closure);
4833-
4834- /* allocate a closure for the menu_item_deselected() callback */
4835- window->menu_item_deselected_closure = g_cclosure_new_object (G_CALLBACK (thunar_window_menu_item_deselected), G_OBJECT (window));
4836- g_closure_ref (window->menu_item_deselected_closure);
4837- g_closure_sink (window->menu_item_deselected_closure);
4838- window->icon_factory = thunar_icon_factory_get_default ();
4839-
4840- /* setup the action group for this window */
4841- window->action_group = gtk_action_group_new ("ThunarWindow");
4842- gtk_action_group_set_translation_domain (window->action_group, GETTEXT_PACKAGE);
4843- gtk_action_group_add_actions (window->action_group, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));
4844- gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
4845-
4846- /* initialize the "show-hidden" action using the last value from the preferences */
4847- action = gtk_action_group_get_action (window->action_group, "show-hidden");
4848- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), last_show_hidden);
4849-
4850- /*
4851- * add view options
4852- */
4853- radio_action = gtk_radio_action_new ("view-as-icons", _("View as _Icons"), _("Display folder content in an icon view"),
4854- NULL, view_type2index (THUNAR_TYPE_ICON_VIEW));
4855- gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (radio_action), "<control>1");
4856- gtk_radio_action_set_group (radio_action, NULL);
4857- group = gtk_radio_action_get_group (radio_action);
4858- g_object_unref (G_OBJECT (radio_action));
4859-
4860- radio_action = gtk_radio_action_new ("view-as-detailed-list", _("View as _Detailed List"), _("Display folder content in a detailed list view"),
4861- NULL, view_type2index (THUNAR_TYPE_DETAILS_VIEW));
4862- gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (radio_action), "<control>2");
4863- gtk_radio_action_set_group (radio_action, group);
4864- group = gtk_radio_action_get_group (radio_action);
4865- g_object_unref (G_OBJECT (radio_action));
4866-
4867- radio_action = gtk_radio_action_new ("view-as-compact-list", _("View as _Compact List"), _("Display folder content in a compact list view"),
4868- NULL, view_type2index (THUNAR_TYPE_COMPACT_VIEW));
4869- gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (radio_action), "<control>3");
4870- gtk_radio_action_set_group (radio_action, group);
4871- group = gtk_radio_action_get_group (radio_action);
4872- g_object_unref (G_OBJECT (radio_action));
4873-
4874- window->ui_manager = gtk_ui_manager_new ();
4875- g_signal_connect (G_OBJECT (window->ui_manager), "connect-proxy", G_CALLBACK (thunar_window_connect_proxy), window);
4876- g_signal_connect (G_OBJECT (window->ui_manager), "disconnect-proxy", G_CALLBACK (thunar_window_disconnect_proxy), window);
4877- gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0);
4878- gtk_ui_manager_add_ui_from_string (window->ui_manager, thunar_window_ui, thunar_window_ui_length, NULL);
4879-
4880- accel_group = gtk_ui_manager_get_accel_group (window->ui_manager);
4881- gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4882-
4883- /* setup the launcher support */
4884- window->launcher = thunar_launcher_new ();
4885- thunar_launcher_set_widget (window->launcher, GTK_WIDGET (window));
4886- thunar_component_set_ui_manager (THUNAR_COMPONENT (window->launcher), window->ui_manager);
4887- exo_binding_new (G_OBJECT (window), "current-directory", G_OBJECT (window->launcher), "current-directory");
4888- g_signal_connect_swapped (G_OBJECT (window->launcher), "change-directory", G_CALLBACK (thunar_window_set_current_directory), window);
4889- g_signal_connect_swapped (G_OBJECT (window->launcher), "open-new-tab", G_CALLBACK (thunar_window_notebook_insert), window);
4890-
4891- /* determine the default window size from the preferences */
4892- gtk_window_set_default_size (GTK_WINDOW (window), last_window_width, last_window_height);
4893-
4894- /* restore the maxized state of the window */
4895- if (G_UNLIKELY (last_window_maximized))
4896- gtk_window_maximize (GTK_WINDOW (window));
4897-
4898- window->table = gtk_table_new (6, 1, FALSE);
4899- gtk_container_add (GTK_CONTAINER (window), window->table);
4900- gtk_widget_show (window->table);
4901-
4902- window->menubar = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu");
4903- gtk_table_attach (GTK_TABLE (window->table), window->menubar, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
4904-
4905- /* update menubar visibiliy */
4906- action = gtk_action_group_get_action (window->action_group, "view-menubar");
4907- g_signal_connect (G_OBJECT (window->menubar), "deactivate", G_CALLBACK (thunar_window_toggle_menubar_deactivate), window);
4908- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), last_menubar_visible);
4909-
4910- /* append the menu item for the spinner */
4911- item = gtk_menu_item_new ();
4912- gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
4913- gtk_menu_item_set_right_justified (GTK_MENU_ITEM (item), TRUE);
4914- gtk_menu_shell_append (GTK_MENU_SHELL (window->menubar), item);
4915- gtk_widget_show (item);
4916-
4917- /* place the spinner into the menu item */
4918- window->spinner = gtk_spinner_new ();
4919- gtk_container_add (GTK_CONTAINER (item), window->spinner);
4920- exo_binding_new (G_OBJECT (window->spinner), "active",
4921- G_OBJECT (window->spinner), "visible");
4922-
4923- /* check if we need to add the root warning */
4924- if (G_UNLIKELY (geteuid () == 0))
4925- {
4926- /* add the bar for the root warning */
4927- infobar = gtk_info_bar_new ();
4928- gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_WARNING);
4929- gtk_table_attach (GTK_TABLE (window->table), infobar, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
4930- gtk_widget_show (infobar);
4931-
4932- /* add the label with the root warning */
4933- label = gtk_label_new (_("Warning, you are using the root account, you may harm your system."));
4934- gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))), label);
4935- gtk_widget_show (label);
4936- }
4937-
4938- window->paned = gtk_hpaned_new ();
4939- gtk_container_set_border_width (GTK_CONTAINER (window->paned), 0);
4940- gtk_table_attach (GTK_TABLE (window->table), window->paned, 0, 1, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
4941- gtk_widget_show (window->paned);
4942-
4943- /* determine the last separator position and apply it to the paned view */
4944- gtk_paned_set_position (GTK_PANED (window->paned), last_separator_position);
4945- g_signal_connect_swapped (window->paned, "accept-position", G_CALLBACK (thunar_window_save_paned), window);
4946- g_signal_connect_swapped (window->paned, "button-release-event", G_CALLBACK (thunar_window_save_paned), window);
4947-
4948- window->view_box = gtk_table_new (3, 1, FALSE);
4949- gtk_paned_pack2 (GTK_PANED (window->paned), window->view_box, TRUE, FALSE);
4950- gtk_widget_show (window->view_box);
4951-
4952- /* tabs */
4953- window->notebook = gtk_notebook_new ();
4954- gtk_table_attach (GTK_TABLE (window->view_box), window->notebook, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
4955- g_signal_connect (G_OBJECT (window->notebook), "switch-page", G_CALLBACK (thunar_window_notebook_switch_page), window);
4956- g_signal_connect (G_OBJECT (window->notebook), "page-added", G_CALLBACK (thunar_window_notebook_page_added), window);
4957- g_signal_connect (G_OBJECT (window->notebook), "page-removed", G_CALLBACK (thunar_window_notebook_page_removed), window);
4958- g_signal_connect_after (G_OBJECT (window->notebook), "button-press-event", G_CALLBACK (thunar_window_notebook_button_press_event), window);
4959- g_signal_connect (G_OBJECT (window->notebook), "popup-menu", G_CALLBACK (thunar_window_notebook_popup_menu), window);
4960- g_signal_connect (G_OBJECT (window->notebook), "create-window", G_CALLBACK (thunar_window_notebook_create_window), window);
4961- gtk_notebook_set_show_border (GTK_NOTEBOOK (window->notebook), FALSE);
4962- gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (window->notebook), TRUE);
4963- gtk_notebook_set_scrollable (GTK_NOTEBOOK (window->notebook), TRUE);
4964- gtk_container_set_border_width (GTK_CONTAINER (window->notebook), 0);
4965- gtk_notebook_set_group_name (GTK_NOTEBOOK (window->notebook), "thunar-tabs");
4966- gtk_widget_show (window->notebook);
4967-
4968- /* drop the notebook borders */
4969- style = gtk_rc_style_new ();
4970- style->xthickness = style->ythickness = 0;
4971- gtk_widget_modify_style (window->notebook, style);
4972- g_object_unref (G_OBJECT (style));
4973-
4974- /* determine the selected location selector */
4975- if (exo_str_is_equal (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_BUTTONS)))
4976- type = THUNAR_TYPE_LOCATION_BUTTONS;
4977- else if (exo_str_is_equal (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_ENTRY)))
4978- type = THUNAR_TYPE_LOCATION_ENTRY;
4979- else
4980- type = G_TYPE_NONE;
4981- g_free (last_location_bar);
4982-
4983- /* activate the selected location selector */
4984- action = gtk_action_group_get_action (window->action_group, "view-location-selector-pathbar");
4985- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), (type == THUNAR_TYPE_LOCATION_BUTTONS));
4986- action = gtk_action_group_get_action (window->action_group, "view-location-selector-toolbar");
4987- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), (type == THUNAR_TYPE_LOCATION_ENTRY));
4988-
4989- /* determine the selected side pane (FIXME: Should probably be last-shortcuts-visible and last-tree-visible preferences) */
4990- if (exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_SHORTCUTS_PANE)))
4991- type = THUNAR_TYPE_SHORTCUTS_PANE;
4992- else if (exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_TREE_PANE)))
4993- type = THUNAR_TYPE_TREE_PANE;
4994- else
4995- type = G_TYPE_NONE;
4996- g_free (last_side_pane);
4997-
4998- /* activate the selected side pane */
4999- action = gtk_action_group_get_action (window->action_group, "view-side-pane-shortcuts");
5000- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), (type == THUNAR_TYPE_SHORTCUTS_PANE));
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: