Fix a lot of memory leaks.
[lxde/lxpanel.git] / src / gtk-run.c
CommitLineData
08ea5341
HJYP
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
28static 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 );
64ec68dc 37#if GTK_CHECK_VERSION( 2, 8, 0 )
08ea5341
HJYP
38 gtk_entry_completion_set_popup_set_width( comp, TRUE );
39 gtk_entry_completion_set_popup_single_match( comp, FALSE );
a68a48a4 40#endif
08ea5341
HJYP
41 store = gtk_list_store_new( 1, G_TYPE_STRING );
42
43 for( dirname = dirnames; *dirname; ++dirname )
44 {
45 GDir *dir = g_dir_open( *dirname, 0, NULL );
46 const char *name;
47 int i = 0;
48 if( ! dir )
49 continue;
50 while( name = g_dir_read_name( dir ) )
51 {
52 char* filename = g_build_filename( *dirname, name, NULL );
53 if( g_file_test( filename, G_FILE_TEST_IS_EXECUTABLE ) )
54 {
55 if( !g_list_find_custom( list, name, (GCompareFunc)strcmp ) )
56 list = g_list_prepend( list, g_strdup( name ) );
57 }
58 g_free( filename );
59 }
0dcb6bf5 60 g_dir_close( dir );
08ea5341
HJYP
61 }
62 g_strfreev( dirnames );
63
64 for( l = list; l; l = l->next )
65 {
66 GtkTreeIter it;
67 gtk_list_store_append( store, &it );
68 gtk_list_store_set( store, &it, 0, l->data, -1 );
69 g_free( l->data );
70 }
71 g_list_free( list );
72
73 gtk_entry_completion_set_model( comp, (GtkTreeModel*)store );
0dcb6bf5 74 g_object_unref( store );
08ea5341
HJYP
75 gtk_entry_completion_set_text_column( comp, 0 );
76 gtk_entry_set_completion( (GtkEntry*)entry, comp );
0dcb6bf5 77 g_object_unref( G_OBJECT(comp) );
08ea5341
HJYP
78 return FALSE;
79}
80
81static void show_error( GtkWindow* parent_win, const char* msg )
82{
83 GtkWidget* dlg = gtk_message_dialog_new( parent_win,
84 GTK_DIALOG_MODAL,
85 GTK_MESSAGE_ERROR,
86 GTK_BUTTONS_OK, msg );
87 gtk_dialog_run( (GtkDialog*)dlg );
88 gtk_widget_destroy( dlg );
89}
90
91static void on_response( GtkDialog* dlg, gint response, gpointer user_data )
92{
93 GtkEntry* entry = (GtkEntry*)user_data;
94 if( G_LIKELY(response == GTK_RESPONSE_OK) )
95 {
96 GError* err = NULL;
97 if( !g_spawn_command_line_async( gtk_entry_get_text(entry), &err ) )
98 {
99 show_error( (GtkWindow*)dlg, err->message );
100 g_error_free( err );
101 g_signal_stop_emission_by_name( dlg, "response" );
102 return;
103 }
104 }
105 g_source_remove_by_user_data( entry ); /* remove timeout */
106 gtk_widget_destroy( (GtkWidget*)dlg );
107}
108
109void gtk_run()
110{
111 GtkWidget *win, *entry, *hbox;
08ea5341
HJYP
112 win = gtk_dialog_new_with_buttons( _("Run"),
113 NULL,
114 GTK_DIALOG_NO_SEPARATOR,
115 GTK_STOCK_OK, GTK_RESPONSE_OK,
116 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
117 NULL );
118 gtk_dialog_set_default_response( (GtkDialog*)win, GTK_RESPONSE_OK );
119 entry = gtk_entry_new();
120 gtk_entry_set_activates_default( (GtkEntry*)entry, TRUE );
121 gtk_box_pack_start( (GtkBox*)((GtkDialog*)win)->vbox,
122 gtk_label_new(_("Enter the command you want to execute:")),
123 FALSE, FALSE, 8 );
124 hbox = gtk_hbox_new( FALSE, 2 );
125 gtk_box_pack_start( (GtkBox*)hbox,
126 gtk_image_new_from_stock( GTK_STOCK_EXECUTE, GTK_ICON_SIZE_DIALOG ),
127 FALSE, FALSE, 4 );
128 gtk_box_pack_start( (GtkBox*)hbox, entry, TRUE, TRUE, 4 );
129 gtk_box_pack_start( (GtkBox*)((GtkDialog*)win)->vbox,
130 hbox, FALSE, FALSE, 8 );
131 g_signal_connect( win, "response", G_CALLBACK(on_response), entry );
132 gtk_window_set_position( (GtkWindow*)win, GTK_WIN_POS_CENTER );
133 gtk_window_set_default_size( (GtkWindow*)win, 360, -1 );
134 gtk_widget_show_all( win );
8c44345a
HJYP
135 /* g_timeout_add( 500, setup_auto_complete, entry ); */
136 setup_auto_complete( entry );
08ea5341
HJYP
137 gtk_widget_show( (GtkDialog*)win );
138}
139