2 * By Tony Houghton, <h@realh.co.uk>.
10 #include <glib/gstdio.h>
14 #include "xxdgautostart.h"
16 #define VIEW_MAX_W 512
17 #define VIEW_MAX_H 320
20 GList
* desktop_entries
;
22 GtkListStore
* list_store
;
23 GtkTreeView
* tree_view
;
24 GtkWidget
* edit_button
;
25 GtkWidget
* remove_button
;
29 ColData
, /* Not shown */
35 ColStartInRoxSensitive
,
41 char *short_locale_name
= NULL
;
43 #if HAVE_GTK_WIDGET_SET_TOOLTIP_TEXT
44 inline static void set_tooltip(GtkWidget
*widget
, const char *text
)
46 gtk_widget_set_tooltip_markup(widget
, text
);
49 static void set_tooltip(GtkWidget
*widget
, const char *text
)
51 static GtkTooltips
*tooltips
= NULL
;
54 tooltips
= gtk_tooltips_new();
55 gtk_tooltips_set_tip(tooltips
, widget
, text
, NULL
);
59 static void set_keyfile_name(GKeyFile
*kf
, const char *name
)
61 char *old_name
= NULL
;
65 g_key_file_set_locale_string(kf
, _DE
, "Name", locale_name
, name
);
66 old_name
= g_key_file_get_string(kf
, _DE
, "Name", NULL
);
67 if (!old_name
|| !old_name
[0])
68 g_key_file_set_string(kf
, _DE
, "Name", name
);
72 g_key_file_set_string(kf
, _DE
, "Name", name
);
74 if (short_locale_name
&&
75 ((old_name
= g_key_file_get_locale_string(kf
, _DE
, "Name",
76 short_locale_name
, NULL
)) == NULL
|| !old_name
[0]))
78 g_key_file_set_locale_string(kf
, _DE
, "Name", short_locale_name
, name
);
83 static void get_entry_and_iter_from_path(DesktopEntriesData
*ded
,
84 DesktopEntry
**entry_out
, GtkTreeIter
*iter_out
, GtkTreePath
*path
)
88 gtk_tree_model_get_iter(GTK_TREE_MODEL(ded
->list_store
),
89 iter_out
? iter_out
: &iter
, path
);
92 gtk_tree_model_get(GTK_TREE_MODEL(ded
->list_store
),
93 iter_out
? iter_out
: &iter
, ColData
, entry_out
, -1);
97 /* If no selection returns FALSE and *entry_out is set to NULL,
98 * *iter_out is unchanged
100 static gboolean
get_selected_entry_and_iter(DesktopEntriesData
*ded
,
101 DesktopEntry
**entry_out
, GtkTreeIter
*iter_out
)
103 GtkTreeSelection
*seln
=
104 gtk_tree_view_get_selection(GTK_TREE_VIEW(ded
->tree_view
));
105 GList
*selected
= gtk_tree_selection_get_selected_rows(seln
, NULL
);
107 /* Only one node can be selected in this view, so just look at first
108 * selected item but be prepared to clean up after multiple just in case
112 get_entry_and_iter_from_path(ded
, entry_out
, iter_out
, selected
->data
);
113 g_list_foreach(selected
, (GFunc
) gtk_tree_path_free
, NULL
);
114 g_list_free(selected
);
125 static void shade_buttons_for_selection(DesktopEntriesData
*ded
)
130 selected
= get_selected_entry_and_iter(ded
, &entry
, NULL
);
131 gtk_widget_set_sensitive(ded
->edit_button
, selected
);
132 gtk_widget_set_sensitive(ded
->remove_button
, entry
&& entry
->deletable
);
135 static GKeyFile
*new_de_keyfile(void)
137 GKeyFile
*kf
= g_key_file_new();
139 g_key_file_set_double(kf
, _DE
, "Version", 1.0);
140 g_key_file_set_string(kf
, _DE
, "Encoding", "UTF-8");
141 g_key_file_set_string(kf
, _DE
, "Name", "AutoStart Entry");
142 set_keyfile_name(kf
, _("New AutoStart Entry"));
143 g_key_file_set_string(kf
, _DE
, "Exec", "rox");
144 g_key_file_set_string(kf
, _DE
, "OnlyShowIn", "ROX;");
148 static DesktopEntry
*new_desktop_entry(void)
150 DesktopEntry
*de
= g_new0(DesktopEntry
, 1);
152 de
->kf
= new_de_keyfile();
153 desktop_entry_read_keyfile(de
);
154 xdesktop_entry_read_name_from_keyfile(de
);
158 static void rox_only_toggled_cb(GtkCellRendererToggle
*cell
,
159 const char *path
, DesktopEntriesData
*ded
)
161 DesktopEntry
*xde
= g_list_nth_data(ded
->desktop_entries
, atoi(path
));
162 gboolean active
= !gtk_cell_renderer_toggle_get_active(cell
);
165 g_return_if_fail(xde
!= NULL
);
166 xdesktop_entry_set_only_in_rox(xde
, active
);
167 xdesktop_entry_save(xde
);
168 g_return_if_fail(gtk_tree_model_get_iter_from_string(
169 GTK_TREE_MODEL(ded
->list_store
), &iter
, path
));
170 gtk_list_store_set(ded
->list_store
, &iter
,
172 ColStartInRoxSensitive
, !active
,
176 static void start_in_rox_toggled_cb(GtkCellRendererToggle
*cell
,
177 const char *path
, DesktopEntriesData
*ded
)
179 DesktopEntry
*xde
= g_list_nth_data(ded
->desktop_entries
, atoi(path
));
180 gboolean active
= !gtk_cell_renderer_toggle_get_active(cell
);
183 g_return_if_fail(xde
!= NULL
);
184 xdesktop_entry_set_start_in_rox(xde
, active
);
185 xdesktop_entry_save(xde
);
186 g_return_if_fail(gtk_tree_model_get_iter_from_string(
187 GTK_TREE_MODEL(ded
->list_store
), &iter
, path
));
188 gtk_list_store_set(ded
->list_store
, &iter
,
189 ColStartInRox
, active
,
190 ColRoxOnlySensitive
, xdesktop_entry_can_set_only_in_rox(xde
),
194 static void open_rs_as_dir(GtkWindow
*parent
)
199 argv
[1] = g_build_filename(g_get_user_config_dir(),
200 "rox.sourceforge.net", "ROX-Session", "AutoStart", NULL
);
201 if (!g_file_test(argv
[1], G_FILE_TEST_IS_DIR
))
203 message_dialog(parent
, GTK_MESSAGE_WARNING
,
204 _("ROX-Session AutoStart directory ('%s') doesn't exist"),
209 argv
[0] = g_find_program_in_path("rox");
212 message_dialog(parent
, GTK_MESSAGE_ERROR
,
213 _("ROX-Filer ('rox') program not found"));
217 if (!gdk_spawn_on_screen(gdk_screen_get_default(), NULL
, argv
, NULL
, 0,
218 NULL
, NULL
, NULL
, &err
))
220 message_dialog(parent
, GTK_MESSAGE_ERROR
,
221 _("Unable to run ROX-Filer: %s"),
222 err
? err
->message
: _("unknown error"));
228 static void set_entry(DesktopEntriesData
*ded
, DesktopEntry
*xde
,
231 gtk_list_store_set(ded
->list_store
, iter
,
232 ColData
, xde
, ColName
, xde
->name
,
233 ColRoxOnly
, xdesktop_entry_get_only_in_rox(xde
),
234 ColStartInRox
, desktop_entry_get_show_in_rox(xde
),
235 ColRoxOnlySensitive
, xdesktop_entry_can_set_only_in_rox(xde
),
236 ColStartInRoxSensitive
,
237 xdesktop_entry_can_set_start_in_rox(xde
),
241 static void add_entry_to_list_store(DesktopEntriesData
*ded
,
246 gtk_list_store_append(ded
->list_store
, &iter
);
247 set_entry(ded
, xde
, &iter
);
250 static int create_or_edit_dialog(DesktopEntriesData
*ded
,
251 DesktopEntry
*xde
, gboolean create
)
253 GtkWidget
*dialog_w
= gtk_dialog_new_with_buttons(
254 create
? _("New AutoStart Entry") : _("Edit AutoStart Entry"),
255 GTK_WINDOW(ded
->dialog
),
256 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
257 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
258 GTK_STOCK_APPLY
, GTK_RESPONSE_ACCEPT
,
260 GtkDialog
*dialog
= GTK_DIALOG(dialog_w
);
261 GtkBox
*vbox
= GTK_BOX(dialog
->vbox
);
262 GtkWidget
*name_w
= gtk_entry_new();
263 GtkWidget
*command_w
= gtk_entry_new();
264 GtkWidget
*only_show_in
= gtk_entry_new();
265 GtkWidget
*not_show_in
= gtk_entry_new();
266 GtkWidget
*terminal_w
= gtk_check_button_new_with_label(
267 _("Run in terminal"));
268 GtkTable
*table
= GTK_TABLE(gtk_table_new(2, 3, FALSE
));
269 GtkWidget
*expander_w
= gtk_expander_new(_("Advanced"));
270 GtkExpander
*expander
= GTK_EXPANDER(expander_w
);
271 GtkTable
*adv_table
= GTK_TABLE(gtk_table_new(2, 3, FALSE
));
275 gboolean valid
= FALSE
;
278 set_tooltip(name_w
, _("Edit the name of the entry here"));
279 set_tooltip(command_w
, _("Set the command that this entry runs here"));
280 set_tooltip(only_show_in
, _("This is a list of desktop environments in "
281 "which this entry will be started, separated (and terminated) "
282 "by semicolons (';'). This option must be blank if you use the "
283 "\"Don't start in\" option."));
284 #if HAVE_GTK_WIDGET_SET_TOOLTIP_TEXT
285 set_tooltip(not_show_in
, _("This is a list of desktop environments in "
286 "which this entry will <b>not</b> be started, separated (and "
287 "terminated) by semicolons (';'). This option must be blank if "
288 "you use the \"Only start in\" option."));
290 set_tooltip(not_show_in
, _("This is a list of desktop environments in "
291 "which this entry will not be started, separated (and "
292 "terminated) by semicolons (';'). This option must be blank if "
293 "you use the \"Only start in\" option."));
295 set_tooltip(expander_w
,
296 _("Click here to toggle the display of extra options"));
297 set_tooltip(terminal_w
,
298 _("Whether the entry's command should be run in a terminal"));
300 gtk_dialog_set_default_response(dialog
, GTK_RESPONSE_ACCEPT
);
301 gtk_entry_set_activates_default(GTK_ENTRY(name_w
), TRUE
);
302 gtk_entry_set_activates_default(GTK_ENTRY(command_w
), TRUE
);
303 gtk_entry_set_activates_default(GTK_ENTRY(only_show_in
), TRUE
);
304 gtk_entry_set_activates_default(GTK_ENTRY(not_show_in
), TRUE
);
306 label
= gtk_label_new(_("Name"));
307 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
308 gtk_table_attach(table
, label
, 0, 1, 0, 1,
309 GTK_FILL
, GTK_FILL
, 6, 6);
310 gtk_table_attach(table
, name_w
, 1, 2, 0, 1,
311 GTK_FILL
| GTK_EXPAND
, GTK_FILL
, 6, 6);
312 label
= gtk_label_new(_("Command"));
313 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
314 gtk_table_attach(table
, label
, 0, 1, 1, 2,
315 GTK_FILL
, GTK_FILL
, 6, 6);
316 gtk_table_attach(table
, command_w
, 1, 2, 1, 2,
317 GTK_FILL
| GTK_EXPAND
, GTK_FILL
, 6, 6);
319 gtk_container_add(GTK_CONTAINER(expander
), GTK_WIDGET(adv_table
));
320 label
= gtk_label_new(_("Only start in"));
321 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
322 gtk_table_attach(adv_table
, label
, 0, 1, 0, 1,
323 GTK_FILL
, GTK_FILL
, 6, 6);
324 gtk_table_attach(adv_table
, only_show_in
, 1, 2, 0, 1,
325 GTK_FILL
| GTK_EXPAND
, GTK_FILL
, 6, 6);
326 label
= gtk_label_new(_("Don't start in"));
327 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
328 gtk_table_attach(adv_table
, label
, 0, 1, 1, 2,
329 GTK_FILL
, GTK_FILL
, 6, 6);
330 gtk_table_attach(adv_table
, not_show_in
, 1, 2, 1, 2,
331 GTK_FILL
| GTK_EXPAND
, GTK_FILL
, 6, 6);
332 gtk_table_attach(adv_table
, terminal_w
, 0, 2, 2, 3,
333 GTK_FILL
| GTK_EXPAND
, GTK_FILL
, 6, 6);
334 gtk_table_attach(table
, GTK_WIDGET(expander
), 0, 2, 2, 3,
335 GTK_FILL
| GTK_EXPAND
, GTK_SHRINK
, 6, 6);
337 gtk_box_pack_start(vbox
, GTK_WIDGET(table
), TRUE
, TRUE
, 6);
339 gtk_entry_set_text(GTK_ENTRY(name_w
), xde
->name
);
340 gtk_entry_set_text(GTK_ENTRY(command_w
), xde
->exec
);
341 kfval
= g_key_file_get_string(xde
->kf
, _DE
, "OnlyShowIn", NULL
);
342 gtk_entry_set_text(GTK_ENTRY(only_show_in
), kfval
? kfval
: "");
344 kfval
= g_key_file_get_string(xde
->kf
, _DE
, "NotShowIn", NULL
);
345 gtk_entry_set_text(GTK_ENTRY(not_show_in
), kfval
? kfval
: "");
347 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(terminal_w
),
350 gtk_widget_show_all(GTK_WIDGET(vbox
));
353 response
= gtk_dialog_run(dialog
);
354 if (response
== GTK_RESPONSE_ACCEPT
)
356 const char *name_str
= gtk_entry_get_text(GTK_ENTRY(name_w
));
357 const char *command_str
= gtk_entry_get_text(GTK_ENTRY(command_w
));
358 const char *only_show_in_str
=
359 gtk_entry_get_text(GTK_ENTRY(only_show_in
));
360 const char *not_show_in_str
=
361 gtk_entry_get_text(GTK_ENTRY(not_show_in
));
363 if (!name_str
|| !name_str
[0])
365 message_dialog(GTK_WINDOW(dialog
), GTK_MESSAGE_ERROR
,
366 _("The entry must have a name"));
369 if (!command_str
|| !command_str
[0])
371 message_dialog(GTK_WINDOW(dialog
), GTK_MESSAGE_ERROR
,
372 _("The entry must have a command"));
375 if (only_show_in_str
&& only_show_in_str
[0] &&
376 not_show_in_str
&& not_show_in_str
[0])
378 message_dialog(GTK_WINDOW(dialog
), GTK_MESSAGE_ERROR
,
379 _("You can't set both \"Don't start in\" and "
380 "\"Only start in\""));
383 set_keyfile_name(xde
->kf
, name_str
);
384 g_key_file_set_string(xde
->kf
, _DE
, "Exec", command_str
);
385 if (only_show_in_str
&& only_show_in_str
[0])
387 g_key_file_set_value(xde
->kf
, _DE
, "OnlyShowIn",
392 g_key_file_remove_key(xde
->kf
, _DE
, "OnlyShowIn", NULL
);
394 if (not_show_in_str
&& not_show_in_str
[0])
396 g_key_file_set_value(xde
->kf
, _DE
, "NotShowIn",
401 g_key_file_remove_key(xde
->kf
, _DE
, "NotShowIn", NULL
);
403 g_key_file_set_boolean(xde
->kf
, _DE
, "Terminal",
404 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(terminal_w
)));
412 if (response
!= GTK_RESPONSE_DELETE_EVENT
)
413 gtk_widget_destroy(dialog_w
);
417 static void new_entry_dialog_for_entry(DesktopEntriesData
*ded
,
420 if (create_or_edit_dialog(ded
, xde
, TRUE
) == GTK_RESPONSE_ACCEPT
)
422 desktop_entry_read_keyfile(xde
);
423 xdesktop_entry_read_name_from_keyfile(xde
);
424 xdesktop_entry_filenames_from_name(xde
, NULL
);
425 xdesktop_entry_save(xde
);
426 ded
->desktop_entries
= g_list_append(ded
->desktop_entries
, xde
);
427 xde
->deletable
= TRUE
;
428 add_entry_to_list_store(ded
, xde
);
429 shade_buttons_for_selection(ded
);
433 desktop_entry_delete(xde
);
437 static void new_entry_cb(DesktopEntriesData
*ded
)
439 new_entry_dialog_for_entry(ded
, new_desktop_entry());
442 static void edit_entry(DesktopEntriesData
*ded
, DesktopEntry
*xde
,
445 if (create_or_edit_dialog(ded
, xde
, FALSE
) == GTK_RESPONSE_ACCEPT
)
447 desktop_entry_read_keyfile(xde
);
448 xdesktop_entry_read_name_from_keyfile(xde
);
449 xdesktop_entry_save(xde
);
450 set_entry(ded
, xde
, iter
);
451 shade_buttons_for_selection(ded
);
455 static void edit_entry_cb(DesktopEntriesData
*ded
)
460 g_return_if_fail(get_selected_entry_and_iter(ded
, &xde
, &iter
));
461 edit_entry(ded
, xde
, &iter
);
464 static void remove_entry_cb(DesktopEntriesData
*ded
)
469 g_return_if_fail(get_selected_entry_and_iter(ded
, &xde
, &iter
));
470 gtk_list_store_remove(ded
->list_store
, &iter
);
471 ded
->desktop_entries
= g_list_remove(ded
->desktop_entries
, xde
);
472 shade_buttons_for_selection(ded
);
473 g_unlink(xde
->pathname
);
474 desktop_entry_delete(xde
);
477 static void row_activated_cb(GtkTreeView
*tree_view
, GtkTreePath
*path
,
478 GtkTreeViewColumn
*column
, DesktopEntriesData
*ded
)
483 get_entry_and_iter_from_path(ded
, &xde
, &iter
, path
);
484 edit_entry(ded
, xde
, &iter
);
487 static DesktopEntry
*desktop_entry_from_rox_app(const char *dir
)
492 static DesktopEntry
*desktop_entry_from_desktop_file(const char *filename
)
497 static DesktopEntry
*desktop_entry_from_executable(const char *dir
)
502 static DesktopEntry
*desktop_entry_from_uri(const char *uri
)
504 DesktopEntry
*entry
= NULL
;
506 if (g_str_has_prefix(uri
, "file://"))
510 else if (strchr(uri
, ':'))
512 g_warning(_("Unrecognised URI %s"), uri
);
515 if (g_file_test(uri
, G_FILE_TEST_IS_DIR
))
517 char *apprun
= g_build_filename(uri
, "AppRun", NULL
);
519 if (g_file_test(apprun
, G_FILE_TEST_IS_EXECUTABLE
))
522 return desktop_entry_from_rox_app(uri
);
525 else if ((entry
= desktop_entry_from_desktop_file(uri
)) != NULL
)
527 else if (g_file_test(uri
, G_FILE_TEST_IS_EXECUTABLE
))
528 return desktop_entry_from_executable(uri
);
529 g_warning(_("Unable to create an entry from %s"), uri
);
537 static void drag_received_cb(GtkWidget
*widget
, GdkDragContext
*context
,
538 gint x
, gint y
, GtkSelectionData
*selection_data
, guint info
,
539 guint time
, DesktopEntriesData
*ded
)
541 gboolean valid
= FALSE
;
543 if (selection_data
->format
!= 8 || !selection_data
->length
)
545 g_critical(_("Invalid selection data (format %d, length %d)"),
546 selection_data
->format
, selection_data
->length
);
548 else if (info
== DragUriList
)
550 char **uris
= gtk_selection_data_get_uris(selection_data
);
555 DesktopEntry
**entries
= NULL
;
557 for (n
= 0; uris
[n
]; ++n
);
558 entries
= g_new0(DesktopEntry
*, n
+ 1);
560 for (n
= 0; uris
[n
]; ++n
)
562 DesktopEntry
*de
= desktop_entry_from_uri(uris
[n
]);
572 gtk_drag_finish(context
, FALSE
, FALSE
, time
);
573 for (n
= 0; entries
[n
]; ++n
)
574 new_entry_dialog_for_entry(ded
, entries
[n
]);
581 gtk_drag_finish(context
, FALSE
, FALSE
, time
);
584 static void set_up_drag_target(GtkWidget
*widget
, DesktopEntriesData
*ded
)
586 static GtkTargetEntry target_table
[] = {
587 { (char *) "text/uri-list", 0, DragUriList
}
590 gtk_drag_dest_set(widget
, GTK_DEST_DEFAULT_ALL
,
591 target_table
, G_N_ELEMENTS(target_table
),
592 GDK_ACTION_COPY
| GDK_ACTION_MOVE
);
593 g_signal_connect(widget
, "drag-data-received",
594 G_CALLBACK(drag_received_cb
), ded
);
597 static DesktopEntriesData
*build_dialog(GList
*desktop_entries
)
599 DesktopEntriesData
*ded
= g_new0(DesktopEntriesData
, 1);
601 GtkCellRenderer
*cell
;
602 GtkTreeViewColumn
*column
;
607 GtkWidget
*btn_hbox2
;
611 ded
->desktop_entries
= desktop_entries
;
612 ded
->dialog
= gtk_dialog_new_with_buttons(_("XDG AutoStart Entries"),
613 NULL
, 0, GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
, NULL
);
615 /* Set up list store */
616 ded
->list_store
= gtk_list_store_new(NumCols
,
617 G_TYPE_POINTER
, G_TYPE_STRING
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
618 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
);
619 for (node
= ded
->desktop_entries
; node
; node
= g_list_next(node
))
620 add_entry_to_list_store(ded
, node
->data
);
622 /* Set up tree view */
623 tvwidget
= gtk_tree_view_new_with_model(
624 GTK_TREE_MODEL(ded
->list_store
));
625 ded
->tree_view
= GTK_TREE_VIEW(tvwidget
);
626 g_signal_connect_swapped(ded
->tree_view
, "cursor-changed",
627 G_CALLBACK(shade_buttons_for_selection
), ded
);
628 g_signal_connect(ded
->tree_view
, "row-activated",
629 G_CALLBACK(row_activated_cb
), ded
);
630 set_tooltip(tvwidget
, _("The entries here are implemented as dektop "
631 "entry files according to the XDG specification"));
632 set_up_drag_target(tvwidget
, ded
);
634 cell
= gtk_cell_renderer_text_new();
635 column
= gtk_tree_view_column_new_with_attributes(_("Name"), cell
,
636 "text", ColName
, NULL
);
637 gtk_tree_view_append_column(ded
->tree_view
, column
);
639 cell
= gtk_cell_renderer_toggle_new();
640 column
= gtk_tree_view_column_new_with_attributes(_("Only in ROX"), cell
,
641 "active", ColRoxOnly
,
642 "activatable", ColRoxOnlySensitive
,
643 "sensitive", ColRoxOnlySensitive
,
645 gtk_tree_view_append_column(ded
->tree_view
, column
);
646 g_signal_connect(cell
, "toggled", G_CALLBACK(rox_only_toggled_cb
), ded
);
648 cell
= gtk_cell_renderer_toggle_new();
649 column
= gtk_tree_view_column_new_with_attributes(_("Start in ROX"), cell
,
650 "active", ColStartInRox
,
651 "activatable", ColStartInRoxSensitive
,
652 "sensitive", ColStartInRoxSensitive
,
654 gtk_tree_view_append_column(ded
->tree_view
, column
);
655 g_signal_connect(cell
, "toggled", G_CALLBACK(start_in_rox_toggled_cb
), ded
);
658 btn_hbox
= gtk_hbox_new(TRUE
, 16);
659 ded
->remove_button
= gtk_button_new_from_stock(GTK_STOCK_DELETE
);
660 g_signal_connect_swapped(ded
->remove_button
, "clicked",
661 G_CALLBACK(remove_entry_cb
), ded
);
662 gtk_box_pack_start_defaults(GTK_BOX(btn_hbox
), ded
->remove_button
);
663 ded
->edit_button
= gtk_button_new_from_stock(GTK_STOCK_EDIT
);
664 g_signal_connect_swapped(ded
->edit_button
, "clicked",
665 G_CALLBACK(edit_entry_cb
), ded
);
666 gtk_box_pack_start_defaults(GTK_BOX(btn_hbox
), ded
->edit_button
);
667 misc_w
= gtk_button_new_from_stock(GTK_STOCK_ADD
);
668 g_signal_connect_swapped(misc_w
, "clicked", G_CALLBACK(new_entry_cb
), ded
);
669 gtk_box_pack_start_defaults(GTK_BOX(btn_hbox
), misc_w
);
671 /* Lay out main TreeView widget */
672 gtk_widget_size_request(tvwidget
, &req
);
673 if (req
.width
< VIEW_MAX_W
)
675 if (req
.width
> VIEW_MAX_W
)
676 req
.width
= VIEW_MAX_W
;
677 if (req
.height
< VIEW_MAX_H
)
679 if (req
.height
> VIEW_MAX_H
)
680 req
.height
= VIEW_MAX_H
;
681 scroll
= gtk_scrolled_window_new(NULL
, NULL
);
682 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll
),
684 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll
),
685 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
686 gtk_container_add(GTK_CONTAINER(scroll
), tvwidget
);
687 gtk_widget_set_size_request(tvwidget
, req
.width
, req
.height
);
689 btn_hbox2
= gtk_hbox_new(FALSE
, 16);
690 misc_w
= gtk_button_new_with_label(
691 _("Open ROX-Session AutoStart directory"));
692 set_tooltip(misc_w
, _("At start-up ROX-Session also automatically runs "
693 "any scripts, executables or ROX applications in its AutoStart "
694 "directory which can be opened with this button"));
695 g_signal_connect_swapped(misc_w
, "clicked",
696 G_CALLBACK(open_rs_as_dir
), ded
->dialog
);
697 gtk_box_pack_end(GTK_BOX(btn_hbox2
), misc_w
, FALSE
, FALSE
, 0);
699 /* Do master lay-out and show everything */
700 vbox
= GTK_BOX(GTK_DIALOG(ded
->dialog
)->vbox
);
701 gtk_box_pack_start(vbox
, scroll
, TRUE
, TRUE
, 6);
702 gtk_box_pack_start(vbox
, btn_hbox
, FALSE
, FALSE
, 6);
703 gtk_box_pack_start(vbox
, btn_hbox2
, FALSE
, FALSE
, 6);
704 shade_buttons_for_selection(ded
);
705 gtk_widget_show_all(GTK_WIDGET(vbox
));
710 int main(int argc
, char **argv
)
713 DesktopEntriesData
*ded
;
714 char *lang
= getenv("LANG");
718 char *sep
= strchr(lang
, '.');
719 int l
= sep
? sep
- lang
: strlen(lang
);
721 locale_name
= g_strdup_printf("%.*s", l
, lang
);
722 sep
= strchr(locale_name
, '_');
725 short_locale_name
= g_strdup_printf("%.*s",
726 (int) (sep
- locale_name
), locale_name
);
733 gtk_init(&argc
, &argv
);
734 desl
= get_desktop_entries((DesktopEntryConstructor
*) xdesktop_entry_new
);
735 ded
= build_dialog(desl
);
736 if (gtk_dialog_run(GTK_DIALOG(ded
->dialog
)) != GTK_RESPONSE_DELETE_EVENT
)
737 gtk_widget_destroy(ded
->dialog
);