[Xfce4-commits] [panel-plugins/xfce4-whiskermenu-plugin] 294/473: Add dragging launchers to panel or desktop. Closes #36.

noreply at xfce.org noreply at xfce.org
Mon Feb 16 23:57:44 CET 2015


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 c9f3b6eed1351a2da72c4b825321196fc70485da
Author: Graeme Gott <graeme at gottcode.org>
Date:   Wed Dec 11 17:32:29 2013 -0500

    Add dragging launchers to panel or desktop. Closes #36.
---
 panel-plugin/launcher-view.cpp |  126 +++++++++++++++++++++++++++++++++++++++-
 panel-plugin/launcher-view.h   |   13 ++++-
 panel-plugin/launcher.h        |    5 ++
 panel-plugin/page.cpp          |    2 +-
 panel-plugin/slot.h            |   72 +++++++++++++++++++++++
 5 files changed, 213 insertions(+), 5 deletions(-)

diff --git a/panel-plugin/launcher-view.cpp b/panel-plugin/launcher-view.cpp
index 27360be..d33b17e 100644
--- a/panel-plugin/launcher-view.cpp
+++ b/panel-plugin/launcher-view.cpp
@@ -17,8 +17,10 @@
 
 #include "launcher-view.h"
 
+#include "launcher.h"
 #include "settings.h"
 #include "slot.h"
+#include "window.h"
 
 #include <algorithm>
 
@@ -38,9 +40,12 @@ static gboolean is_separator(GtkTreeModel* model, GtkTreeIter* iter, gpointer)
 
 //-----------------------------------------------------------------------------
 
-LauncherView::LauncherView() :
+LauncherView::LauncherView(Window* window) :
+	m_window(window),
 	m_model(NULL),
-	m_icon_size(0)
+	m_icon_size(0),
+	m_pressed_launcher(NULL),
+	m_launcher_dragged(false)
 {
 	// Create the view
 	m_view = GTK_TREE_VIEW(exo_tree_view_new());
@@ -63,6 +68,13 @@ LauncherView::LauncherView() :
 	gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
 
 	g_object_ref_sink(m_view);
+
+	// Handle drag-and-drop
+	g_signal_connect_slot(m_view, "button-press-event", &LauncherView::on_button_press_event, this);
+	g_signal_connect_slot(m_view, "button-release-event", &LauncherView::on_button_release_event, this);
+	g_signal_connect_slot(m_view, "drag-data-get", &LauncherView::on_drag_data_get, this);
+	g_signal_connect_slot(m_view, "drag-end", &LauncherView::on_drag_end, this);
+	set_reorderable(false);
 }
 
 //-----------------------------------------------------------------------------
@@ -133,7 +145,40 @@ void LauncherView::set_fixed_height_mode(bool fixed_height)
 
 void LauncherView::set_reorderable(bool reorderable)
 {
-	gtk_tree_view_set_reorderable(m_view, reorderable);
+	if (reorderable)
+	{
+		const GtkTargetEntry row_targets[] = {
+			{ g_strdup("GTK_TREE_MODEL_ROW"), GTK_TARGET_SAME_WIDGET, 0 },
+			{ g_strdup("text/uri-list"), GTK_TARGET_OTHER_APP, 1 }
+		};
+
+		gtk_tree_view_enable_model_drag_source(m_view,
+				GDK_BUTTON1_MASK,
+				row_targets, 2,
+				GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY));
+
+		gtk_tree_view_enable_model_drag_dest(m_view,
+				row_targets, 1,
+				GDK_ACTION_MOVE);
+
+		g_free(row_targets[0].target);
+		g_free(row_targets[1].target);
+	}
+	else
+	{
+		const GtkTargetEntry row_targets[] = {
+			{ g_strdup("text/uri-list"), GTK_TARGET_OTHER_APP, 1 }
+		};
+
+		gtk_tree_view_enable_model_drag_source(m_view,
+				GDK_BUTTON1_MASK,
+				row_targets, 1,
+				GDK_ACTION_COPY);
+
+		gtk_tree_view_unset_rows_drag_dest(m_view);
+
+		g_free(row_targets[0].target);
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -231,3 +276,78 @@ gboolean LauncherView::on_key_release_event(GtkWidget*, GdkEventKey* event)
 }
 
 //-----------------------------------------------------------------------------
+
+gboolean LauncherView::on_button_press_event(GtkWidget*, GdkEventButton* event)
+{
+	if (event->button != 1)
+	{
+		return false;
+	}
+
+	m_launcher_dragged = false;
+	m_pressed_launcher = NULL;
+
+	GtkTreeIter iter;
+	if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection(m_view), NULL, &iter))
+	{
+		return false;
+	}
+
+	gtk_tree_model_get(m_model, &iter, LauncherView::COLUMN_LAUNCHER, &m_pressed_launcher, -1);
+	if (m_pressed_launcher->get_type() != Launcher::Type)
+	{
+		m_pressed_launcher = NULL;
+	}
+
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+
+gboolean LauncherView::on_button_release_event(GtkWidget*, GdkEventButton* event)
+{
+	if (event->button != 1)
+	{
+		return false;
+	}
+
+	if (m_launcher_dragged)
+	{
+		m_window->hide();
+		m_launcher_dragged = false;
+	}
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+
+void LauncherView::on_drag_data_get(GtkWidget*, GdkDragContext*, GtkSelectionData* data, guint info, guint)
+{
+	if ((info != 1) || !m_pressed_launcher)
+	{
+		return;
+	}
+
+	gchar* uris[2] = { m_pressed_launcher->get_uri(), NULL };
+	if (uris[0] != NULL)
+	{
+		gtk_selection_data_set_uris(data, uris);
+		g_free(uris[0]);
+	}
+
+	m_launcher_dragged = true;
+}
+
+//-----------------------------------------------------------------------------
+
+void LauncherView::on_drag_end(GtkWidget*, GdkDragContext*)
+{
+	if (m_launcher_dragged)
+	{
+		m_window->hide();
+		m_launcher_dragged = false;
+	}
+	m_pressed_launcher = NULL;
+}
+
+//-----------------------------------------------------------------------------
diff --git a/panel-plugin/launcher-view.h b/panel-plugin/launcher-view.h
index 9bf1190..3ee6258 100644
--- a/panel-plugin/launcher-view.h
+++ b/panel-plugin/launcher-view.h
@@ -24,11 +24,13 @@ namespace WhiskerMenu
 {
 
 class IconSize;
+class Launcher;
+class Window;
 
 class LauncherView
 {
 public:
-	LauncherView();
+	LauncherView(Window* window);
 	~LauncherView();
 
 	GtkWidget* get_widget() const
@@ -70,12 +72,21 @@ private:
 	void create_column();
 	gboolean on_key_press_event(GtkWidget*, GdkEventKey* event);
 	gboolean on_key_release_event(GtkWidget*, GdkEventKey* event);
+	gboolean on_button_press_event(GtkWidget*, GdkEventButton* event);
+	gboolean on_button_release_event(GtkWidget*, GdkEventButton* event);
+	void on_drag_data_get(GtkWidget*, GdkDragContext*, GtkSelectionData* data, guint info, guint);
+	void on_drag_end(GtkWidget*, GdkDragContext*);
 
 private:
+	Window* m_window;
+
 	GtkTreeModel* m_model;
 	GtkTreeView* m_view;
 	GtkTreeViewColumn* m_column;
 	int m_icon_size;
+
+	Launcher* m_pressed_launcher;
+	bool m_launcher_dragged;
 };
 
 }
diff --git a/panel-plugin/launcher.h b/panel-plugin/launcher.h
index e18766e..2c99b31 100644
--- a/panel-plugin/launcher.h
+++ b/panel-plugin/launcher.h
@@ -57,6 +57,11 @@ public:
 		return garcon_menu_item_get_file(m_item);
 	}
 
+	gchar* get_uri() const
+	{
+		return garcon_menu_item_get_uri(m_item);
+	}
+
 	void run(GdkScreen* screen) const;
 
 	int search(const Query& query);
diff --git a/panel-plugin/page.cpp b/panel-plugin/page.cpp
index f02d08d..1a83c18 100644
--- a/panel-plugin/page.cpp
+++ b/panel-plugin/page.cpp
@@ -35,7 +35,7 @@ Page::Page(Window* window) :
 	m_selected_path(NULL)
 {
 	// Create view
-	m_view = new LauncherView;
+	m_view = new LauncherView(window);
 	g_signal_connect_slot(m_view->get_widget(), "button-press-event", &Page::view_button_press_event, this);
 	g_signal_connect_slot(m_view->get_widget(), "popup-menu", &Page::view_popup_menu_event, this);
 	g_signal_connect_slot(m_view->get_widget(), "row-activated", &Page::item_activated, this);
diff --git a/panel-plugin/slot.h b/panel-plugin/slot.h
index 16d2cae..ffb2160 100644
--- a/panel-plugin/slot.h
+++ b/panel-plugin/slot.h
@@ -167,6 +167,78 @@ gulong g_signal_connect_slot(gpointer instance, const gchar* detailed_signal, R(
 			after ? G_CONNECT_AFTER : GConnectFlags(0));
 }
 
+// Member function with 4 parameters
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4>
+gulong g_signal_connect_slot(gpointer instance, const gchar* detailed_signal, R(T::*member)(A1,A2,A3,A4), T* obj, bool after = false)
+{
+	class Slot
+	{
+		T* m_instance;
+		R (T::*m_member)(A1,A2,A3);
+
+	public:
+		Slot(T* instance, R (T::*member)(A1,A2,A3,A4)) :
+			m_instance(instance),
+			m_member(member)
+		{
+		}
+
+		static R invoke(A1 a1, A2 a2, A3 a3, A4 a4, Slot* slot)
+		{
+			return (slot->m_instance->*slot->m_member)(a1, a2, a3, a4);
+		}
+
+		static void destroy(Slot* slot)
+		{
+			delete slot;
+		}
+	};
+	R (*invoke_slot)(A1,A2,A3,A4,Slot*) = &Slot::invoke;
+	void (*destroy_slot)(Slot*) = &Slot::destroy;
+
+	return g_signal_connect_data(instance, detailed_signal,
+			reinterpret_cast<GCallback>(invoke_slot),
+			new Slot(obj, member),
+			reinterpret_cast<GClosureNotify>(destroy_slot),
+			after ? G_CONNECT_AFTER : GConnectFlags(0));
+}
+
+// Member function with 5 parameters
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
+gulong g_signal_connect_slot(gpointer instance, const gchar* detailed_signal, R(T::*member)(A1,A2,A3,A4,A5), T* obj, bool after = false)
+{
+	class Slot
+	{
+		T* m_instance;
+		R (T::*m_member)(A1,A2,A3,A4,A5);
+
+	public:
+		Slot(T* instance, R (T::*member)(A1,A2,A3,A4,A5)) :
+			m_instance(instance),
+			m_member(member)
+		{
+		}
+
+		static R invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, Slot* slot)
+		{
+			return (slot->m_instance->*slot->m_member)(a1, a2, a3, a4, a5);
+		}
+
+		static void destroy(Slot* slot)
+		{
+			delete slot;
+		}
+	};
+	R (*invoke_slot)(A1,A2,A3,A4,A5,Slot*) = &Slot::invoke;
+	void (*destroy_slot)(Slot*) = &Slot::destroy;
+
+	return g_signal_connect_data(instance, detailed_signal,
+			reinterpret_cast<GCallback>(invoke_slot),
+			new Slot(obj, member),
+			reinterpret_cast<GClosureNotify>(destroy_slot),
+			after ? G_CONNECT_AFTER : GConnectFlags(0));
+}
+
 }
 
 #endif // WHISKERMENU_SLOT_H

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list