[Xfce4-commits] [panel-plugins/xfce4-whiskermenu-plugin] 02/02: Add support for desktop actions. (bug #11787)
noreply at xfce.org
noreply at xfce.org
Tue Oct 25 13:54:49 CEST 2016
This is an automated email from the git hooks/post-receive script.
gottcode pushed a commit to branch master
in repository panel-plugins/xfce4-whiskermenu-plugin.
commit cb95442b745b8f8b9d2928a49601ed1d99b5f19f
Author: Graeme Gott <graeme at gottcode.org>
Date: Sun Oct 23 19:41:51 2016 -0400
Add support for desktop actions. (bug #11787)
---
panel-plugin/launcher.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++++++
panel-plugin/launcher.h | 60 ++++++++++++++++++++++++++++++-
panel-plugin/page.cpp | 42 ++++++++++++++++++++++
panel-plugin/page.h | 2 ++
panel-plugin/slot.h | 41 ++++++++++++++++++++-
5 files changed, 234 insertions(+), 2 deletions(-)
diff --git a/panel-plugin/launcher.cpp b/panel-plugin/launcher.cpp
index fcc2d50..7c3396e 100644
--- a/panel-plugin/launcher.cpp
+++ b/panel-plugin/launcher.cpp
@@ -185,12 +185,30 @@ Launcher::Launcher(GarconMenuItem* item) :
{
m_search_command = normalize(command);
}
+
+ // Fetch desktop actions
+#ifdef GARCON_TYPE_MENU_ITEM_ACTION
+ GList* actions = garcon_menu_item_get_actions(m_item);
+ for (GList* i = actions; i != NULL; i = i->next)
+ {
+ GarconMenuItemAction* action = garcon_menu_item_get_action(m_item, reinterpret_cast<gchar*>(i->data));
+ if (action)
+ {
+ m_actions.push_back(new DesktopAction(action));
+ }
+ }
+ g_list_free(actions);
+#endif
}
//-----------------------------------------------------------------------------
Launcher::~Launcher()
{
+ for (std::vector<DesktopAction*>::size_type i = 0, end = m_actions.size(); i < end; ++i)
+ {
+ delete m_actions[i];
+ }
}
//-----------------------------------------------------------------------------
@@ -274,6 +292,79 @@ void Launcher::run(GdkScreen* screen) const
//-----------------------------------------------------------------------------
+void Launcher::run(GdkScreen* screen, DesktopAction* action) const
+{
+ const gchar* string = action->get_command();
+ if (exo_str_is_empty(string))
+ {
+ return;
+ }
+ std::string command(string);
+
+ // Expand the field codes
+ size_t length = command.length() - 1;
+ for (size_t i = 0; i < length; ++i)
+ {
+ if (G_UNLIKELY(command[i] == '%'))
+ {
+ switch (command[i + 1])
+ {
+ case 'i':
+ replace_with_quoted_string(command, i, "--icon ", action->get_icon());
+ break;
+
+ case 'c':
+ replace_with_quoted_string(command, i, action->get_name());
+ break;
+
+ case 'k':
+ replace_and_free_with_quoted_string(command, i, garcon_menu_item_get_uri(m_item));
+
+ case '%':
+ command.erase(i, 1);
+ break;
+
+ case 'f':
+ // unsupported, pass in a single file dropped on launcher
+ case 'F':
+ // unsupported, pass in a list of files dropped on launcher
+ case 'u':
+ // unsupported, pass in a single URL dropped on launcher
+ case 'U':
+ // unsupported, pass in a list of URLs dropped on launcher
+ default:
+ command.erase(i, 2);
+ break;
+ }
+ length = command.length() - 1;
+ }
+ }
+
+ // Parse and spawn command
+ gchar** argv;
+ gboolean result = false;
+ GError* error = NULL;
+ if (g_shell_parse_argv(command.c_str(), NULL, &argv, &error))
+ {
+ result = xfce_spawn_on_screen(screen,
+ garcon_menu_item_get_path(m_item),
+ argv, NULL, G_SPAWN_SEARCH_PATH,
+ garcon_menu_item_supports_startup_notification(m_item),
+ gtk_get_current_event_time(),
+ action->get_icon(),
+ &error);
+ g_strfreev(argv);
+ }
+
+ if (G_UNLIKELY(!result))
+ {
+ xfce_dialog_show_error(NULL, error, _("Failed to execute command \"%s\"."), string);
+ g_error_free(error);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
guint Launcher::search(const Query& query)
{
// Prioritize matches in favorites and recent, then favories, and then recent
diff --git a/panel-plugin/launcher.h b/panel-plugin/launcher.h
index d13733d..f21d1c9 100644
--- a/panel-plugin/launcher.h
+++ b/panel-plugin/launcher.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2015 Graeme Gott <graeme at gottcode.org>
+ * Copyright (C) 2013, 2015, 2016 Graeme Gott <graeme at gottcode.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,12 +21,62 @@
#include "element.h"
#include <string>
+#include <vector>
#include <garcon/garcon.h>
namespace WhiskerMenu
{
+struct DesktopAction
+{
+#ifdef GARCON_TYPE_MENU_ITEM_ACTION
+
+public:
+ DesktopAction(GarconMenuItemAction* action) :
+ m_action(action)
+ {
+ }
+
+ const gchar* get_name() const
+ {
+ return garcon_menu_item_action_get_name(m_action);
+ }
+
+ const gchar* get_icon() const
+ {
+ return garcon_menu_item_action_get_icon_name(m_action);
+ }
+
+ const gchar* get_command() const
+ {
+ return garcon_menu_item_action_get_command(m_action);
+ }
+
+private:
+ GarconMenuItemAction* m_action;
+
+#else
+
+public:
+ const gchar* get_name() const
+ {
+ return NULL;
+ }
+
+ const gchar* get_icon() const
+ {
+ return NULL;
+ }
+
+ const gchar* get_command() const
+ {
+ return NULL;
+ }
+
+#endif
+};
+
class Launcher : public Element
{
public:
@@ -42,6 +92,11 @@ public:
return Type;
}
+ std::vector<DesktopAction*> get_actions() const
+ {
+ return m_actions;
+ }
+
const gchar* get_display_name() const
{
return m_display_name;
@@ -64,6 +119,8 @@ public:
void run(GdkScreen* screen) const;
+ void run(GdkScreen* screen, DesktopAction* action) const;
+
guint search(const Query& query);
enum SearchFlag
@@ -81,6 +138,7 @@ private:
std::string m_search_comment;
std::string m_search_command;
guint m_search_flags;
+ std::vector<DesktopAction*> m_actions;
};
}
diff --git a/panel-plugin/page.cpp b/panel-plugin/page.cpp
index 97b8573..063f934 100644
--- a/panel-plugin/page.cpp
+++ b/panel-plugin/page.cpp
@@ -139,6 +139,29 @@ void Page::item_activated(GtkTreeView* view, GtkTreePath* path, GtkTreeViewColum
//-----------------------------------------------------------------------------
+void Page::item_action_activated(GtkMenuItem* menuitem, DesktopAction* action)
+{
+ Launcher* launcher = get_selected_launcher();
+ if (!launcher)
+ {
+ return;
+ }
+
+ // Add to recent
+ if (remember_launcher(launcher))
+ {
+ m_window->get_recent()->add(launcher);
+ }
+
+ // Hide window
+ m_window->hide();
+
+ // Execute app
+ launcher->run(gtk_widget_get_screen(GTK_WIDGET(menuitem)), action);
+}
+
+//-----------------------------------------------------------------------------
+
gboolean Page::view_button_press_event(GtkWidget* view, GdkEvent* event)
{
GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
@@ -194,6 +217,25 @@ void Page::create_context_menu(GtkTreeIter* iter, GdkEvent* event)
menuitem = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+ const std::vector<DesktopAction*> actions = launcher->get_actions();
+ if (!actions.empty())
+ {
+ for (std::vector<DesktopAction*>::size_type i = 0, end = actions.size(); i < end; ++i)
+ {
+ DesktopAction* action = actions[i];
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ menuitem = gtk_image_menu_item_new_with_label(action->get_name());
+ GtkWidget* image = gtk_image_new_from_icon_name(action->get_icon(), GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
+G_GNUC_END_IGNORE_DEPRECATIONS
+ g_signal_connect_slot(menuitem, "activate", &Page::item_action_activated, this, action);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+ }
+
+ menuitem = gtk_separator_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+ }
+
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (!m_window->get_favorites()->contains(launcher))
{
diff --git a/panel-plugin/page.h b/panel-plugin/page.h
index c11f75e..25a0851 100644
--- a/panel-plugin/page.h
+++ b/panel-plugin/page.h
@@ -23,6 +23,7 @@
namespace WhiskerMenu
{
+class DesktopAction;
class Launcher;
class LauncherView;
class Window;
@@ -54,6 +55,7 @@ protected:
private:
virtual bool remember_launcher(Launcher* launcher);
void item_activated(GtkTreeView* view, GtkTreePath* path, GtkTreeViewColumn*);
+ void item_action_activated(GtkMenuItem* menuitem, DesktopAction* action);
gboolean view_button_press_event(GtkWidget* view, GdkEvent* event);
gboolean view_popup_menu_event(GtkWidget* view);
void on_unmap();
diff --git a/panel-plugin/slot.h b/panel-plugin/slot.h
index f0202b2..a30a177 100644
--- a/panel-plugin/slot.h
+++ b/panel-plugin/slot.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Graeme Gott <graeme at gottcode.org>
+ * Copyright (C) 2013, 2016 Graeme Gott <graeme at gottcode.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -96,6 +96,45 @@ gulong g_signal_connect_slot(gpointer instance, const gchar* detailed_signal, R(
after ? G_CONNECT_AFTER : GConnectFlags(0));
}
+// Member function with 1 parameter and 1 bound parameter
+template<typename T, typename R, typename A1, typename A2>
+gulong g_signal_connect_slot(gpointer instance, const gchar* detailed_signal, R(T::*member)(A1,A2), T* obj, A2 bound1, bool after = false)
+{
+ class Slot
+ {
+ T* m_instance;
+ R (T::*m_member)(A1,A2);
+ A2 m_bound1;
+
+ public:
+ Slot(T* instance, R (T::*member)(A1,A2), A2 bound1) :
+ m_instance(instance),
+ m_member(member),
+ m_bound1(bound1)
+ {
+ }
+
+ static R invoke(A1 a1, gpointer user_data)
+ {
+ Slot* slot = reinterpret_cast<Slot*>(user_data);
+ return (slot->m_instance->*slot->m_member)(a1, slot->m_bound1);
+ }
+
+ static void destroy(gpointer data, GClosure*)
+ {
+ delete reinterpret_cast<Slot*>(data);
+ }
+ };
+ R (*invoke_slot)(A1,gpointer) = &Slot::invoke;
+ void (*destroy_slot)(gpointer, GClosure*) = &Slot::destroy;
+
+ return g_signal_connect_data(instance, detailed_signal,
+ reinterpret_cast<GCallback>(invoke_slot),
+ new Slot(obj, member, bound1),
+ destroy_slot,
+ after ? G_CONNECT_AFTER : GConnectFlags(0));
+}
+
// Member function with 2 parameters
template<typename T, typename R, typename A1, typename A2>
gulong g_signal_connect_slot(gpointer instance, const gchar* detailed_signal, R(T::*member)(A1,A2), T* obj, bool after = false)
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list