l10n: Updated Portuguese (Brazilian) (pt_BR) translation to 100%
[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();
ab86a7a2 298 g_snprintf( buf, len, "/tmp/.pcmanfm-socket%s-%s", dpy, g_get_user_name() );
f8f2bfad
HJYP
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{
16a17d6b 378 if(err->domain == G_IO_ERROR)
ee12f37e 379 {
16a17d6b
HJYP
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;
ee12f37e 387 }
16a17d6b 388 fm_show_error(NULL, err->message);
ee12f37e
HJYP
389 return FM_JOB_CONTINUE;
390}
f8f2bfad
HJYP
391
392gboolean pcmanfm_run()
393{
394 gboolean ret = TRUE;
f8f2bfad 395
f8f2bfad
HJYP
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 }
19abb8bf 406 show_desktop = FALSE;
f8f2bfad
HJYP
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 }
19abb8bf 416 desktop_off = FALSE;
f8f2bfad
HJYP
417 return FALSE;
418 }
419 else if(show_pref > 0)
420 {
c5fccf1d
HJYP
421 fm_edit_preference(NULL, show_pref - 1);
422 show_pref = 0;
f8f2bfad
HJYP
423 return TRUE;
424 }
425 else if(desktop_pref)
426 {
c5fccf1d 427 fm_desktop_preference();
19abb8bf 428 desktop_pref = FALSE;
f8f2bfad
HJYP
429 return TRUE;
430 }
107cdb22 431 else
f8f2bfad 432 {
107cdb22
HJYP
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)
f8f2bfad 475 {
4b3e1fe9 476 fm_config_emit_changed(FM_CONFIG(app_config), "wallpaper");
dcecce78 477 fm_app_config_save(app_config, config_name);
f8f2bfad 478 }
107cdb22
HJYP
479
480 if(need_to_exit)
481 return FALSE;
f8f2bfad
HJYP
482 }
483 }
484
485 if(G_UNLIKELY(find_files))
486 {
487 /* FIXME: find files */
488 }
489 else
490 {
df6826e0
HJYP
491 if(files_to_open)
492 {
493 char** filename;
0a053694 494 FmJob* job = fm_file_info_job_new(NULL, 0);
cacf261a 495 FmPath* cwd = NULL;
d951adb8 496 GList* infos;
df6826e0
HJYP
497 for(filename=files_to_open; *filename; ++filename)
498 {
cacf261a
HJYP
499 FmPath* path;
500 if( **filename == '/' || strstr(*filename, ":/") ) /* absolute path or URI */
501 path = fm_path_new(*filename);
0d8dce1a
HJYP
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 }
cacf261a
HJYP
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 }
4b3e1fe9 519 fm_file_info_job_add(FM_FILE_INFO_JOB(job), path);
df6826e0
HJYP
520 fm_path_unref(path);
521 }
cacf261a
HJYP
522 if(cwd)
523 fm_path_unref(cwd);
ee12f37e 524 g_signal_connect(job, "error", G_CALLBACK(on_file_info_job_error), NULL);
a48f9fc8 525 fm_job_run_sync_with_mainloop(job);
d951adb8
HJYP
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);
df6826e0 528 g_object_unref(job);
cacf261a 529 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
2b46b521
HJYP
530
531 g_strfreev(files_to_open);
532 files_to_open = NULL;
df6826e0
HJYP
533 }
534 else
f8f2bfad
HJYP
535 {
536 FmPath* path;
5b890032 537 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
0d8dce1a
HJYP
538 path = fm_path_new(cwd);
539 fm_main_win_add_win(NULL, path);
540 fm_path_unref(path);
541 g_free(cwd);
5b890032 542 ipc_cwd = NULL;
f8f2bfad
HJYP
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();
b6e3c554 564}
df6826e0
HJYP
565
566gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
567{
df6826e0
HJYP
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}
dcecce78
HJYP
576
577void pcmanfm_save_config()
578{
579 fm_config_save(fm_config, NULL);
580 fm_app_config_save(app_config, config_name);
581}
c56a211a
HJYP
582
583void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
584{
585 GAppInfo* app;
c56a211a
HJYP
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 }
99476ede 612 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
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}
7cb06c27
HJYP
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 {
98daf506 645 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
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 {
98daf506 679 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
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}