Merging upstream version 0.9.7.
[debian/pcmanfm.git] / src / pcmanfm.c
CommitLineData
92978c90
DB
1/*
2 * pcmanfm.c
3 *
4 * Copyright 2009 - 2010 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
26#include <gtk/gtk.h>
27#include <stdio.h>
28#include <glib/gi18n.h>
29
30#include <stdlib.h>
31#include <string.h>
32/* socket is used to keep single instance */
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <sys/un.h>
36#include <signal.h>
37#include <unistd.h> /* for getcwd */
38
39#include <libfm/fm-gtk.h>
40#include "app-config.h"
41#include "main-win.h"
42#include "desktop.h"
43#include "volume-manager.h"
44#include "pref.h"
45#include "pcmanfm.h"
46
47static int sock;
48GIOChannel* io_channel = NULL;
49
50gboolean daemon_mode = FALSE;
51
52static char** files_to_open = NULL;
53static char* profile = NULL;
54static char* config_name = NULL;
55static gboolean no_desktop = FALSE;
56static gboolean show_desktop = FALSE;
57static gboolean desktop_off = FALSE;
58static gboolean desktop_running = FALSE;
59/* static gboolean new_tab = FALSE; */
60static int show_pref = 0;
61static gboolean desktop_pref = FALSE;
62static char* set_wallpaper = NULL;
63static char* wallpaper_mode = NULL;
64static gboolean find_files = FALSE;
65static char* ipc_cwd = NULL;
66
67static int n_pcmanfm_ref = 0;
68
69static GOptionEntry opt_entries[] =
70{
71 /* { "new-tab", 't', 0, G_OPTION_ARG_NONE, &new_tab, N_("Open folders in new tabs of the last used window instead of creating new windows"), NULL }, */
72 { "profile", 'p', 0, G_OPTION_ARG_STRING, &profile, N_("Name of configuration profile"), "<profile name>" },
73 { "desktop", '\0', 0, G_OPTION_ARG_NONE, &show_desktop, N_("Launch desktop manager"), NULL },
74 { "desktop-off", '\0', 0, G_OPTION_ARG_NONE, &desktop_off, N_("Turn off desktop manager if it's running"), NULL },
75 { "daemon-mode", 'd', 0, G_OPTION_ARG_NONE, &daemon_mode, N_("Run PCManFM as a daemon"), NULL },
76 { "desktop-pref", '\0', 0, G_OPTION_ARG_NONE, &desktop_pref, N_("Open desktop preference dialog"), NULL },
77 { "set-wallpaper", 'w', 0, G_OPTION_ARG_FILENAME, &set_wallpaper, N_("Set desktop wallpaper"), N_("<image file>") },
78 { "wallpaper-mode", '\0', 0, G_OPTION_ARG_STRING, &wallpaper_mode, N_("Set mode of desktop wallpaper. <mode>=(color|stretch|fit|center|tile)"), N_("<mode>") },
79 { "show-pref", '\0', 0, G_OPTION_ARG_INT, &show_pref, N_("Open preference dialog. 'n' is number of the page you want to show (1, 2, 3...)."), "n" },
80 /* { "find-files", 'f', 0, G_OPTION_ARG_NONE, &find_files, N_("Open Find Files utility"), NULL }, */
81 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &no_desktop, N_("No function. Just to be compatible with nautilus"), NULL },
82 {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files_to_open, NULL, N_("[FILE1, FILE2,...]")},
83 { NULL }
84};
85
86static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"};
87
88static gboolean single_instance_check();
89static void single_instance_finalize();
90static void get_socket_name(char* buf, int len);
91static gboolean pcmanfm_run();
92static gboolean on_socket_event(GIOChannel* ioc, GIOCondition cond, gpointer data);
93
94int main(int argc, char** argv)
95{
96 FmConfig* config;
97 GError* err = NULL;
98
99#ifdef ENABLE_NLS
100 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
101 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
102 textdomain ( GETTEXT_PACKAGE );
103#endif
104
105 /* initialize GTK+ and parse the command line arguments */
106 if(G_UNLIKELY(!gtk_init_with_args(&argc, &argv, "", opt_entries, GETTEXT_PACKAGE, &err)))
107 {
108 g_printf("%s\n", err->message);
109 g_error_free(err);
110 return 1;
111 }
112
113 /* ensure that there is only one instance of pcmanfm.
114 if there is an existing instance, command line arguments
115 will be passed to the existing instance, and exit() will be called here. */
116 single_instance_check();
117
118 /* intercept signals */
119 signal( SIGPIPE, SIG_IGN );
120 /* signal( SIGHUP, gtk_main_quit ); */
121 signal( SIGINT, gtk_main_quit );
122 signal( SIGTERM, gtk_main_quit );
123
124 config = fm_app_config_new(); /* this automatically load libfm config file. */
125 /* load pcmanfm-specific config file */
126 if(profile)
127 config_name = g_strconcat("pcmanfm/", profile, ".conf", NULL);
128 fm_app_config_load_from_file(FM_APP_CONFIG(config), config_name);
129
130 fm_gtk_init(config);
131
132 /* the main part */
133 if(pcmanfm_run())
134 {
135 fm_volume_manager_init();
136 gtk_main();
137 if(desktop_running)
138 fm_desktop_manager_finalize();
139 fm_config_save(config, NULL); /* save libfm config */
140 fm_app_config_save((FmAppConfig*)config, config_name); /* save pcmanfm config */
141 fm_volume_manager_finalize();
142 }
143 single_instance_finalize();
144
145 fm_gtk_finalize();
146 g_object_unref(config);
147 return 0;
148}
149
150inline static void buf_append_str(GByteArray* buf, const char* str)
151{
152 int len;
153 if(G_LIKELY(str))
154 {
155 len = strlen(str) + 1;
156 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
157 g_byte_array_append(buf, (guint8*)str, len);
158 }
159 else
160 {
161 len = 0;
162 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
163 }
164}
165
166inline static GByteArray* args_to_ipc_buf()
167{
168 int i, len;
169 GByteArray* buf = g_byte_array_sized_new(4096);
170 /* send our current working dir to existing instance via IPC. */
171 ipc_cwd = g_get_current_dir();
172 buf_append_str(buf, ipc_cwd);
173 g_free(ipc_cwd);
174
175 /* g_byte_array_append(buf, (guint8*)&new_tab, sizeof(new_tab)); */
176 g_byte_array_append(buf, (guint8*)&show_desktop, sizeof(show_desktop));
177 g_byte_array_append(buf, (guint8*)&desktop_off, sizeof(desktop_off));
178 g_byte_array_append(buf, (guint8*)&desktop_pref, sizeof(desktop_pref));
179 buf_append_str(buf, set_wallpaper);
180 buf_append_str(buf, wallpaper_mode);
181 g_byte_array_append(buf, (guint8*)&show_pref, sizeof(show_pref));
182 g_byte_array_append(buf, (guint8*)&find_files, sizeof(find_files));
183 g_byte_array_append(buf, (guint8*)&no_desktop, sizeof(no_desktop));
184
185 len = files_to_open ? g_strv_length(files_to_open) : 0;
186 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
187 for(i = 0; i < len; ++i)
188 buf_append_str(buf, files_to_open[i]);
189
190 return buf;
191}
192
193inline static gboolean buf_read_bool(const char**p)
194{
195 gboolean ret;
196 memcpy(&ret, *p, sizeof(ret));
197 *p += sizeof(ret);
198 return ret;
199}
200
201inline static int buf_read_int(const char**p)
202{
203 int ret;
204 memcpy(&ret, *p, sizeof(ret));
205 *p += sizeof(ret);
206 return ret;
207}
208
209inline static char* buf_read_str(const char**p)
210{
211 char* ret;
212 int len = buf_read_int(p);
213 if(len > 0)
214 {
215 ret = g_malloc(len);
216 memcpy(ret, *p, len);
217 *p += len;
218 }
219 else
220 ret = NULL;
221 return ret;
222}
223
224inline static void ipc_buf_to_args(GByteArray* buf)
225{
226 int i, len;
227 char* p = buf->data;
228 char* cwd = buf_read_str(&p);
229 /* new_tab = buf_read_bool(&p); */
230 show_desktop = buf_read_bool(&p);
231 desktop_off = buf_read_bool(&p);
232 desktop_pref = buf_read_bool(&p);
233 g_free(set_wallpaper);
234 set_wallpaper = buf_read_str(&p);
235 g_free(wallpaper_mode);
236 wallpaper_mode = buf_read_str(&p);
237 show_pref = buf_read_int(&p);
238 find_files = buf_read_bool(&p);
239 no_desktop = buf_read_bool(&p);
240
241 len = buf_read_int(&p);
242 /* g_debug("len = %d", len); */
243 if(len > 0)
244 {
245 files_to_open = g_new(char*, len + 1);
246 for(i = 0; i < len; ++i)
247 {
248 char* file = buf_read_str(&p);
249 char* scheme = g_uri_parse_scheme(file);
250 if(scheme) /* a valid URI */
251 {
252 /* FIXME: should we canonicalize URIs? and how about file:///? */
253 files_to_open[i] = file;
254 g_free(scheme);
255 }
256 else /* a file path */
257 {
258 files_to_open[i] = fm_canonicalize_filename(file, cwd);
259 g_free(file);
260 }
261 }
262 files_to_open[i] = NULL;
263 }
264 else
265 files_to_open = NULL;
266 g_free(cwd);
267}
268
269gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data )
270{
271 int client, r;
272 socklen_t addr_len = 0;
273 struct sockaddr_un client_addr ={ 0 };
274 static char buf[ 1024 ];
275 GByteArray* args;
276
277 if ( cond & G_IO_IN )
278 {
279 client = accept( g_io_channel_unix_get_fd( ioc ), (struct sockaddr *)&client_addr, &addr_len );
280 if ( client != -1 )
281 {
282 args = g_byte_array_sized_new(4096);
283 while( (r = read( client, buf, sizeof(buf) )) > 0 )
284 g_byte_array_append( args, (guint8*)buf, r);
285 shutdown( client, 2 );
286 close( client );
287 ipc_buf_to_args(args);
288 g_byte_array_free( args, TRUE );
289 pcmanfm_run();
290 }
291 }
292 return TRUE;
293}
294
295void get_socket_name( char* buf, int len )
296{
297 char* dpy = gdk_get_display();
55e66dba 298 g_snprintf( buf, len, "/tmp/.pcmanfm-socket%s-%s", dpy, g_get_user_name() );
92978c90
DB
299 g_free( dpy );
300}
301
302gboolean single_instance_check()
303{
304 struct sockaddr_un addr;
305 int addr_len;
306 int ret;
307 int reuse;
308
309 if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
310 {
311 ret = 1;
312 goto _exit;
313 }
314
315 /* FIXME: use abstract socket */
316 addr.sun_family = AF_UNIX;
317 get_socket_name(addr.sun_path, sizeof( addr.sun_path ));
318#ifdef SUN_LEN
319 addr_len = SUN_LEN(&addr);
320#else
321 addr_len = strlen( addr.sun_path ) + sizeof( addr.sun_family );
322#endif
323
324 /* try to connect to existing instance */
325 if(connect(sock, (struct sockaddr*)&addr, addr_len) == 0)
326 {
327 /* connected successfully */
328 GByteArray* buf = args_to_ipc_buf();
329 write(sock, buf->data, buf->len);
330 g_byte_array_free(buf, TRUE);
331
332 shutdown( sock, 2 );
333 close( sock );
334 ret = 0;
335 goto _exit;
336 }
337
338 /* There is no existing server, and we are in the first instance. */
339 unlink( addr.sun_path ); /* delete old socket file if it exists. */
340 reuse = 1;
341 ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) );
342 if(bind(sock, (struct sockaddr*)&addr, addr_len) == -1)
343 {
344 ret = 1;
345 goto _exit;
346 }
347
348 io_channel = g_io_channel_unix_new(sock);
349 g_io_channel_set_encoding(io_channel, NULL, NULL);
350 g_io_channel_set_buffered(io_channel, FALSE);
351 g_io_add_watch(io_channel, G_IO_IN,
352 (GIOFunc)on_socket_event, NULL);
353 if(listen(sock, 5) == -1)
354 {
355 ret = 1;
356 goto _exit;
357 }
358 return TRUE;
359
360_exit:
361
362 gdk_notify_startup_complete();
363 exit( ret );
364}
365
366void single_instance_finalize()
367{
368 char lock_file[256];
369 shutdown(sock, 2);
370 g_io_channel_unref(io_channel);
371 close(sock);
372 get_socket_name(lock_file, sizeof( lock_file ));
373 unlink(lock_file);
374}
375
376static FmJobErrorAction on_file_info_job_error(FmFileInfoJob* job, GError* err, FmJobErrorSeverity severity, gpointer user_data)
377{
55e66dba 378 if(err->domain == G_IO_ERROR)
92978c90 379 {
55e66dba
DB
380 if(err->code == G_IO_ERROR_NOT_MOUNTED)
381 {
382 if(fm_mount_path(NULL, fm_file_info_job_get_current(job), TRUE))
383 return FM_JOB_RETRY;
384 }
385 else if(err->code == G_IO_ERROR_FAILED_HANDLED)
386 return FM_JOB_CONTINUE;
92978c90 387 }
55e66dba 388 fm_show_error(NULL, err->message);
92978c90
DB
389 return FM_JOB_CONTINUE;
390}
391
392gboolean pcmanfm_run()
393{
394 gboolean ret = TRUE;
395
396 if(!files_to_open)
397 {
398 /* Launch desktop manager */
399 if(show_desktop)
400 {
401 if(!desktop_running)
402 {
403 fm_desktop_manager_init();
404 desktop_running = TRUE;
405 }
406 show_desktop = FALSE;
407 return TRUE;
408 }
409 else if(desktop_off)
410 {
411 if(desktop_running)
412 {
413 desktop_running = FALSE;
414 fm_desktop_manager_finalize();
415 }
416 desktop_off = FALSE;
417 return FALSE;
418 }
419 else if(show_pref > 0)
420 {
421 fm_edit_preference(NULL, show_pref - 1);
422 show_pref = 0;
423 return TRUE;
424 }
425 else if(desktop_pref)
426 {
427 fm_desktop_preference();
428 desktop_pref = FALSE;
429 return TRUE;
430 }
431 else
432 {
433 gboolean need_to_exit = (wallpaper_mode || set_wallpaper);
434 gboolean wallpaper_changed = FALSE;
435 if(set_wallpaper) /* a new wallpaper is assigned */
436 {
437 /* g_debug("\'%s\'", set_wallpaper); */
438 /* Make sure this is a support image file. */
439 if(gdk_pixbuf_get_file_info(set_wallpaper, NULL, NULL))
440 {
441 if(app_config->wallpaper)
442 g_free(app_config->wallpaper);
443 app_config->wallpaper = set_wallpaper;
444 set_wallpaper = NULL;
445 if(! wallpaper_mode) /* if wallpaper mode is not specified */
446 {
447 /* do not use solid color mode; otherwise wallpaper won't be shown. */
448 if(app_config->wallpaper_mode == FM_WP_COLOR)
449 app_config->wallpaper_mode = FM_WP_FIT;
450 }
451 wallpaper_changed = TRUE;
452 }
453 }
454
455 if(wallpaper_mode)
456 {
457 int i = 0;
458 for(i = 0; i < G_N_ELEMENTS(valid_wallpaper_modes); ++i)
459 {
460 if(strcmp(valid_wallpaper_modes[i], wallpaper_mode) == 0)
461 {
462 if(i != app_config->wallpaper_mode)
463 {
464 app_config->wallpaper_mode = i;
465 wallpaper_changed = TRUE;
466 }
467 break;
468 }
469 }
470 g_free(wallpaper_mode);
471 wallpaper_mode = NULL;
472 }
473
474 if(wallpaper_changed)
475 {
476 fm_config_emit_changed(FM_CONFIG(app_config), "wallpaper");
477 fm_app_config_save(app_config, config_name);
478 }
479
480 if(need_to_exit)
481 return FALSE;
482 }
483 }
484
485 if(G_UNLIKELY(find_files))
486 {
487 /* FIXME: find files */
488 }
489 else
490 {
491 if(files_to_open)
492 {
493 char** filename;
494 FmJob* job = fm_file_info_job_new(NULL, 0);
495 FmPath* cwd = NULL;
496 GList* infos;
497 for(filename=files_to_open; *filename; ++filename)
498 {
499 FmPath* path;
500 if( **filename == '/' || strstr(*filename, ":/") ) /* absolute path or URI */
501 path = fm_path_new(*filename);
502 else if( strcmp(*filename, "~") == 0 ) /* special case for home dir */
503 {
504 path = fm_path_get_home();
505 fm_main_win_add_win(NULL, path);
506 continue;
507 }
508 else /* basename */
509 {
510 if(G_UNLIKELY(!cwd))
511 {
512 /* FIXME: This won't work if those filenames are passed via IPC since the receiving process has different cwd. */
513 char* cwd_str = g_get_current_dir();
514 cwd = fm_path_new(cwd_str);
515 g_free(cwd_str);
516 }
517 path = fm_path_new_relative(cwd, *filename);
518 }
519 fm_file_info_job_add(FM_FILE_INFO_JOB(job), path);
520 fm_path_unref(path);
521 }
522 if(cwd)
523 fm_path_unref(cwd);
524 g_signal_connect(job, "error", G_CALLBACK(on_file_info_job_error), NULL);
525 fm_job_run_sync_with_mainloop(job);
526 infos = fm_list_peek_head_link(FM_FILE_INFO_JOB(job)->file_infos);
527 fm_launch_files_simple(NULL, NULL, infos, pcmanfm_open_folder, NULL);
528 g_object_unref(job);
529 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
530
531 g_strfreev(files_to_open);
532 files_to_open = NULL;
533 }
534 else
535 {
536 FmPath* path;
537 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
538 path = fm_path_new(cwd);
539 fm_main_win_add_win(NULL, path);
540 fm_path_unref(path);
541 g_free(cwd);
542 ipc_cwd = NULL;
543 }
544 }
545 return ret;
546}
547
548/* After opening any window/dialog/tool, this should be called. */
549void pcmanfm_ref()
550{
551 ++n_pcmanfm_ref;
552 /* g_debug("ref: %d", n_pcmanfm_ref); */
553}
554
555/* After closing any window/dialog/tool, this should be called.
556 * If the last window is closed and we are not a deamon, pcmanfm will quit.
557 */
558void pcmanfm_unref()
559{
560 --n_pcmanfm_ref;
561 /* g_debug("unref: %d, daemon_mode=%d, desktop_running=%d", n_pcmanfm_ref, daemon_mode, desktop_running); */
562 if( 0 == n_pcmanfm_ref && !daemon_mode && !desktop_running )
563 gtk_main_quit();
564}
565
566gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
567{
568 GList* l = folder_infos;
569 for(; l; l=l->next)
570 {
571 FmFileInfo* fi = (FmFileInfo*)l->data;
572 fm_main_win_open_in_last_active(fi->path);
573 }
574 return TRUE;
575}
576
577void pcmanfm_save_config()
578{
579 fm_config_save(fm_config, NULL);
580 fm_app_config_save(app_config, config_name);
581}
582
583void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
584{
585 GAppInfo* app;
586 char** argv;
587 int argc;
588 if(!fm_config->terminal)
589 {
590 fm_show_error(parent, _("Terminal emulator is not set."));
591 fm_edit_preference(parent, PREF_ADVANCED);
592 return;
593 }
594 if(!g_shell_parse_argv(fm_config->terminal, &argc, &argv, NULL))
595 return;
596 app = g_app_info_create_from_commandline(argv[0], NULL, 0, NULL);
597 g_strfreev(argv);
598 if(app)
599 {
600 GError* err = NULL;
601 GAppLaunchContext* ctx = gdk_app_launch_context_new();
602 char* cwd_str;
603
604 if(fm_path_is_native(dir))
605 cwd_str = fm_path_to_str(dir);
606 else
607 {
608 GFile* gf = fm_path_to_gfile(dir);
609 cwd_str = g_file_get_path(gf);
610 g_object_unref(gf);
611 }
612 gdk_app_launch_context_set_screen(GDK_APP_LAUNCH_CONTEXT(ctx), parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
613 gdk_app_launch_context_set_timestamp(GDK_APP_LAUNCH_CONTEXT(ctx), gtk_get_current_event_time());
614 g_chdir(cwd_str); /* FIXME: currently we don't have better way for this. maybe a wrapper script? */
615 g_free(cwd_str);
616 if(!g_app_info_launch(app, NULL, ctx, &err))
617 {
618 fm_show_error(parent, err->message);
619 g_error_free(err);
620 }
621 g_object_unref(ctx);
622 g_object_unref(app);
623 }
624}
625
626/* FIXME: Need to load content of ~/Templates and list available templates in popup menus. */
627void pcmanfm_create_new(GtkWindow* parent, FmPath* cwd, const char* templ)
628{
629 GError* err = NULL;
630 FmPath* dest;
631 char* basename;
632_retry:
633 basename = fm_get_user_input(parent, _("Create New..."), _("Enter a name for the newly created file:"), _("New"));
634 if(!basename)
635 return;
636
637 dest = fm_path_new_child(cwd, basename);
638 g_free(basename);
639
640 if( templ == TEMPL_NAME_FOLDER )
641 {
642 GFile* gf = fm_path_to_gfile(dest);
643 if(!g_file_make_directory(gf, NULL, &err))
644 {
645 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
646 {
647 fm_path_unref(dest);
648 g_error_free(err);
649 g_object_unref(gf);
650 err = NULL;
651 goto _retry;
652 }
653 fm_show_error(parent, err->message);
654 g_error_free(err);
655 }
656
657 if(!err) /* select the newly created file */
658 {
659 /*FIXME: this doesn't work since the newly created file will
660 * only be shown after file-created event was fired on its
661 * folder's monitor and after FmFolder handles it in idle
662 * handler. So, we cannot select it since it's not yet in
663 * the folder model now. */
664 /* fm_folder_view_select_file_path(fv, dest); */
665 }
666 g_object_unref(gf);
667 }
668 else if( templ == TEMPL_NAME_BLANK )
669 {
670 GFile* gf = fm_path_to_gfile(dest);
671 GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
672 if(f)
673 {
674 g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
675 g_object_unref(f);
676 }
677 else
678 {
679 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
680 {
681 fm_path_unref(dest);
682 g_error_free(err);
683 g_object_unref(gf);
684 err = NULL;
685 goto _retry;
686 }
687 fm_show_error(parent, err->message);
688 g_error_free(err);
689 }
690
691 if(!err) /* select the newly created file */
692 {
693 /*FIXME: this doesn't work since the newly created file will
694 * only be shown after file-created event was fired on its
695 * folder's monitor and after FmFolder handles it in idle
696 * handler. So, we cannot select it since it's not yet in
697 * the folder model now. */
698 /* fm_folder_view_select_file_path(fv, dest); */
699 }
700 g_object_unref(gf);
701 }
702 else /* templates in ~/Templates */
703 {
704 FmPath* dir = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
705 FmPath* template = fm_path_new_child(dir, templ);
706 fm_copy_file(template, cwd);
707 fm_path_unref(template);
708 }
709 fm_path_unref(dest);
710}