[gtkmm] drag and drop signals comming twice



Hi there,

I've been trying to implement DnD functionality in my application but my drag source and destination widgets emit the drag_data_get and drag_data_received signals twice and so my on_drag_data_get and on_drag_data_received methods are called twice.

I did search the web, forums and mailing lists and did my best to fix this strange behaviour but I neither found any solutions on the net, neither could fix it myself. I found two unanswered posts on the gtk and gtk-app-devel mailing list archives as provided by http://marc.theaimsgroup.com. Here are the links:
http://marc.theaimsgroup.com/?l=gtk-app-devel&m=107411384929412&w=2
http://marc.theaimsgroup.com/?l=gtk&m=103004942000379&w=2
I also posted a question in gnomesupport.org's development forum but it has been several day now and I still have no reply. Here is a link to that post:
http://gnomesupport.org/forums/viewtopic.php?t=6804

So if anyone could help me or at least give me some clue I'll deeply appreciate it. I'll be happy to read any comments or suggestions as I'm a gtk(mm) newbie and I'm not sure that I'm doing things the right way.

Here are some details about the implementation:

First of all here is a list of the used libraries and their versions all of which I compiled and installed from source: atk-1.7.0, glib-2.4.2, gtk+-2.4.2, libglade-2.4.0, libxml2-2.6.9 and the corresponding C++ libs: glibmm-2.4.2, gtkmm-2.4.2, libglademm-2.4.1, libsigc++-2.0.3, libxml++-2.6.1

Some informal description of what I'm trying to do:
I have a main window which has, among other things, a "project workspace" which is derived from Gtk::Layout. The user can add a file to the "project workspace" via the main window's menu or by right-clicking in the "project workspace". The latter invokes a popup menu. The files which can be added to the workspace are raster images which may be one or more and they show up in the workspace as thumbnails. The point is that if the user has to work with a very large image it will be more convinient and less resource consuming if the app can work with many different portions of the large image. That is the original large image is split into several smaller image files which are processed independently. The user could either partition a large image with an external program (say the GIMP) or he could have many images as a result of scanning a large sketch. What I want to do is to allow the user arrange the thumbnails (representing the image files) in the "project workspace" so that 
 they form the original large image. That is what I'm trying to implement DnD for. For representing each input image file in the workspace I've created an ActiveThumbnail class which is derived from Gtk::EventBox and contains a thumbnail of the image. So the user should be able to arrange the ActiveThumbnails in the workspace while clicking an ActiveThumbnail should open the corresponding file for processing and right-clicking it should bring up a popup menu with some options (like remove from project etc.)

A more detailed (and human readable :-) ) description of what I've done so far follows. I've included only the details which I think could be related to the DnD problem I ran into.
Description of the ActiveThumbnail class:
The ActiveThumbnail class is defined like this:
class ActiveThumbnail : public Gtk::EventBox
{
   Gtk::Menu popup_menu;
   // skip skip skip
   bool on_button_press_event (GdkEventButton* event);
   void on_drag_data_get (const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time);
   // skip skip skip
};
In its constructor I have the following:
ActiveThumbnail::ActiveThumbnail()
{
   // skip skip skip
   signal_button_press_event().connect(sigc::mem_fun(*this, &ActiveThumbnail::on_button_press_event));

   std::list<Gtk::TargetEntry> lst_targets;
   lst_targets.push_back (Gtk::TargetEntry ("vnd.my_app.active_thumb"));
   drag_source_set (lst_targets, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE);
   signal_drag_data_get().connect (sigc::mem_fun (*this, &ActiveThumbnail::on_drag_data_get));
   // skip skip skip
}
The on_button_press_event handler is like this:
bool ActiveThumbnail::on_button_press_event (GdkEventButton* event)
{
  if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
    popup_menu.popup(event->button, event->time);
    return true;
  }
  else
    return false;
}
And the on_drag_data_get signal handler is:
void ActiveThumbnail::on_drag_data_get (const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time)
{
  // The following union is used to pass a pointer to the drag source
  // widget to the destionation widget
  union {
    guchar guch [5];
    ActiveThumbnail* at_ptr;
  } u_drag_src;
  u_drag_src.at_ptr = this;
  u_drag_src.guch [4] = '\0';

  selection_data.set (selection_data.get_target(), 8 /* 8 bits format*/, u_drag_src.guch, 5 /* Length in bytes*/);
}
The ProjectWorkspace class is defined like this:
class ProjectWorkspace : public Gtk::Layout
{
   Gtk::Menu popup_menu;
   bool on_button_press_event(GdkEventButton*);
   // skip skip skip
   void on_drag_data_received (const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time);
   // skip skip skip
};
The ProjectWorkspace's constructor looks like this:
Project_Workspace::Project_Workspace()
{
   // skip skip skip
   signal_button_press_event().connect(sigc::mem_fun(*this, &ProjectWorkspace::on_button_press_event));

   std::list<Gtk::TargetEntry> lst_targets;
   lst_targets.push_back (Gtk::TargetEntry ("vnd.my_app.active_thumb"));
   drag_dest_set (lst_targets, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE);
   signal_drag_data_received().connect (sigc::mem_fun (*this, &ProjectWorkspace::on_drag_data_received));
}
The mouse button signal handler is:
bool ProjectWorkspace::on_button_press_event(GdkEventButton* event)
{
  if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
    popup_menu.popup(event->button, event->time);
    return true;
  }
  else
    return false;
}
And finally the on_drag_data_received handler is:
void ProjectWorkspace::on_drag_data_received (const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time)
{
  ActiveThumbnail* p_drag_src;
  const guchar* p_gch = selection_data.get_data();
  union {
    guchar guch [5];
    ActiveThumbnail* at_ptr;
  } u_drag_src;

  if ((selection_data.get_length() >=0) && (selection_data.get_format() == 8)) {
    for (char i = 0; i < 5; i++) {
      u_drag_src.guch [i] = p_gch [i];
    }
    // skip skip skip
  }
  context->drag_finish (true, true, time);
}

Thanks really a lot for any help.
Enjoy!
Let the source be with you!


-----------------------------------------------------------------
http://www.elmaz.com - Запознанства



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]