summaryrefslogtreecommitdiff
path: root/exo-open
diff options
context:
space:
mode:
authorNick Schermer <nick@xfce.org>2010-11-13 19:47:40 +0100
committerNick Schermer <nick@xfce.org>2010-11-13 19:56:18 +0100
commita974e2d5feed0ff233d8a1406f0e4f07fc55b6c3 (patch)
treeb638e09046265ee80e04e7dc4e918d522200079b /exo-open
parenta581e8e3edd15853db531d706ae2ff036b01ae47 (diff)
downloadexo-a974e2d5feed0ff233d8a1406f0e4f07fc55b6c3.tar.gz
Make exo-open more standalone (bug #6573).
Not all file managers support file locations, so instead try other launch methodes first. If not category is supplied in for exo-open we try to following steps: - Known uri for preferred apps (mailto, http(s), ftp(s), trash) -> launch through exo_execute. - File type is a directory -> Launch through exo_execute as a file manager - Lookup default application for the content type -> Launch it - Fallback to gtk_show_uri() -> Who knows what others find. With those steps we also bypass most of the GIO module, which is not going to build with glib 2.27 anyways.
Diffstat (limited to 'exo-open')
-rw-r--r--exo-open/main.c213
1 files changed, 185 insertions, 28 deletions
diff --git a/exo-open/main.c b/exo-open/main.c
index e2756a3..9fbfd4e 100644
--- a/exo-open/main.c
+++ b/exo-open/main.c
@@ -76,6 +76,21 @@ static GOptionEntry entries[] =
{ NULL, },
};
+typedef struct _KnownSchemes KnownSchemes;
+struct _KnownSchemes
+{
+ const gchar *pattern;
+ const gchar *category;
+};
+
+static KnownSchemes known_schemes[] =
+{
+ { "^(https?|ftps?|gopher)$", "WebBrowser" },
+ { "^mailto$", "MailReader" },
+ /* no file here, because we handle directories and files differently */
+ { "^(trash)$", "FileManager" }
+};
+
static void
@@ -214,8 +229,163 @@ exo_open_find_scheme (const gchar *string)
-int
-main (int argc, char **argv)
+static gboolean
+exo_open_launch_category (const gchar *category,
+ const gchar *parameters)
+{
+ GtkWidget *dialog;
+ GError *error = NULL;
+
+#ifndef NDEBUG
+ g_debug ("category='%s', wd='%s', parameters='%s'", category, opt_working_directory, parameters);
+#endif
+
+ /* run the preferred application */
+ if (!exo_execute_preferred_application (category, parameters, opt_working_directory, NULL, &error))
+ {
+ /* display an error dialog */
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ _("Failed to launch preferred application for category \"%s\"."), category);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+exo_open_uri_known_category (const gchar *uri,
+ const gchar *scheme,
+ gboolean *succeed)
+{
+ guint i;
+ const gchar *category = NULL;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (scheme != NULL, FALSE);
+
+ /* check if the scheme matches a known preferred application type */
+ for (i = 0; category == NULL && i < G_N_ELEMENTS (known_schemes); i++)
+ {
+ if (g_regex_match_simple (known_schemes[i].pattern, scheme, G_REGEX_CASELESS, 0))
+ {
+ /* launch the preferred application */
+ *succeed = exo_open_launch_category (known_schemes[i].category, uri);
+
+ /* we always return, because we found a matching scheme */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+static gboolean
+exo_open_uri (const gchar *uri,
+ GError **error)
+{
+ GFile *file;
+ gchar *scheme;
+ GFileInfo *file_info;
+ gboolean succeed = FALSE;
+ gboolean retval = FALSE;
+ GFileType file_type;
+ const gchar *content_type;
+ GAppInfo *app_info;
+ gchar *path;
+ const gchar *executable;
+ GList fake_list;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ file = g_file_new_for_uri (uri);
+ scheme = g_file_get_uri_scheme (file);
+
+ /* try to launch common schemes for know preferred applications */
+ if (scheme != NULL && exo_open_uri_known_category (uri, scheme, &retval))
+ {
+ g_free (scheme);
+ return retval;
+ }
+
+ /* handle the uri as a file, maybe we succeed... */
+ file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE, NULL, error);
+ if (file_info != NULL)
+ {
+ file_type = g_file_info_get_file_type (file_info);
+ if (file_type == G_FILE_TYPE_DIRECTORY)
+ {
+ /* directories should go fine with a file manager */
+ retval = exo_open_launch_category ("FileManager", uri);
+ succeed = TRUE;
+ }
+ else
+ {
+ content_type = g_file_info_get_content_type (file_info);
+#ifndef NDEBUG
+ g_debug ("content type=%s", content_type);
+#endif
+ if (G_LIKELY (content_type))
+ {
+ /* try to find a suitable application for this content type */
+ path = g_file_get_path (file);
+ app_info = g_app_info_get_default_for_type (content_type, path == NULL);
+ g_free (path);
+
+ if (app_info != NULL)
+ {
+ /* make sure we don't loop somehow */
+ executable = g_app_info_get_executable (app_info);
+#ifndef NDEBUG
+ g_debug ("default executable=%s", executable);
+#endif
+ if (g_strcmp0 (executable, "exo-open") != 0)
+ {
+ fake_list.data = (gpointer) uri;
+ fake_list.prev = fake_list.next = NULL;
+
+ /* launch it */
+ retval = g_app_info_launch_uris (app_info, &fake_list, NULL, error);
+ succeed = TRUE;
+ }
+
+ g_object_unref (G_OBJECT (app_info));
+ }
+ }
+ }
+
+ g_object_unref (G_OBJECT (file_info));
+ }
+
+ g_object_unref (G_OBJECT (file));
+ g_free (scheme);
+
+ /* our last try... */
+ if (!succeed)
+ {
+#ifndef NDEBUG
+ g_debug ("use gtk_show_uri()");
+#endif
+ retval = gtk_show_uri (NULL, uri, 0, error);
+ }
+
+ return retval;
+}
+
+
+
+gint
+main (gint argc, gchar **argv)
{
GOptionContext *context;
GtkWidget *dialog;
@@ -300,25 +470,10 @@ main (int argc, char **argv)
parameter = NULL;
}
-#ifndef NDEBUG
- g_debug ("launch=%s, wd=%s, parameters (%d)=%s", opt_launch, opt_working_directory, argc, parameter);
-#endif
-
/* run the preferred application */
- if (!exo_execute_preferred_application (opt_launch, parameter, opt_working_directory, NULL, &err))
- {
- /* display an error dialog */
- dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Failed to launch preferred application for category \"%s\"."),
- opt_launch);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", err->message);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- result = EXIT_FAILURE;
- g_error_free (err);
- }
+ if (!exo_open_launch_category (opt_launch, parameter))
+ result = EXIT_FAILURE;
- /* cleanup */
g_free (parameter);
}
else if (argc > 1)
@@ -357,20 +512,22 @@ main (int argc, char **argv)
result = EXIT_FAILURE;
}
- else if (!gtk_show_uri (NULL, uri, 0, &err))
+ else if (!exo_open_uri (uri, &err))
{
- /* display an error dialog */
- dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Failed to open URI \"%s\"."), uri);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", err->message);
- g_error_free (err);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
+ if (err != NULL)
+ {
+ /* display an error dialog */
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ _("Failed to open URI \"%s\"."), uri);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", err->message);
+ g_error_free (err);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
result = EXIT_FAILURE;
}
- /* cleanup */
g_free (uri);
}
}