[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