Commit 25ef9f3c authored by Alexander Schwinn's avatar Alexander Schwinn
Browse files

Introduced widget thunar-menu in order to unify the way menus are build

in thunar, and used it for the context menu (Bug #16654)
parent 4e06221b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ thunar/thunar-location-bar.c
thunar/thunar-location-button.c
thunar/thunar-location-buttons.c
thunar/thunar-location-entry.c
thunar/thunar-menu.c
thunar/thunar-notify.c
thunar/thunar-navigator.c
thunar/thunar-pango-extensions.c
+2 −0
Original line number Diff line number Diff line
@@ -142,6 +142,8 @@ thunar_SOURCES = \
	thunar-location-buttons.h					\
	thunar-location-entry.c						\
	thunar-location-entry.h						\
	thunar-menu.c						\
	thunar-menu.h						\
	thunar-menu-util.c						\
	thunar-menu-util.h						\
	thunar-notify.c							\

thunar/thunar-menu.c

0 → 100644
+347 −0
Original line number Diff line number Diff line
/*-
 * Copyright (c) 2020 Alexander Schwinn <alexxcons@xfce.org>
 *
 * 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
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <thunar/thunar-menu.h>

#include <thunar/thunar-gtk-extensions.h>
#include <thunar/thunar-launcher.h>
#include <thunar/thunar-private.h>
#include <thunar/thunar-window.h>

/* property identifiers */
enum
{
  PROP_0,
  PROP_MENU_TYPE,
  PROP_LAUNCHER,
  PROP_FORCE_SECTION_OPEN,
  PROP_TAB_SUPPORT_DISABLED,
  PROP_CHANGE_DIRECTORY_SUPPORT_DISABLED,
};

static void thunar_menu_finalize      (GObject                *object);
static void thunar_menu_get_property  (GObject                *object,
                                       guint                   prop_id,
                                       GValue                 *value,
                                       GParamSpec             *pspec);
static void thunar_menu_set_property  (GObject                *object,
                                       guint                   prop_uid,
                                       const GValue           *value,
                                       GParamSpec             *pspec);

struct _ThunarMenuClass
{
  GtkMenuClass __parent__;
};

struct _ThunarMenu
{
  GtkMenu __parent__;
  ThunarLauncher  *launcher;

  /* true, if the 'open' section should be forced */
  gboolean         force_section_open;

  /* true, if 'open as new tab' should not be shown */
  gboolean         tab_support_disabled;

  /* true, if 'open' for folders, which would result in changing the directory, should not be shown */
  gboolean         change_directory_support_disabled;

  /* detailed type of the thunar menu */
  ThunarMenuType   type;
};



static GQuark thunar_menu_handler_quark;

G_DEFINE_TYPE (ThunarMenu, thunar_menu, GTK_TYPE_MENU)



static void
thunar_menu_class_init (ThunarMenuClass *klass)
{
  GObjectClass *gobject_class;

  /* determine the "thunar-menu-handler" quark */
  thunar_menu_handler_quark = g_quark_from_static_string ("thunar-menu-handler");

  gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = thunar_menu_finalize;
  gobject_class->get_property = thunar_menu_get_property;
  gobject_class->set_property = thunar_menu_set_property;

  g_object_class_install_property (gobject_class,
                                   PROP_MENU_TYPE,
                                   g_param_spec_int ("menu-type",
                                                     "menu-type",
                                                     "menu-type",
                                                     0, 1, 0, // min, max, default
                                                     G_PARAM_WRITABLE
                                                     | G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (gobject_class,
                                   PROP_LAUNCHER,
                                   g_param_spec_object ("launcher",
                                                        "launcher",
                                                        "launcher",
                                                        THUNAR_TYPE_LAUNCHER,
                                                          G_PARAM_WRITABLE
                                                        | G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (gobject_class,
                                   PROP_FORCE_SECTION_OPEN,
                                   g_param_spec_boolean ("force-section-open",
                                                         "force-section-open",
                                                         "force-section-open",
                                                         FALSE,
                                                           G_PARAM_WRITABLE
                                                         | G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (gobject_class,
                                   PROP_TAB_SUPPORT_DISABLED,
                                   g_param_spec_boolean ("tab-support-disabled",
                                                         "tab-support-disabled",
                                                         "tab-support-disabled",
                                                         FALSE,
                                                           G_PARAM_WRITABLE
                                                         | G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (gobject_class,
                                   PROP_CHANGE_DIRECTORY_SUPPORT_DISABLED,
                                   g_param_spec_boolean ("change_directory-support-disabled",
                                                         "change_directory-support-disabled",
                                                         "change_directory-support-disabled",
                                                         FALSE,
                                                           G_PARAM_WRITABLE
                                                         | G_PARAM_CONSTRUCT_ONLY));
}



static void
thunar_menu_init (ThunarMenu *menu)
{
  menu->force_section_open = FALSE;
  menu->type = FALSE;
  menu->tab_support_disabled = FALSE;
  menu->change_directory_support_disabled = FALSE;
}



static void
thunar_menu_finalize (GObject *object)
{
  ThunarMenu *menu = THUNAR_MENU (object);

  g_object_unref (menu->launcher);

  (*G_OBJECT_CLASS (thunar_menu_parent_class)->finalize) (object);
}



static void
thunar_menu_get_property (GObject    *object,
                          guint       prop_id,
                          GValue     *value,
                          GParamSpec *pspec)
{
  switch (prop_id)
    {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}



static void
thunar_menu_set_property (GObject      *object,
                          guint         prop_id,
                          const GValue *value,
                          GParamSpec   *pspec)
{
  ThunarMenu *menu = THUNAR_MENU (object);

  switch (prop_id)
    {
    case PROP_MENU_TYPE:
      menu->type = g_value_get_int (value);
      break;

    case PROP_LAUNCHER:
      menu->launcher = g_value_dup_object (value);
      g_object_ref (G_OBJECT (menu->launcher));
     break;

    case PROP_FORCE_SECTION_OPEN:
      menu->force_section_open = g_value_get_boolean (value);
      break;

    case PROP_TAB_SUPPORT_DISABLED:
      menu->tab_support_disabled = g_value_get_boolean (value);
      break;

    case PROP_CHANGE_DIRECTORY_SUPPORT_DISABLED:
      menu->change_directory_support_disabled = g_value_get_boolean (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}



/**
 * thunar_menu_add_sections:
 * @menu : a #ThunarMenu instance
 * @menu_sections : bit enumeration of #ThunarMenuSections which should be added to the #ThunarMenu
 *
 * Method to add different sections of #GtkMenuItems to the #ThunarMenu,
 * according to the selected #ThunarMenuSections
 *
 * Return value: TRUE if any #GtkMenuItem was added
 **/
gboolean
thunar_menu_add_sections (ThunarMenu         *menu,
                          ThunarMenuSections  menu_sections)
{
  GtkWidget *window;
  gboolean   item_added;
  gboolean   is_window_menu = menu->type == THUNAR_MENU_TYPE_WINDOW;

  _thunar_return_val_if_fail (THUNAR_IS_MENU (menu), FALSE);

  if (menu_sections & THUNAR_MENU_SECTION_OPEN)
    {
      if (thunar_launcher_append_open_section (menu->launcher, GTK_MENU_SHELL (menu), !menu->tab_support_disabled, !menu->change_directory_support_disabled, menu->force_section_open))
         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
    }

  if (menu_sections & THUNAR_MENU_SECTION_SENDTO)
    {
      item_added = thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_SENDTO_MENU, FALSE) != NULL;
      if (item_added)
         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
    }
  if (menu_sections & THUNAR_MENU_SECTION_CREATE_NEW_FILES)
    {
      item_added = FALSE;
      item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_CREATE_FOLDER, is_window_menu) != NULL);
      // TODO: Create Document
      if (item_added)
         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
    }
  item_added = FALSE;
  if (menu_sections & THUNAR_MENU_SECTION_CUT)
    item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_CUT, is_window_menu) != NULL);
  if (menu_sections & THUNAR_MENU_SECTION_COPY_PASTE)
    {
      item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_COPY, is_window_menu) != NULL);
      item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_PASTE, is_window_menu) != NULL);
    }
  if (item_added)
     xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));

  if (menu_sections & THUNAR_MENU_SECTION_TRASH_DELETE)
    {
      item_added = FALSE;
      item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_MOVE_TO_TRASH, is_window_menu) != NULL);
      item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_DELETE, is_window_menu) != NULL);
      if (item_added)
         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
    }
  if (menu_sections & THUNAR_MENU_SECTION_EMPTY_TRASH)
    {
      if (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_EMPTY_TRASH, FALSE) != NULL )
         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
    }
  if (menu_sections & THUNAR_MENU_SECTION_RESTORE)
    {
      if (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_RESTORE, FALSE) != NULL)
         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
    }

  item_added = FALSE;
  if (menu_sections & THUNAR_MENU_SECTION_DUPLICATE)
    item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_DUPLICATE, is_window_menu) != NULL);
  if (menu_sections & THUNAR_MENU_SECTION_MAKELINK)
    item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_MAKE_LINK, is_window_menu) != NULL);
  if (menu_sections & THUNAR_MENU_SECTION_RENAME)
    item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_RENAME, is_window_menu) != NULL);
  if (item_added)
     xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));

  if (menu_sections & THUNAR_MENU_SECTION_CUSTOM_ACTIONS)
    {
       // TODO
    }

  if (menu_sections & THUNAR_MENU_SECTION_ZOOM)
    {
       // TODO
    }

  if (menu_sections & THUNAR_MENU_SECTION_PROPERTIES)
      thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_PROPERTIES, FALSE);

  return TRUE;
}



/**
 * thunar_menu_get_launcher:
 * @menu : a #ThunarMenu instance
 *
 * Return value: (transfer none): The launcher of this #ThunarMenu instance
 **/
GtkWidget*
thunar_menu_get_launcher (ThunarMenu *menu)
{
  _thunar_return_val_if_fail (THUNAR_IS_MENU (menu), NULL);
  return GTK_WIDGET (menu->launcher);
}



/**
 * thunar_menu_hide_accel_labels:
 * @menu : a #ThunarMenu instance
 *
 * Will hide the accel_labels of all menu items of this menu
 **/
void
thunar_menu_hide_accel_labels (ThunarMenu *menu)
{
  _thunar_return_if_fail (THUNAR_IS_MENU (menu));

  for (GList* lp = gtk_container_get_children (GTK_CONTAINER (menu)); lp != NULL; lp = lp->next)
    xfce_gtk_menu_item_set_accel_label (lp->data, NULL);
}

thunar/thunar-menu.h

0 → 100644
+74 −0
Original line number Diff line number Diff line
/*-
 * Copyright (c) 2020 Alexander Schwinn <alexxcons@xfce.org>
 *
 * 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
 */
#ifndef __THUNAR_MENU_H__
#define __THUNAR_MENU_H__

#include <gtk/gtk.h>

#include <thunar/thunar-file.h>

G_BEGIN_DECLS;

typedef struct _ThunarMenuClass ThunarMenuClass;
typedef struct _ThunarMenu      ThunarMenu;

#define THUNAR_TYPE_MENU             (thunar_menu_get_type ())
#define THUNAR_MENU(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_MENU, ThunarMenu))
#define THUNAR_MENU_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  THUNAR_TYPE_MENU, ThunarMenuClass))
#define THUNAR_IS_MENU(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_MENU))
#define THUNAR_IS_MENU_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  THUNAR_TYPE_MENU))
#define THUNAR_MENU_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  THUNAR_TYPE_MENU, ThunarMenu))

/* For window menu, some items are shown insensitive, instead of hidden */
typedef enum
{
  THUNAR_MENU_TYPE_WINDOW,
  THUNAR_MENU_TYPE_CONTEXT,
} ThunarMenuType;

/* Bundles of #GtkMenuItems, which can be created by this widget */
typedef enum
{
  THUNAR_MENU_SECTION_OPEN             = 1 << 0,
  THUNAR_MENU_SECTION_SENDTO           = 1 << 1,
  THUNAR_MENU_SECTION_CREATE_NEW_FILES = 1 << 2,
  THUNAR_MENU_SECTION_CUT              = 1 << 3,
  THUNAR_MENU_SECTION_COPY_PASTE       = 1 << 4,
  THUNAR_MENU_SECTION_TRASH_DELETE     = 1 << 5,
  THUNAR_MENU_SECTION_EMPTY_TRASH      = 1 << 6,
  THUNAR_MENU_SECTION_RESTORE          = 1 << 7,
  THUNAR_MENU_SECTION_DUPLICATE        = 1 << 8,
  THUNAR_MENU_SECTION_MAKELINK         = 1 << 9,
  THUNAR_MENU_SECTION_RENAME           = 1 << 10,
  THUNAR_MENU_SECTION_CUSTOM_ACTIONS   = 1 << 11,
  THUNAR_MENU_SECTION_ZOOM             = 1 << 12,
  THUNAR_MENU_SECTION_PROPERTIES       = 1 << 13,

} ThunarMenuSections;


GType      thunar_menu_get_type          (void) G_GNUC_CONST;

gboolean   thunar_menu_add_sections      (ThunarMenu         *menu,
                                          ThunarMenuSections  menu_sections);
GtkWidget* thunar_menu_get_launcher      (ThunarMenu         *menu);
void       thunar_menu_hide_accel_labels (ThunarMenu         *menu);

G_END_DECLS;

#endif /* !__THUNAR_CONTEXT_MENU_H__ */
+37 −8
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <gdk/gdkkeysyms.h>

#include <thunar/thunar-application.h>
#include <thunar/thunar-menu.h>
#include <thunar/thunar-create-dialog.h>
#include <thunar/thunar-dialogs.h>
#include <thunar/thunar-dnd.h>
@@ -3589,7 +3590,8 @@ thunar_standard_view_size_allocate (ThunarStandardView *standard_view,
void
thunar_standard_view_context_menu (ThunarStandardView *standard_view)
{
  GtkWidget *menu;
  GtkWidget  *window;
  ThunarMenu *context_menu;
  GList      *selected_items;

  _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
@@ -3597,20 +3599,47 @@ thunar_standard_view_context_menu (ThunarStandardView *standard_view)
  /* grab an additional reference on the view */
  g_object_ref (G_OBJECT (standard_view));

  /* run the menu (figuring out whether to use the file or the folder context menu) */
  selected_items = (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_selected_items) (standard_view);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
  menu = gtk_ui_manager_get_widget (standard_view->ui_manager, (selected_items != NULL) ? "/file-context-menu" : "/folder-context-menu");
G_GNUC_END_IGNORE_DEPRECATIONS

  window = gtk_widget_get_toplevel (GTK_WIDGET (standard_view));

  context_menu = g_object_new (THUNAR_TYPE_MENU, "menu-type", THUNAR_MENU_TYPE_CONTEXT,
                                                 "launcher", thunar_window_get_launcher (THUNAR_WINDOW (window)), NULL);
  if (selected_items != NULL)
    {
      thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_OPEN
                                            | THUNAR_MENU_SECTION_SENDTO
                                            | THUNAR_MENU_SECTION_CUT
                                            | THUNAR_MENU_SECTION_COPY_PASTE
                                            | THUNAR_MENU_SECTION_TRASH_DELETE
                                            | THUNAR_MENU_SECTION_EMPTY_TRASH
                                            | THUNAR_MENU_SECTION_RESTORE
                                            | THUNAR_MENU_SECTION_RENAME
                                            | THUNAR_MENU_SECTION_CUSTOM_ACTIONS
                                            | THUNAR_MENU_SECTION_PROPERTIES);
    }
  else /* right click on some empty space */
    {
      thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_CREATE_NEW_FILES
                                            | THUNAR_MENU_SECTION_COPY_PASTE
                                            | THUNAR_MENU_SECTION_EMPTY_TRASH
                                            | THUNAR_MENU_SECTION_CUSTOM_ACTIONS);
      xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (context_menu));
      thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_ZOOM
                                            | THUNAR_MENU_SECTION_PROPERTIES);
    }
  thunar_menu_hide_accel_labels (context_menu);
  gtk_widget_show_all (GTK_WIDGET (context_menu));

  /* if there is a drag_timer_event (long press), we use it */
  if (standard_view->priv->drag_timer_event != NULL)
    {
      thunar_gtk_menu_run_at_event (GTK_MENU (menu), standard_view->priv->drag_timer_event);
      thunar_gtk_menu_run_at_event (GTK_MENU (context_menu), standard_view->priv->drag_timer_event);
      gdk_event_free (standard_view->priv->drag_timer_event);
      standard_view->priv->drag_timer_event = NULL;
    }
  else
    thunar_gtk_menu_run (GTK_MENU (menu));
    thunar_gtk_menu_run (GTK_MENU (context_menu));

  g_list_free_full (selected_items, (GDestroyNotify) gtk_tree_path_free);