Support desktop entry in launchbar.
[lxde/lxpanel.git] / src / gtk-run.c
1 /*
2 * gtk-run.c: Little application launcher
3 * Copyright (C) 2006 Hong Jen Tee (PCMan) pcman.tw(AT)gmail.com
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * Compile this program with following command line:
20 * gcc `pkg-config gtk+-2.0 --cflags --libs` gtk-run.c -o gtk-run
21 *
22 */
23
24 #include <gtk/gtk.h>
25 #include <glib/gi18n.h>
26 #include <string.h>
27
28 static gboolean setup_auto_complete( gpointer entry )
29 {
30 GtkListStore* store;
31 GList *list = NULL, *l;
32 gchar **dirname;
33 gchar **dirnames = g_strsplit( g_getenv("PATH"), ":", 0 );
34 GtkEntryCompletion* comp = gtk_entry_completion_new();
35 gtk_entry_completion_set_minimum_key_length( comp, 2 );
36 gtk_entry_completion_set_inline_completion( comp, TRUE );
37 gtk_entry_completion_set_popup_set_width( comp, TRUE );
38 gtk_entry_completion_set_popup_single_match( comp, FALSE );
39 store = gtk_list_store_new( 1, G_TYPE_STRING );
40
41 for( dirname = dirnames; *dirname; ++dirname )
42 {
43 GDir *dir = g_dir_open( *dirname, 0, NULL );
44 const char *name;
45 int i = 0;
46 if( ! dir )
47 continue;
48 while( name = g_dir_read_name( dir ) )
49 {
50 char* filename = g_build_filename( *dirname, name, NULL );
51 if( g_file_test( filename, G_FILE_TEST_IS_EXECUTABLE ) )
52 {
53 if( !g_list_find_custom( list, name, (GCompareFunc)strcmp ) )
54 list = g_list_prepend( list, g_strdup( name ) );
55 }
56 g_free( filename );
57 }
58 }
59 g_strfreev( dirnames );
60
61 for( l = list; l; l = l->next )
62 {
63 GtkTreeIter it;
64 gtk_list_store_append( store, &it );
65 gtk_list_store_set( store, &it, 0, l->data, -1 );
66 g_free( l->data );
67 }
68 g_list_free( list );
69
70 gtk_entry_completion_set_model( comp, (GtkTreeModel*)store );
71 gtk_entry_completion_set_text_column( comp, 0 );
72 gtk_entry_set_completion( (GtkEntry*)entry, comp );
73 return FALSE;
74 }
75
76 static void show_error( GtkWindow* parent_win, const char* msg )
77 {
78 GtkWidget* dlg = gtk_message_dialog_new( parent_win,
79 GTK_DIALOG_MODAL,
80 GTK_MESSAGE_ERROR,
81 GTK_BUTTONS_OK, msg );
82 gtk_dialog_run( (GtkDialog*)dlg );
83 gtk_widget_destroy( dlg );
84 }
85
86 static void on_response( GtkDialog* dlg, gint response, gpointer user_data )
87 {
88 GtkEntry* entry = (GtkEntry*)user_data;
89 if( G_LIKELY(response == GTK_RESPONSE_OK) )
90 {
91 GError* err = NULL;
92 if( !g_spawn_command_line_async( gtk_entry_get_text(entry), &err ) )
93 {
94 show_error( (GtkWindow*)dlg, err->message );
95 g_error_free( err );
96 g_signal_stop_emission_by_name( dlg, "response" );
97 return;
98 }
99 }
100 g_source_remove_by_user_data( entry ); /* remove timeout */
101 gtk_widget_destroy( (GtkWidget*)dlg );
102 }
103
104 void gtk_run()
105 {
106 GtkWidget *win, *entry, *hbox;
107
108 win = gtk_dialog_new_with_buttons( _("Run"),
109 NULL,
110 GTK_DIALOG_NO_SEPARATOR,
111 GTK_STOCK_OK, GTK_RESPONSE_OK,
112 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
113 NULL );
114 gtk_dialog_set_default_response( (GtkDialog*)win, GTK_RESPONSE_OK );
115 entry = gtk_entry_new();
116 gtk_entry_set_activates_default( (GtkEntry*)entry, TRUE );
117 gtk_box_pack_start( (GtkBox*)((GtkDialog*)win)->vbox,
118 gtk_label_new(_("Enter the command you want to execute:")),
119 FALSE, FALSE, 8 );
120 hbox = gtk_hbox_new( FALSE, 2 );
121 gtk_box_pack_start( (GtkBox*)hbox,
122 gtk_image_new_from_stock( GTK_STOCK_EXECUTE, GTK_ICON_SIZE_DIALOG ),
123 FALSE, FALSE, 4 );
124 gtk_box_pack_start( (GtkBox*)hbox, entry, TRUE, TRUE, 4 );
125 gtk_box_pack_start( (GtkBox*)((GtkDialog*)win)->vbox,
126 hbox, FALSE, FALSE, 8 );
127 g_signal_connect( win, "response", G_CALLBACK(on_response), entry );
128 gtk_window_set_position( (GtkWindow*)win, GTK_WIN_POS_CENTER );
129 gtk_window_set_default_size( (GtkWindow*)win, 360, -1 );
130 gtk_widget_show_all( win );
131 g_timeout_add( 500, setup_auto_complete, entry );
132 gtk_widget_show( (GtkDialog*)win );
133 }
134