[nautilus/wip/apoos-maximus/gsoc2020: 15/27] properties-window: Stop using NautilusMimeApplicationChooser class
- From: António Fernandes <antoniof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/apoos-maximus/gsoc2020: 15/27] properties-window: Stop using NautilusMimeApplicationChooser class
- Date: Sun, 2 Aug 2020 17:30:00 +0000 (UTC)
commit 425d42a60f6e4b686eeea90e8ea3743d6f4d5aa1
Author: Apoorv Sachan <apoorv 99 sachan gmail com>
Date: Sat Jul 25 22:24:07 2020 +0530
properties-window: Stop using NautilusMimeApplicationChooser class
The template UI definition has the Open With tab empty. This is
because its contents come from the NautilusMimeApplicationChooser
widget.
But a separate abstraction for choosing appications based on MIME
types isn't required as GTK provides GtkAppChooser.
The other widgets can be neatly tucked away in the UI built using
XML templates to achieve the same results, and at the same time
allowing the open-with page to be customizable in Glade.
Some functions are adapted from mime-application-chooser.c, but
modified to remove any dependency on that class.
src/nautilus-properties-window.c | 309 ++++++++++++++++++++++++-
src/resources/ui/nautilus-properties-window.ui | 86 ++++++-
2 files changed, 384 insertions(+), 11 deletions(-)
---
diff --git a/src/nautilus-properties-window.c b/src/nautilus-properties-window.c
index 2fcaa7a37..047d3b4b8 100644
--- a/src/nautilus-properties-window.c
+++ b/src/nautilus-properties-window.c
@@ -44,9 +44,10 @@
#include "nautilus-icon-info.h"
#include "nautilus-metadata.h"
#include "nautilus-mime-actions.h"
-#include "nautilus-mime-application-chooser.h"
#include "nautilus-module.h"
+#include "nautilus-signaller.h"
#include "nautilus-ui-utilities.h"
+#include "nautilus-signaller.h"
#define PREVIEW_IMAGE_WIDTH 96
@@ -203,6 +204,14 @@ struct _NautilusPropertiesWindow
/* Open With tab Widgets */
GtkWidget *open_with_box;
+ GtkWidget *open_with_label;
+ GtkWidget *app_chooser_widget_box;
+ GtkWidget *app_chooser_widget;
+ GtkWidget *reset_button;
+ GtkWidget *add_button;
+ GtkWidget *set_as_default_button;
+ char *content_type;
+ GList *open_with_files;
GroupChange *group_change;
OwnerChange *owner_change;
@@ -4974,16 +4983,293 @@ should_show_open_with (NautilusPropertiesWindow *window)
return !hide;
}
+static void
+add_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ NautilusPropertiesWindow *window = NAUTILUS_PROPERTIES_WINDOW (user_data);
+ GAppInfo *info;
+ gchar *message;
+ GError *error = NULL;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (window->app_chooser_widget));
+
+ if (info == NULL)
+ {
+ return;
+ }
+
+ g_app_info_set_as_last_used_for_type (info, window->content_type, &error);
+
+ if (error != NULL)
+ {
+ message = g_strdup_printf (_("Error while adding “%s”: %s"),
+ g_app_info_get_display_name (info), error->message);
+ show_dialog (_("Could not add application"),
+ message,
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (window))),
+ GTK_MESSAGE_ERROR);
+ g_error_free (error);
+ g_free (message);
+ }
+ else
+ {
+ gtk_app_chooser_refresh (GTK_APP_CHOOSER (window->app_chooser_widget));
+ g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed");
+ }
+
+ g_object_unref (info);
+}
+
+static void
+remove_clicked_cb (GtkMenuItem *item,
+ gpointer user_data)
+{
+ NautilusPropertiesWindow *window = NAUTILUS_PROPERTIES_WINDOW (user_data);
+ GError *error;
+ GAppInfo *info;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (window->app_chooser_widget));
+
+ if (info)
+ {
+ error = NULL;
+ if (!g_app_info_remove_supports_type (info,
+ window->content_type,
+ &error))
+ {
+ show_dialog (_("Could not forget association"),
+ error->message,
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (window))),
+ GTK_MESSAGE_ERROR);
+ g_error_free (error);
+ }
+
+ gtk_app_chooser_refresh (GTK_APP_CHOOSER (window->app_chooser_widget));
+ g_object_unref (info);
+ }
+
+ g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed");
+}
+
+static void
+populate_popup_cb (GtkAppChooserWidget *widget,
+ GtkMenu *menu,
+ GAppInfo *app,
+ gpointer user_data)
+{
+ GtkWidget *item;
+ NautilusPropertiesWindow *window = NAUTILUS_PROPERTIES_WINDOW (user_data);
+
+ if (g_app_info_can_remove_supports_type (app))
+ {
+ item = gtk_menu_item_new_with_label (_("Forget association"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ g_signal_connect (item, "activate",
+ G_CALLBACK (remove_clicked_cb), window);
+ }
+}
+
+static void
+reset_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ NautilusPropertiesWindow *window;
+
+ window = NAUTILUS_PROPERTIES_WINDOW (user_data);
+
+ g_app_info_reset_type_associations (window->content_type);
+ gtk_app_chooser_refresh (GTK_APP_CHOOSER (window->app_chooser_widget));
+
+ g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed");
+}
+
+static void
+set_as_default_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ NautilusPropertiesWindow *window = NAUTILUS_PROPERTIES_WINDOW (user_data);
+ GAppInfo *info;
+ GError *error = NULL;
+ gchar *message = NULL;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (window->app_chooser_widget));
+
+ g_app_info_set_as_default_for_type (info, window->content_type,
+ &error);
+
+ if (error != NULL)
+ {
+ message = g_strdup_printf (_("Error while setting “%s” as default application: %s"),
+ g_app_info_get_display_name (info), error->message);
+ show_dialog (_("Could not set as default"),
+ message,
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (window))),
+ GTK_MESSAGE_ERROR);
+ }
+
+ g_object_unref (info);
+
+ gtk_app_chooser_refresh (GTK_APP_CHOOSER (window->app_chooser_widget));
+ g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed");
+}
+
+static gint
+app_compare (gconstpointer a,
+ gconstpointer b)
+{
+ return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b));
+}
+
+static gboolean
+app_info_can_add (GAppInfo *info,
+ const gchar *content_type)
+{
+ GList *recommended, *fallback;
+ gboolean retval = FALSE;
+
+ recommended = g_app_info_get_recommended_for_type (content_type);
+ fallback = g_app_info_get_fallback_for_type (content_type);
+
+ if (g_list_find_custom (recommended, info, app_compare))
+ {
+ goto out;
+ }
+
+ if (g_list_find_custom (fallback, info, app_compare))
+ {
+ goto out;
+ }
+
+ retval = TRUE;
+
+out:
+ g_list_free_full (recommended, g_object_unref);
+ g_list_free_full (fallback, g_object_unref);
+
+ return retval;
+}
+
+static void
+application_selected_cb (GtkAppChooserWidget *widget,
+ GAppInfo *info,
+ gpointer user_data)
+{
+ NautilusPropertiesWindow *window = NAUTILUS_PROPERTIES_WINDOW (user_data);
+ GAppInfo *default_app;
+
+ default_app = g_app_info_get_default_for_type (window->content_type, FALSE);
+ if (default_app != NULL)
+ {
+ gtk_widget_set_sensitive (window->set_as_default_button,
+ !g_app_info_equal (info, default_app));
+ g_object_unref (default_app);
+ }
+ gtk_widget_set_sensitive (window->add_button,
+ app_info_can_add (info, window->content_type));
+}
+
+static void
+application_chooser_apply_labels (NautilusPropertiesWindow *window)
+{
+ gchar *label, *extension = NULL, *description = NULL;
+ gint num_files;
+ NautilusFile *file;
+
+ num_files = g_list_length (window->open_with_files);
+ file = window->open_with_files->data;
+
+ /* here we assume all files are of the same content type */
+ if (g_content_type_is_unknown (window->content_type))
+ {
+ extension = nautilus_file_get_extension (file);
+
+ /* Translators: the %s here is a file extension */
+ description = g_strdup_printf (_("%s document"), extension);
+ }
+ else
+ {
+ description = g_content_type_get_description (window->content_type);
+ }
+
+ if (num_files > 1)
+ {
+ /* Translators; %s here is a mime-type description */
+ label = g_strdup_printf (_("Open all files of type “%s” with"),
+ description);
+ }
+ else
+ {
+ gchar *display_name;
+ display_name = nautilus_file_get_display_name (file);
+
+ /* Translators: first %s is filename, second %s is mime-type description */
+ label = g_strdup_printf (_("Select an application to open “%s” and other files of type “%s”"),
+ display_name, description);
+
+ g_free (display_name);
+ }
+
+ gtk_label_set_markup (GTK_LABEL (window->open_with_label), label);
+
+ g_free (label);
+ g_free (extension);
+ g_free (description);
+}
+
+static void
+setup_app_chooser_area (NautilusPropertiesWindow *window)
+{
+ GAppInfo *info;
+
+ window->app_chooser_widget = gtk_app_chooser_widget_new (window->content_type);
+ gtk_box_pack_start (GTK_BOX (window->app_chooser_widget_box), window->app_chooser_widget, TRUE, TRUE, 6);
+
+ gtk_app_chooser_widget_set_show_default (GTK_APP_CHOOSER_WIDGET (window->app_chooser_widget), TRUE);
+ gtk_app_chooser_widget_set_show_fallback (GTK_APP_CHOOSER_WIDGET (window->app_chooser_widget), TRUE);
+ gtk_app_chooser_widget_set_show_other (GTK_APP_CHOOSER_WIDGET (window->app_chooser_widget), TRUE);
+ gtk_widget_show (window->app_chooser_widget);
+ g_signal_connect (window->reset_button, "clicked",
+ G_CALLBACK (reset_clicked_cb),
+ window);
+ g_signal_connect (window->add_button, "clicked",
+ G_CALLBACK (add_clicked_cb),
+ window);
+ g_signal_connect (window->set_as_default_button, "clicked",
+ G_CALLBACK (set_as_default_clicked_cb),
+ window);
+
+ /* initialize sensitivity */
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (window->app_chooser_widget));
+ if (info != NULL)
+ {
+ application_selected_cb (GTK_APP_CHOOSER_WIDGET (window->app_chooser_widget),
+ info, window);
+ g_object_unref (info);
+ }
+
+ g_signal_connect (window->app_chooser_widget,
+ "application-selected",
+ G_CALLBACK (application_selected_cb),
+ window);
+ g_signal_connect (window->app_chooser_widget,
+ "populate-popup",
+ G_CALLBACK (populate_popup_cb),
+ window);
+
+ application_chooser_apply_labels (window);
+}
+
static void
create_open_with_page (NautilusPropertiesWindow *window)
{
- GtkWidget *vbox;
- char *mime_type;
GList *files = NULL;
NautilusFile *target_file;
target_file = get_target_file (window);
- mime_type = nautilus_file_get_mime_type (target_file);
+ window->content_type = nautilus_file_get_mime_type (target_file);
if (!is_multi_file_window (window))
{
@@ -4998,13 +5284,9 @@ create_open_with_page (NautilusPropertiesWindow *window)
}
}
- vbox = nautilus_mime_application_chooser_new (files, mime_type);
- gtk_box_pack_start (GTK_BOX (window->open_with_box), vbox, TRUE, TRUE, 0);
-
+ window->open_with_files = files;
+ setup_app_chooser_area (window);
gtk_widget_show_all (window->open_with_box);
- g_free (mime_type);
- g_list_free (files);
- g_object_set_data_full (G_OBJECT (vbox), "help-uri", g_strdup ("help:gnome-help/files-open"), g_free);
}
@@ -5494,6 +5776,8 @@ real_finalize (GObject *object)
g_list_free_full (window->mime_list, g_free);
g_free (window->pending_name);
+ g_free (window->content_type);
+ g_list_free (window->open_with_files);
if (window->select_idle_id != 0)
{
@@ -5831,6 +6115,11 @@ nautilus_properties_window_class_init (NautilusPropertiesWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow,
change_permissions_button_box);
gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, change_permissions_button);
gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, open_with_box);
+ gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, open_with_label);
+ gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, app_chooser_widget_box);
+ gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, reset_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, add_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusPropertiesWindow, set_as_default_button);
}
static void
diff --git a/src/resources/ui/nautilus-properties-window.ui b/src/resources/ui/nautilus-properties-window.ui
index f2caa3259..f4425caa6 100644
--- a/src/resources/ui/nautilus-properties-window.ui
+++ b/src/resources/ui/nautilus-properties-window.ui
@@ -1170,9 +1170,93 @@
<child>
<object class="GtkBox" id="open_with_box">
<property name="can_focus">False</property>
+ <property name="border_width">8</property>
<property name="orientation">vertical</property>
<child>
- <placeholder/>
+ <object class="GtkLabel" id="open_with_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="max_width_chars">60</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="app_chooser_widget_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="app_chooser_button_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset_button">
+ <property name="label" translatable="yes">Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="set_as_default_button">
+ <property name="label" translatable="yes">Set as default</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">6</property>
+ <property name="position">2</property>
+ </packing>
</child>
</object>
<packing>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]