Commit from LXDE Translation Project with Pootle by user brother.: 145 of 145 message...
[lxde/pcmanfm.git] / src / pcmanfm.c
CommitLineData
b6e3c554
HJYP
1/*
2 * pcmanfm.c
d3451adb 3 *
7b7d923f 4 * Copyright 2009 - 2010 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
d3451adb 5 *
b6e3c554
HJYP
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.
d3451adb 10 *
b6e3c554
HJYP
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.
d3451adb 15 *
b6e3c554
HJYP
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
08e70fea 22#ifdef HAVE_CONFIG_H
b6e3c554 23#include <config.h>
08e70fea
HJYP
24#endif
25
b6e3c554
HJYP
26#include <gtk/gtk.h>
27#include <stdio.h>
f8f2bfad
HJYP
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 */
b6e3c554 38
20c0bc9a 39#include <libfm/fm-gtk.h>
4d55886c 40#include "app-config.h"
b6e3c554 41#include "main-win.h"
8505a8ef 42#include "desktop.h"
71f82759 43#include "volume-manager.h"
c5fccf1d 44#include "pref.h"
df6826e0 45#include "pcmanfm.h"
8505a8ef 46
f8f2bfad
HJYP
47static int sock;
48GIOChannel* io_channel = NULL;
49
50gboolean daemon_mode = FALSE;
51
f8f2bfad 52static char** files_to_open = NULL;
f970e846
HJYP
53static char* profile = NULL;
54static char* config_name = NULL;
f8f2bfad
HJYP
55static gboolean no_desktop = FALSE;
56static gboolean show_desktop = FALSE;
57static gboolean desktop_off = FALSE;
58static gboolean desktop_running = FALSE;
107cdb22 59/* static gboolean new_tab = FALSE; */
f8f2bfad
HJYP
60static int show_pref = 0;
61static gboolean desktop_pref = FALSE;
62static char* set_wallpaper = NULL;
107cdb22 63static char* wallpaper_mode = NULL;
f8f2bfad 64static gboolean find_files = FALSE;
5b890032 65static char* ipc_cwd = NULL;
f8f2bfad
HJYP
66
67static int n_pcmanfm_ref = 0;
68
69static GOptionEntry opt_entries[] =
8505a8ef 70{
107cdb22 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 }, */
a48f9fc8 72 { "profile", 'p', 0, G_OPTION_ARG_STRING, &profile, N_("Name of configuration profile"), "<profile name>" },
f8f2bfad
HJYP
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 },
f8f2bfad 75 { "daemon-mode", 'd', 0, G_OPTION_ARG_NONE, &daemon_mode, N_("Run PCManFM as a daemon"), NULL },
f8f2bfad 76 { "desktop-pref", '\0', 0, G_OPTION_ARG_NONE, &desktop_pref, N_("Open desktop preference dialog"), NULL },
f970e846 77 { "set-wallpaper", 'w', 0, G_OPTION_ARG_FILENAME, &set_wallpaper, N_("Set desktop wallpaper"), N_("<image file>") },
107cdb22 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>") },
a48f9fc8 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" },
1d071341 80 /* { "find-files", 'f', 0, G_OPTION_ARG_NONE, &find_files, N_("Open Find Files utility"), NULL }, */
f970e846 81 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &no_desktop, N_("No function. Just to be compatible with nautilus"), NULL },
f8f2bfad
HJYP
82 {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files_to_open, NULL, N_("[FILE1, FILE2,...]")},
83 { NULL }
84};
85
107cdb22
HJYP
86static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"};
87
f8f2bfad
HJYP
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);
b6e3c554
HJYP
93
94int main(int argc, char** argv)
95{
4d55886c 96 FmConfig* config;
f8f2bfad
HJYP
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);
c5fccf1d 109 g_error_free(err);
f8f2bfad
HJYP
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 );
b6e3c554 123
f970e846
HJYP
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);
4b3e1fe9 128 fm_app_config_load_from_file(FM_APP_CONFIG(config), config_name);
f970e846 129
4d55886c 130 fm_gtk_init(config);
b6e3c554 131
f8f2bfad
HJYP
132 /* the main part */
133 if(pcmanfm_run())
134 {
71f82759 135 fm_volume_manager_init();
f8f2bfad
HJYP
136 gtk_main();
137 if(desktop_running)
138 fm_desktop_manager_finalize();
f8f2bfad 139 fm_config_save(config, NULL); /* save libfm config */
f970e846 140 fm_app_config_save((FmAppConfig*)config, config_name); /* save pcmanfm config */
71f82759 141 fm_volume_manager_finalize();
f8f2bfad
HJYP
142 }
143 single_instance_finalize();
8505a8ef 144
f8f2bfad
HJYP
145 fm_gtk_finalize();
146 g_object_unref(config);
f8f2bfad
HJYP
147 return 0;
148}
149
7b7d923f 150inline static void buf_append_str(GByteArray* buf, const char* str)
f8f2bfad 151{
7b7d923f
HJYP
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);
5b890032
HJYP
170 /* send our current working dir to existing instance via IPC. */
171 ipc_cwd = g_get_current_dir();
7b7d923f 172 buf_append_str(buf, ipc_cwd);
5b890032 173 g_free(ipc_cwd);
7b7d923f 174
107cdb22 175 /* g_byte_array_append(buf, (guint8*)&new_tab, sizeof(new_tab)); */
7b7d923f
HJYP
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);
107cdb22 180 buf_append_str(buf, wallpaper_mode);
7b7d923f
HJYP
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
a1a528d2 185 len = files_to_open ? g_strv_length(files_to_open) : 0;
2b46b521
HJYP
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]);
7b7d923f 189
f8f2bfad
HJYP
190 return buf;
191}
192
7b7d923f
HJYP
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)
f8f2bfad 225{
7b7d923f
HJYP
226 int i, len;
227 char* p = buf->data;
228 char* cwd = buf_read_str(&p);
107cdb22 229 /* new_tab = buf_read_bool(&p); */
7b7d923f
HJYP
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);
107cdb22
HJYP
235 g_free(wallpaper_mode);
236 wallpaper_mode = buf_read_str(&p);
7b7d923f
HJYP
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);
107cdb22 242 /* g_debug("len = %d", len); */
7b7d923f 243 if(len > 0)
b6e3c554 244 {
7b7d923f
HJYP
245 files_to_open = g_new(char*, len + 1);
246 for(i = 0; i < len; ++i)
f8f2bfad 247 {
7b7d923f 248 char* file = buf_read_str(&p);
ee12f37e
HJYP
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 }
f8f2bfad 261 }
7b7d923f 262 files_to_open[i] = NULL;
b6e3c554 263 }
7b7d923f
HJYP
264 else
265 files_to_open = NULL;
266 g_free(cwd);
f8f2bfad 267}
8505a8ef 268
f8f2bfad
HJYP
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 ];
7b7d923f 275 GByteArray* args;
b6e3c554 276
f8f2bfad
HJYP
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 {
7b7d923f 282 args = g_byte_array_sized_new(4096);
f8f2bfad 283 while( (r = read( client, buf, sizeof(buf) )) > 0 )
7b7d923f 284 g_byte_array_append( args, (guint8*)buf, r);
f8f2bfad
HJYP
285 shutdown( client, 2 );
286 close( client );
44409230 287 ipc_buf_to_args(args);
7b7d923f 288 g_byte_array_free( args, TRUE );
f8f2bfad
HJYP
289 pcmanfm_run();
290 }
291 }
292 return TRUE;
293}
19fbd668 294
f8f2bfad
HJYP
295void get_socket_name( char* buf, int len )
296{
297 char* dpy = gdk_get_display();
298 g_snprintf( buf, len, "/tmp/.pcmanfm2-socket%s-%s", dpy, g_get_user_name() );
299 g_free( dpy );
300}
8505a8ef 301
f8f2bfad
HJYP
302gboolean single_instance_check()
303{
304 struct sockaddr_un addr;
305 int addr_len;
306 int ret;
307 int reuse;
b6e3c554 308
f8f2bfad
HJYP
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 */
7b7d923f
HJYP
328 GByteArray* buf = args_to_ipc_buf();
329 write(sock, buf->data, buf->len);
330 g_byte_array_free(buf, TRUE);
f8f2bfad
HJYP
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 }
d3451adb 358 return TRUE;
f8f2bfad
HJYP
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
ee12f37e
HJYP
376static FmJobErrorAction on_file_info_job_error(FmFileInfoJob* job, GError* err, FmJobErrorSeverity severity, gpointer user_data)
377{
378 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED)
379 {
380 FmPath* current = fm_file_info_job_get_current(job);
381 if( fm_mount_path(NULL, current, TRUE) )
382 return FM_JOB_RETRY;
383 }
384 return FM_JOB_CONTINUE;
385}
f8f2bfad
HJYP
386
387gboolean pcmanfm_run()
388{
389 gboolean ret = TRUE;
f8f2bfad 390
f8f2bfad
HJYP
391 if(!files_to_open)
392 {
393 /* Launch desktop manager */
394 if(show_desktop)
395 {
396 if(!desktop_running)
397 {
398 fm_desktop_manager_init();
399 desktop_running = TRUE;
400 }
19abb8bf 401 show_desktop = FALSE;
f8f2bfad
HJYP
402 return TRUE;
403 }
404 else if(desktop_off)
405 {
406 if(desktop_running)
407 {
408 desktop_running = FALSE;
409 fm_desktop_manager_finalize();
410 }
19abb8bf 411 desktop_off = FALSE;
f8f2bfad
HJYP
412 return FALSE;
413 }
414 else if(show_pref > 0)
415 {
c5fccf1d
HJYP
416 fm_edit_preference(NULL, show_pref - 1);
417 show_pref = 0;
f8f2bfad
HJYP
418 return TRUE;
419 }
420 else if(desktop_pref)
421 {
c5fccf1d 422 fm_desktop_preference();
19abb8bf 423 desktop_pref = FALSE;
f8f2bfad
HJYP
424 return TRUE;
425 }
107cdb22 426 else
f8f2bfad 427 {
107cdb22
HJYP
428 gboolean need_to_exit = (wallpaper_mode || set_wallpaper);
429 gboolean wallpaper_changed = FALSE;
430 if(set_wallpaper) /* a new wallpaper is assigned */
431 {
432 /* g_debug("\'%s\'", set_wallpaper); */
433 /* Make sure this is a support image file. */
434 if(gdk_pixbuf_get_file_info(set_wallpaper, NULL, NULL))
435 {
436 if(app_config->wallpaper)
437 g_free(app_config->wallpaper);
438 app_config->wallpaper = set_wallpaper;
439 set_wallpaper = NULL;
440 if(! wallpaper_mode) /* if wallpaper mode is not specified */
441 {
442 /* do not use solid color mode; otherwise wallpaper won't be shown. */
443 if(app_config->wallpaper_mode == FM_WP_COLOR)
444 app_config->wallpaper_mode = FM_WP_FIT;
445 }
446 wallpaper_changed = TRUE;
447 }
448 }
449
450 if(wallpaper_mode)
451 {
452 int i = 0;
453 for(i = 0; i < G_N_ELEMENTS(valid_wallpaper_modes); ++i)
454 {
455 if(strcmp(valid_wallpaper_modes[i], wallpaper_mode) == 0)
456 {
457 if(i != app_config->wallpaper_mode)
458 {
459 app_config->wallpaper_mode = i;
460 wallpaper_changed = TRUE;
461 }
462 break;
463 }
464 }
465 g_free(wallpaper_mode);
466 wallpaper_mode = NULL;
467 }
468
469 if(wallpaper_changed)
f8f2bfad 470 {
4b3e1fe9 471 fm_config_emit_changed(FM_CONFIG(app_config), "wallpaper");
dcecce78 472 fm_app_config_save(app_config, config_name);
f8f2bfad 473 }
107cdb22
HJYP
474
475 if(need_to_exit)
476 return FALSE;
f8f2bfad
HJYP
477 }
478 }
479
480 if(G_UNLIKELY(find_files))
481 {
482 /* FIXME: find files */
483 }
484 else
485 {
df6826e0
HJYP
486 if(files_to_open)
487 {
488 char** filename;
0a053694 489 FmJob* job = fm_file_info_job_new(NULL, 0);
cacf261a 490 FmPath* cwd = NULL;
d951adb8 491 GList* infos;
df6826e0
HJYP
492 for(filename=files_to_open; *filename; ++filename)
493 {
cacf261a
HJYP
494 FmPath* path;
495 if( **filename == '/' || strstr(*filename, ":/") ) /* absolute path or URI */
496 path = fm_path_new(*filename);
0d8dce1a
HJYP
497 else if( strcmp(*filename, "~") == 0 ) /* special case for home dir */
498 {
499 path = fm_path_get_home();
500 fm_main_win_add_win(NULL, path);
501 continue;
502 }
cacf261a
HJYP
503 else /* basename */
504 {
505 if(G_UNLIKELY(!cwd))
506 {
507 /* FIXME: This won't work if those filenames are passed via IPC since the receiving process has different cwd. */
508 char* cwd_str = g_get_current_dir();
509 cwd = fm_path_new(cwd_str);
510 g_free(cwd_str);
511 }
512 path = fm_path_new_relative(cwd, *filename);
513 }
4b3e1fe9 514 fm_file_info_job_add(FM_FILE_INFO_JOB(job), path);
df6826e0
HJYP
515 fm_path_unref(path);
516 }
cacf261a
HJYP
517 if(cwd)
518 fm_path_unref(cwd);
ee12f37e 519 g_signal_connect(job, "error", G_CALLBACK(on_file_info_job_error), NULL);
a48f9fc8 520 fm_job_run_sync_with_mainloop(job);
d951adb8
HJYP
521 infos = fm_list_peek_head_link(FM_FILE_INFO_JOB(job)->file_infos);
522 fm_launch_files_simple(NULL, NULL, infos, pcmanfm_open_folder, NULL);
df6826e0 523 g_object_unref(job);
cacf261a 524 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
2b46b521
HJYP
525
526 g_strfreev(files_to_open);
527 files_to_open = NULL;
df6826e0
HJYP
528 }
529 else
f8f2bfad
HJYP
530 {
531 FmPath* path;
5b890032 532 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
0d8dce1a
HJYP
533 path = fm_path_new(cwd);
534 fm_main_win_add_win(NULL, path);
535 fm_path_unref(path);
536 g_free(cwd);
5b890032 537 ipc_cwd = NULL;
f8f2bfad
HJYP
538 }
539 }
540 return ret;
541}
542
543/* After opening any window/dialog/tool, this should be called. */
544void pcmanfm_ref()
545{
546 ++n_pcmanfm_ref;
547 /* g_debug("ref: %d", n_pcmanfm_ref); */
548}
549
550/* After closing any window/dialog/tool, this should be called.
551 * If the last window is closed and we are not a deamon, pcmanfm will quit.
552 */
553void pcmanfm_unref()
554{
555 --n_pcmanfm_ref;
556 /* g_debug("unref: %d, daemon_mode=%d, desktop_running=%d", n_pcmanfm_ref, daemon_mode, desktop_running); */
557 if( 0 == n_pcmanfm_ref && !daemon_mode && !desktop_running )
558 gtk_main_quit();
b6e3c554 559}
df6826e0
HJYP
560
561gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
562{
df6826e0
HJYP
563 GList* l = folder_infos;
564 for(; l; l=l->next)
565 {
566 FmFileInfo* fi = (FmFileInfo*)l->data;
567 fm_main_win_open_in_last_active(fi->path);
568 }
569 return TRUE;
570}
dcecce78
HJYP
571
572void pcmanfm_save_config()
573{
574 fm_config_save(fm_config, NULL);
575 fm_app_config_save(app_config, config_name);
576}
c56a211a
HJYP
577
578void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
579{
580 GAppInfo* app;
c56a211a
HJYP
581 char** argv;
582 int argc;
583 if(!fm_config->terminal)
584 {
585 fm_show_error(parent, _("Terminal emulator is not set."));
586 fm_edit_preference(parent, PREF_ADVANCED);
587 return;
588 }
589 if(!g_shell_parse_argv(fm_config->terminal, &argc, &argv, NULL))
590 return;
591 app = g_app_info_create_from_commandline(argv[0], NULL, 0, NULL);
592 g_strfreev(argv);
593 if(app)
594 {
595 GError* err = NULL;
596 GAppLaunchContext* ctx = gdk_app_launch_context_new();
597 char* cwd_str;
598
599 if(fm_path_is_native(dir))
600 cwd_str = fm_path_to_str(dir);
601 else
602 {
603 GFile* gf = fm_path_to_gfile(dir);
604 cwd_str = g_file_get_path(gf);
605 g_object_unref(gf);
606 }
99476ede 607 gdk_app_launch_context_set_screen(GDK_APP_LAUNCH_CONTEXT(ctx), parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
c56a211a
HJYP
608 gdk_app_launch_context_set_timestamp(GDK_APP_LAUNCH_CONTEXT(ctx), gtk_get_current_event_time());
609 g_chdir(cwd_str); /* FIXME: currently we don't have better way for this. maybe a wrapper script? */
610 g_free(cwd_str);
611 if(!g_app_info_launch(app, NULL, ctx, &err))
612 {
613 fm_show_error(parent, err->message);
614 g_error_free(err);
615 }
616 g_object_unref(ctx);
617 g_object_unref(app);
618 }
619}
7cb06c27
HJYP
620
621/* FIXME: Need to load content of ~/Templates and list available templates in popup menus. */
622void pcmanfm_create_new(GtkWindow* parent, FmPath* cwd, const char* templ)
623{
624 GError* err = NULL;
625 FmPath* dest;
626 char* basename;
627_retry:
628 basename = fm_get_user_input(parent, _("Create New..."), _("Enter a name for the newly created file:"), _("New"));
629 if(!basename)
630 return;
631
632 dest = fm_path_new_child(cwd, basename);
633 g_free(basename);
634
635 if( templ == TEMPL_NAME_FOLDER )
636 {
637 GFile* gf = fm_path_to_gfile(dest);
638 if(!g_file_make_directory(gf, NULL, &err))
639 {
98daf506 640 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
641 {
642 fm_path_unref(dest);
643 g_error_free(err);
644 g_object_unref(gf);
645 err = NULL;
646 goto _retry;
647 }
648 fm_show_error(parent, err->message);
649 g_error_free(err);
650 }
651
652 if(!err) /* select the newly created file */
653 {
654 /*FIXME: this doesn't work since the newly created file will
655 * only be shown after file-created event was fired on its
656 * folder's monitor and after FmFolder handles it in idle
657 * handler. So, we cannot select it since it's not yet in
658 * the folder model now. */
659 /* fm_folder_view_select_file_path(fv, dest); */
660 }
661 g_object_unref(gf);
662 }
663 else if( templ == TEMPL_NAME_BLANK )
664 {
665 GFile* gf = fm_path_to_gfile(dest);
666 GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
667 if(f)
668 {
669 g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
670 g_object_unref(f);
671 }
672 else
673 {
98daf506 674 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
675 {
676 fm_path_unref(dest);
677 g_error_free(err);
678 g_object_unref(gf);
679 err = NULL;
680 goto _retry;
681 }
682 fm_show_error(parent, err->message);
683 g_error_free(err);
684 }
685
686 if(!err) /* select the newly created file */
687 {
688 /*FIXME: this doesn't work since the newly created file will
689 * only be shown after file-created event was fired on its
690 * folder's monitor and after FmFolder handles it in idle
691 * handler. So, we cannot select it since it's not yet in
692 * the folder model now. */
693 /* fm_folder_view_select_file_path(fv, dest); */
694 }
695 g_object_unref(gf);
696 }
697 else /* templates in ~/Templates */
698 {
699 FmPath* dir = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
700 FmPath* template = fm_path_new_child(dir, templ);
701 fm_copy_file(template, cwd);
702 fm_path_unref(template);
703 }
704 fm_path_unref(dest);
705}