Commit e27fb553 authored by Mark McLoughlin's avatar Mark McLoughlin Committed by Mark McLoughlin

Random re-formatting foo and: (get_url_from_input): add from Frank's

2003-05-19  Mark McLoughlin  <mark@skynet.ie>

	* panel-run-dialog.[ch]:
	Random re-formatting foo and:
	(get_url_from_input): add from Frank's original libgnome
	patch. Seems it never got in.

2003-05-19  Frank Worsley <fworsley@shaw.ca>

	* panel-run-dialog.c
	* panel-run-dialog.h
	* panel-run-dialog.glade
	the sweet new run program dialog

	* Makefile.am:
	added in the new files

	* menu.c: (add_to_run_dialog):
	* panel-action-button.c: (panel_action_run_program):
	* panel-action-protocol.c: (panel_action_protocol_run_dialog):
	moved to new run dialog function names

	* panel-util.c: (panel_get_unique_uri):
	copied from launcher.c, a function to get a unique uri
	for a given location and file suffix

	* launcher.c: (launcher_location), (panel_launcher_save_ditem):
	now uses new util function to get unique uri

	* panel-util.h:
	updated for new function

	* panel.c:
	don't include gnome-run.h
parent 52ffe563
2003-05-19 Mark McLoughlin <mark@skynet.ie>
* panel-run-dialog.[ch]:
Random re-formatting foo and:
(get_url_from_input): add from Frank's original libgnome
patch. Seems it never got in.
2003-05-19 Frank Worsley <fworsley@shaw.ca>
* panel-run-dialog.c
* panel-run-dialog.h
* panel-run-dialog.glade
the sweet new run program dialog
* Makefile.am:
added in the new files
* menu.c: (add_to_run_dialog):
* panel-action-button.c: (panel_action_run_program):
* panel-action-protocol.c: (panel_action_protocol_run_dialog):
moved to new run dialog function names
* panel-util.c: (panel_get_unique_uri):
copied from launcher.c, a function to get a unique uri
for a given location and file suffix
* launcher.c: (launcher_location), (panel_launcher_save_ditem):
now uses new util function to get unique uri
* panel-util.h:
updated for new function
* panel.c:
don't include gnome-run.h
2003-05-19 Mark McLoughlin <mark@skynet.ie>
* gnome-run.c: (unset_selected): Remove bogus unsetting
......
......@@ -113,7 +113,7 @@ panel_sources = \
panel-gconf.c \
panel-properties-dialog.c \
distribution.c \
gnome-run.c \
panel-run-dialog.c \
menu.c \
menu-util.c \
menu-ditem.c \
......@@ -159,7 +159,7 @@ panel_headers = \
panel-config-global.h \
panel-gconf.h \
distribution.h \
gnome-run.h \
panel-run-dialog.h \
menu.h \
menu-util.h \
menu-ditem.h \
......@@ -249,7 +249,8 @@ gladedir = $(datadir)/gnome/panel
glade_DATA = \
gnome-panel-preferences.glade \
gnome-panel-screenshot.glade \
panel-properties-dialog.glade
panel-properties-dialog.glade \
panel-run-dialog.glade
EXTRA_DIST = \
GNOME_Panel.server.in \
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* grun: Popup a command dialog. Original version by Elliot Lee,
* bloatware edition by Havoc Pennington. Both versions written in 10
* minutes or less. :-)
* Copyright (C) 1998 Havoc Pennington <hp@pobox.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <config.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <libgnome/libgnome.h>
#include <libgnomeui/libgnomeui.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-ops.h>
#include <libgnomevfs/gnome-vfs-mime.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include "gnome-run.h"
#include "disclosure-widget.h"
#include "menu-fentry.h"
#include "menu.h"
#include "panel-util.h"
#include "panel-profile.h"
#include "quick-desktop-reader.h"
#include "nothing.h"
#include "egg-screen-exec.h"
#include "egg-screen-url.h"
#include "panel-stock-icons.h"
#include "panel-multiscreen.h"
#include "panel-a11y.h"
#include "panel-globals.h"
enum {
COLUMN_ICON,
COLUMN_ICON_FILE,
COLUMN_FULLNAME,
COLUMN_COMMENT,
COLUMN_NAME,
COLUMN_EXEC,
NUM_COLUMNS
};
typedef enum {
PANEL_RESPONSE_RUN
} PanelResponseType;
#define ENABLE_LIST_DEFAULT TRUE
#define SHOW_LIST_DEFAULT FALSE
#define IMAGE_SIZE 48.0
static GtkWidget *run_dialog = NULL;
static GSList *add_icon_paths = NULL;
static guint add_icon_idle_id = 0;
static guint add_items_idle_id = 0;
static guint find_icon_timeout_id = 0;
static GList *executables = NULL;
static GCompletion *exe_completion = NULL;
static void update_contents (GtkWidget *dialog);
static void unset_selected (GtkWidget *dialog);
static void unset_pixmap (GtkWidget *gpixmap);
static gboolean find_icon_timeout (gpointer data);
static void
fill_executables_from (const char *dirname)
{
struct dirent *dent;
DIR *dir;
dir = opendir (dirname);
if (dir == NULL)
return;
while ( (dent = readdir (dir)) != NULL) {
char *file = g_strconcat (dirname, "/", dent->d_name, NULL);
if (access (file, X_OK) == 0)
executables = g_list_prepend (executables,
g_strdup (dent->d_name));
}
closedir (dir);
}
static void
fill_executables (void)
{
int i;
const char *path;
char **pathv;
panel_g_list_deep_free (executables);
executables = NULL;
path = g_getenv ("PATH");
if (path == NULL ||
path[0] == '\0')
return;
pathv = g_strsplit (path, ":", 0);
for (i = 0; pathv[i] != NULL; i++)
fill_executables_from (pathv[i]);
g_strfreev (pathv);
}
static void
ensure_completion (void)
{
if (exe_completion == NULL) {
exe_completion = g_completion_new (NULL);
fill_executables ();
g_completion_add_items (exe_completion, executables);
}
}
static void
kill_completion (void)
{
if (executables != NULL) {
panel_g_list_deep_free (executables);
executables = NULL;
}
if (exe_completion != NULL) {
g_completion_free (exe_completion);
exe_completion = NULL;
}
}
static void
get_environment (int *argc,
char ***argv,
int *envc,
char ***envv,
GdkScreen *screen)
{
GList *envar = NULL, *li;
gboolean display_found = FALSE;
int i, moveby;
*envv = NULL;
*envc = 0;
moveby = 0;
for (i = 0; i < *argc; i++) {
if (!strchr ((*argv) [i], '='))
break;
if (!strncmp ((*argv) [i], "DISPLAY", 7))
display_found = TRUE;
envar = g_list_append (envar, g_strdup ((*argv)[i]));
moveby ++;
}
if (!display_found && gdk_screen_get_default () != screen)
envar = g_list_append (
envar, egg_screen_exec_display_string (screen));
if (moveby == *argc) {
panel_g_list_deep_free (envar);
return;
}
if (envar == NULL)
return;
for (i = 0; i < *argc && moveby; i++) {
g_free ((*argv)[i]);
if (i + moveby < *argc) {
(*argv)[i] = (*argv)[i+moveby];
(*argv)[i+moveby] = NULL;
} else {
(*argv)[i] = NULL;
}
}
*argc -= moveby;
*envc = g_list_length (envar);
*envv = g_new0 (char *, *envc + 1);
for (i = 0, li = envar; li != NULL; li = li->next, i++) {
(*envv)[i] = li->data;
li->data = NULL;
}
(*envv)[i] = NULL;
g_list_free (envar);
}
static void
launch_selected (GtkTreeModel *model,
GtkTreeIter *iter,
GtkWidget *dialog)
{
GnomeDesktopItem *ditem;
GnomeEntry *gnome_entry;
GtkWidget *entry;
GError *error = NULL;
GtkToggleButton *terminal;
char *name, *command;
gtk_tree_model_get (model, iter, COLUMN_NAME, &name, -1);
if (!name)
return;
ditem = gnome_desktop_item_new_from_uri (name,
GNOME_DESKTOP_ITEM_LOAD_NO_TRANSLATIONS,
&error);
g_free (name);
if (!ditem) {
panel_error_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"failed_to_load_desktop",
_("<b>Failed to run this program</b>\n\nDetails: %s"),
error->message);
g_clear_error (&error);
return;
}
terminal = GTK_TOGGLE_BUTTON (
g_object_get_data (G_OBJECT (dialog), "terminal"));
/* Honor "run in terminal" button */
gnome_desktop_item_set_boolean (ditem,
GNOME_DESKTOP_ITEM_TERMINAL,
terminal->active);
if (!panel_ditem_launch (
ditem, NULL, 0,
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
&error)) {
panel_error_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"failed_to_load_desktop",
_("<b>Failed to run this program</b>\n\nDetails: %s"),
error->message);
g_clear_error (&error);
}
/* save command history */
gnome_entry = g_object_get_data (G_OBJECT (dialog), "gnome_entry");
entry = g_object_get_data (G_OBJECT (dialog), "entry");
command = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
gnome_entry_prepend_history (gnome_entry, TRUE, command);
g_free (command);
gnome_desktop_item_unref (ditem);
}
static void
run_dialog_response (GtkWidget *w, int response, gpointer data)
{
GtkWidget *entry;
GtkWidget *list;
GnomeEntry *gnome_entry;
char **argv = NULL;
char **temp_argv = NULL;
int argc, temp_argc;
char *s = NULL;
char *escaped = NULL;
char *disk = NULL;
char **envv = NULL;
int envc;
GError *error = NULL;
if (response == GTK_RESPONSE_HELP) {
panel_show_help (
gtk_window_get_screen (GTK_WINDOW (w)),
"wgoseditmainmenu.xml", "gospanel-23");
/* just return as we don't want to close */
return;
} else if (response != PANEL_RESPONSE_RUN) {
goto return_and_close;
}
if (g_object_get_data (G_OBJECT (run_dialog), "use_list")) {
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
list = g_object_get_data (G_OBJECT (run_dialog), "program_list");
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
/* just return if nothing selected */
if ( ! gtk_tree_selection_get_selected (selection,
&model, &iter))
return;
launch_selected (model, &iter, w);
} else {
GtkToggleButton *terminal;
entry = g_object_get_data (G_OBJECT (w), "entry");
s = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
if (string_empty (s))
goto return_and_close;
escaped = g_markup_escape_text (s, -1);
disk = g_locale_from_utf8 (s, -1, NULL, NULL, NULL);
/* save command in history */
gnome_entry = g_object_get_data (G_OBJECT (w), "gnome_entry");
gnome_entry_prepend_history (gnome_entry, TRUE, s);
/* evil eggies, do not translate! */
if (strcmp (s, "you shall bring us a shrubbery") == 0) {
panel_info_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"ni_ni_ni_ni",
"NI! NI! NI! NI! NI! NI!");
goto return_and_close;
} else if (strcmp (s, "supreme executive power") == 0) {
panel_info_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"evil",
"Listen -- strange women lying in\n"
"ponds distributing swords is no\n"
"basis for a system of government.\n"
"Supreme executive power derives from\n"
"a mandate from the masses, not from\n"
"some farcical aquatic ceremony!");
goto return_and_close;
} else if (strcmp (s, "free the fish") == 0) {
start_screen_check ();
goto return_and_close;
} else if (strcmp (s, "gegls from outer space") == 0) {
start_geginv ();
goto return_and_close;
} else if (strcmp (s, "End world hunger") == 0) {
egg_url_show_on_screen (
"http://www.wfp.org",
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
NULL);
goto return_and_close;
}
/* Somewhat of a hack I suppose */
if (panel_is_url (s)) {
/* FIXME: URLs are in UTF8 ... right? */
egg_url_show_on_screen (
s, gtk_window_get_screen (GTK_WINDOW (run_dialog)), NULL);
goto return_and_close;
}
/* Note, the command is taken to have to be in disk encoding
* even though it could contain strings, but more likely
* it is all filenames and thus should be in disk encoding */
if ( ! g_shell_parse_argv (disk, &temp_argc, &temp_argv, &error)) {
g_clear_error (&error);
error = NULL;
if ( ! g_shell_parse_argv (s, &temp_argc, &temp_argv, &error)) {
panel_error_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"run_error",
_("<b>Failed to execute command:</b> '%s'\n\nDetails: %s"),
escaped, error->message);
g_clear_error (&error);
goto return_and_close;
}
}
get_environment (
&temp_argc, &temp_argv, &envc, &envv,
gtk_window_get_screen (GTK_WINDOW (run_dialog)));
terminal = GTK_TOGGLE_BUTTON (
g_object_get_data (G_OBJECT (w), "terminal"));
if (terminal->active) {
char **term_argv;
int term_argc;
gnome_config_get_vector ("/Gnome/Applications/Terminal",
&term_argc, &term_argv);
if (term_argv) {
int i;
argv = g_new(char *, term_argc + temp_argc + 1);
argc = term_argc + temp_argc;
for(i = 0; i < term_argc; i++) {
argv[i] = term_argv[i];
term_argv[i] = NULL;
}
for(i = term_argc; i < term_argc+temp_argc; i++) {
argv[i] = temp_argv[i-term_argc];
temp_argv[i-term_argc] = NULL;
}
argv[i] = NULL;
g_free (term_argv);
} else {
char *check;
int i;
check = g_find_program_in_path ("gnome-terminal");
argv = g_new(char *, 2 + temp_argc + 1);
argc = 2 + temp_argc;
if(!check) {
argv[0] = g_strdup ("xterm");
argv[1] = g_strdup ("-e");
} else {
argv[0] = check;
argv[1] = g_strdup ("-x");
}
for(i = 2; i < 2+temp_argc; i++) {
argv[i] = temp_argv[i-2];
temp_argv[i-2] = NULL;
}
argv[i] = NULL;
}
} else {
argv = temp_argv;
temp_argv = NULL;
argc = temp_argc;
}
if (gnome_execute_async_with_env (g_get_home_dir (),
argc, argv,
envc, envv) < 0) {
/* if all else fails we try to open the file with an app */
char *path;
char *command = NULL;
GError *error = NULL;
GnomeVFSFileInfo *info = NULL;
if (!g_path_is_absolute (s)) {
path = g_strconcat (g_get_home_dir (), "/", s, NULL);
} else {
path = g_strdup (s);
}
info = gnome_vfs_file_info_new ();
if (gnome_vfs_get_file_info (path,info,
GNOME_VFS_FILE_INFO_FOLLOW_LINKS) != GNOME_VFS_OK) {
panel_error_dialog(
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"run_error",
_("<b>Failed to execute command:</b> '%s'\n\nDetails: %s"),
escaped, g_strerror (errno));
g_free (path);
gnome_vfs_file_info_unref (info);
goto return_and_close;
}
if (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
command = g_strconcat ("nautilus ", path, NULL);
} else {
char *mime_info;
GnomeVFSMimeApplication *app;
mime_info = gnome_vfs_get_mime_type (path);
app = gnome_vfs_mime_get_default_application (mime_info);
if (app != NULL) {
command = g_strconcat (app->command, " ", path, NULL);
}
gnome_vfs_mime_application_free (app);
g_free (mime_info);
if (command == NULL) {
panel_error_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"run_error",
_("<b>Failed to open file:</b> '%s'\n\n"
"Details: no application available to open file"),
escaped);
gnome_vfs_file_info_unref (info);
g_free (path);
goto return_and_close;
}
}
if (!egg_screen_execute_command_line_async (
gtk_window_get_screen (GTK_WINDOW (run_dialog)), command, &error)) {
panel_error_dialog (
gtk_window_get_screen (GTK_WINDOW (run_dialog)),
"run_error",
_("<b>Failed to open file:</b> '%s'\n\nDetails: %s"),
escaped, error->message);
g_clear_error (&error);
}
gnome_vfs_file_info_unref (info);
g_free (path);
g_free (command);
}
}
return_and_close:
g_strfreev (argv);
g_strfreev (temp_argv);
g_strfreev (envv);
g_free (s);
g_free (escaped);
g_free (disk);
gtk_widget_destroy (w);
}
static char *
quote_string (const char *s)
{
const char *p;
for (p = s; *p != '\0'; p++) {
if ((*p >= 'a' && *p <= 'z') ||
(*p >= 'A' && *p <= 'Z') ||
(*p >= '0' && *p <= '9') ||
strchr ("-_./=:", *p) != NULL)
;
else
return g_shell_quote (s);
}
return g_strdup (s);
}
static void
append_file_utf8 (GtkWidget *entry, const char *file)
{
const char *text;
char *quoted = quote_string (file);
text = gtk_entry_get_text (GTK_ENTRY (entry));
if (string_empty (text)) {
gtk_entry_set_text (GTK_ENTRY (entry), quoted);
} else {
char *new = g_strconcat (text, " ", quoted, NULL);
gtk_entry_set_text (GTK_ENTRY (entry), new);
g_free (new);
}
g_free (quoted);
}
static void
append_file (GtkWidget *entry, const char *file)
{
char *utf8_file = g_filename_to_utf8 (file, -1, NULL, NULL, NULL);
if (utf8_file != NULL) {
append_file_utf8 (entry, utf8_file);
g_free (utf8_file);
}
}
static void
browse_ok (GtkWidget *widget, GtkFileSelection *fsel)
{
const char *fname;
GtkWidget *entry;
g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
entry = g_object_get_data (G_OBJECT (fsel), "entry");
fname = gtk_file_selection_get_filename (fsel);
if (fname != NULL) {
append_file (entry, fname);
gtk_widget_grab_focus (entry);
}
gtk_widget_destroy (GTK_WIDGET (fsel));
}
static void
browse (GtkWidget *w, GtkWidget *entry)
{
char *home;
GtkFileSelection *fsel;
fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Choose a file")));
home = g_strconcat (g_get_home_dir (), "/", NULL);
gtk_file_selection_set_filename (fsel, home);
g_free (home);
gtk_window_set_transient_for (GTK_WINDOW (fsel),
GTK_WINDOW (run_dialog));
g_object_set_data (G_OBJECT (fsel), "entry", entry);
g_signal_connect (G_OBJECT (fsel->ok_button), "clicked",
G_CALLBACK (browse_ok), fsel);
g_signal_connect_swapped (G_OBJECT (fsel->cancel_button), "clicked",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (fsel));
panel_signal_connect_object_while_alive
(G_OBJECT (entry), "destroy",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (fsel));
gtk_window_present (GTK_WINDOW (fsel));
}
static gboolean
entry_event (GtkEntry * entry, GdkEventKey * event, gpointer data)
{
if (event->type != GDK_KEY_PRESS)
return FALSE;
/* completion */
if ((event->keyval == GDK_Tab) &&
(event->state & GDK_CONTROL_MASK)) {
gchar* prefix;
gchar* nprefix = NULL;
gint pos;
ensure_completion ();
pos = gtk_editable_get_position (GTK_EDITABLE (entry));
prefix = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, pos);
g_completion_complete (exe_completion, prefix, &nprefix);
if (nprefix != NULL &&
strlen (nprefix) > strlen (prefix)) {
gtk_editable_insert_text (GTK_EDITABLE (entry),
nprefix + pos,
strlen (nprefix) -
strlen (prefix),
&pos);
gtk_editable_set_position (GTK_EDITABLE (entry), pos);
} else {
gdk_beep ();
}
g_free (nprefix);
g_free (prefix);
return TRUE;
}
return FALSE;
}
static void
sync_entry_to_list (GtkWidget *dialog)
{
GtkWidget *entry;
gboolean blocked;
blocked = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
"sync_entry_to_list_blocked"));
if (blocked)
return;
if (panel_profile_get_enable_program_list ()) {
unset_selected (dialog