From 58228a6de2d84f9283853a18fe3eb6c52f204eb1 Mon Sep 17 00:00:00 2001
From: Andre Miranda <andreldm@xfce.org>
Date: Tue, 12 Jan 2021 15:31:39 +0100
Subject: [PATCH] Add option to forget application association (Issue #197)

Fixes #197
---
 thunar/thunar-chooser-dialog.c | 80 +++++++++++++++++++++++++++++++++-
 thunar/thunar-chooser-model.c  | 15 ++++---
 thunar/thunar-chooser-model.h  |  1 +
 3 files changed, 88 insertions(+), 8 deletions(-)

diff --git a/thunar/thunar-chooser-dialog.c b/thunar/thunar-chooser-dialog.c
index 65986ecf1..91fe07c70 100644
--- a/thunar/thunar-chooser-dialog.c
+++ b/thunar/thunar-chooser-dialog.c
@@ -72,6 +72,7 @@ static gboolean    thunar_chooser_dialog_context_menu        (ThunarChooserDialo
 static void        thunar_chooser_dialog_update_accept       (ThunarChooserDialog      *dialog);
 static void        thunar_chooser_dialog_update_header       (ThunarChooserDialog      *dialog);
 static void        thunar_chooser_dialog_action_remove       (ThunarChooserDialog      *dialog);
+static void        thunar_chooser_dialog_action_forget       (ThunarChooserDialog      *dialog);
 static void        thunar_chooser_dialog_browse_clicked      (GtkWidget                *button,
                                                               ThunarChooserDialog      *dialog);
 static gboolean    thunar_chooser_dialog_button_press_event  (GtkWidget                *tree_view,
@@ -581,6 +582,13 @@ thunar_chooser_dialog_context_menu (ThunarChooserDialog *dialog)
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show (item);
 
+  /* append the "Forget Association" item */
+  item = gtk_menu_item_new_with_mnemonic (_("_Forget Association"));
+  gtk_widget_set_sensitive (item, g_app_info_can_remove_supports_type (app_info));
+  g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_chooser_dialog_action_forget), dialog);
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show (item);
+
   /* run the menu (takes over the floating of menu) */
   thunar_gtk_menu_run (GTK_MENU (menu));
 
@@ -733,7 +741,7 @@ thunar_chooser_dialog_action_remove (ThunarChooserDialog *dialog)
       if (G_LIKELY (response == GTK_RESPONSE_YES))
         {
           /* try to delete the application from the model */
-          if (!thunar_chooser_model_remove (THUNAR_CHOOSER_MODEL (model), &iter, &error))
+          if (!thunar_chooser_model_remove (THUNAR_CHOOSER_MODEL (model), &iter, TRUE, &error))
             {
               /* display an error to the user */
               thunar_dialogs_show_error (dialog, error, _("Failed to remove \"%s\""), name);
@@ -753,6 +761,76 @@ thunar_chooser_dialog_action_remove (ThunarChooserDialog *dialog)
 
 
 
+static void
+thunar_chooser_dialog_action_forget (ThunarChooserDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel     *model;
+  GtkTreeIter       iter;
+  const gchar      *name;
+  GtkWidget        *message;
+  GAppInfo         *app_info;
+  GError           *error = NULL;
+  gint              response;
+
+  _thunar_return_if_fail (THUNAR_IS_CHOOSER_DIALOG (dialog));
+
+  /* determine the selected row */
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return;
+
+  /* determine the app info for the row */
+  gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &app_info, -1);
+  if (G_UNLIKELY (app_info == NULL))
+    return;
+
+  if (g_app_info_can_remove_supports_type (app_info))
+    {
+      /* determine the name of the app info */
+      name = g_app_info_get_name (app_info);
+
+      /* ask the user whether to forget the application launcher */
+      message = gtk_message_dialog_new (GTK_WINDOW (dialog),
+                                        GTK_DIALOG_DESTROY_WITH_PARENT
+                                        | GTK_DIALOG_MODAL,
+                                        GTK_MESSAGE_QUESTION,
+                                        GTK_BUTTONS_NONE,
+                                        _("Are you sure that you want to forget \"%s\"?"), name);
+      gtk_dialog_add_buttons (GTK_DIALOG (message),
+                              _("_Cancel"), GTK_RESPONSE_CANCEL,
+                              _("_Forget"), GTK_RESPONSE_YES,
+                              NULL);
+      gtk_dialog_set_default_response (GTK_DIALOG (message), GTK_RESPONSE_YES);
+      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), _("This will dissociate the application launcher for this file type, "
+                                                                                "but will not uninstall or remove the application launcher itself."));
+      response = gtk_dialog_run (GTK_DIALOG (message));
+      gtk_widget_destroy (message);
+
+      /* check if the user confirmed */
+      if (G_LIKELY (response == GTK_RESPONSE_YES))
+        {
+          /* try to delete the application from the model */
+          if (!thunar_chooser_model_remove (THUNAR_CHOOSER_MODEL (model), &iter, FALSE, &error))
+            {
+              /* display an error to the user */
+              thunar_dialogs_show_error (dialog, error, _("Failed to forget \"%s\""), name);
+              g_error_free (error);
+            }
+          else if (G_LIKELY (dialog->file != NULL))
+            {
+              /* emit "changed" for the file, so the context menu is updated */
+              thunar_file_changed (dialog->file);
+            }
+        }
+    }
+
+  /* cleanup */
+  g_object_unref (app_info);
+}
+
+
+
 static void
 thunar_chooser_dialog_browse_clicked (GtkWidget           *button,
                                       ThunarChooserDialog *dialog)
diff --git a/thunar/thunar-chooser-model.c b/thunar/thunar-chooser-model.c
index b54e1ea0c..388b0dce4 100644
--- a/thunar/thunar-chooser-model.c
+++ b/thunar/thunar-chooser-model.c
@@ -362,19 +362,20 @@ thunar_chooser_model_get_content_type (ThunarChooserModel *model)
 
 /**
  * thunar_chooser_model_remove:
- * @model : a #ThunarChooserModel.
- * @iter  : the #GtkTreeIter for the application to remove.
- * @error : return location for errors or %NULL.
+ * @model  : a #ThunarChooserModel.
+ * @iter   : the #GtkTreeIter for the application to remove.
+ * @delete : whether delete or just dissociate the application.
+ * @error  : return location for errors or %NULL.
  *
- * Tries to remove the application at the specified @iter from
- * the systems application database. Returns %TRUE on success,
- * otherwise %FALSE is returned.
+ * Tries to remove or dissociate the application at the specified
+ * @iter from the systems application database.
  *
  * Return value: %TRUE on success, %FALSE otherwise.
  **/
 gboolean
 thunar_chooser_model_remove (ThunarChooserModel *model,
                              GtkTreeIter        *iter,
+                             gboolean            delete,
                              GError            **error)
 {
   GAppInfo *app_info;
@@ -399,7 +400,7 @@ thunar_chooser_model_remove (ThunarChooserModel *model,
                                              error);
 
   /* try to delete the file */
-  if (succeed && g_app_info_delete (app_info))
+  if (delete && succeed && g_app_info_delete (app_info))
     {
       g_set_error (error, G_IO_ERROR,
                    G_IO_ERROR_FAILED,
diff --git a/thunar/thunar-chooser-model.h b/thunar/thunar-chooser-model.h
index 3ee77a5ff..0727e4838 100644
--- a/thunar/thunar-chooser-model.h
+++ b/thunar/thunar-chooser-model.h
@@ -61,6 +61,7 @@ ThunarChooserModel *thunar_chooser_model_new              (const gchar        *c
 const gchar        *thunar_chooser_model_get_content_type (ThunarChooserModel *model);
 gboolean            thunar_chooser_model_remove           (ThunarChooserModel *model,
                                                            GtkTreeIter        *iter,
+                                                           gboolean            delete,
                                                            GError            **error);
 
 G_END_DECLS;
-- 
GitLab