Re: libglademm signal_connect?



On Sat, 1 Jan 2005 13:33:04 -0800, leyland needham <leyland gmail com> wrote:
> I checked out the latest cvs of it and this seems like a (shorter)
> replacement for this :
> 
> Gtk::MenuItem* pMenuItem = 0;
> refXml->get_widget("menuitem5", pMenuItem);
> if(pMenuItem)
>   pMenuItem->signal_activate().connect(sigc::ptr_fun(&on_button_clicked));
> 
> Which is what I kind of didn't want to do. I was hoping for something
> that would use the handler name, and not the widget name. There by any
> place in the gladexml you use the handler name it would attach my
> callback. Or even something that would do autoconnects, although glade
> doesn't support objects in every place you can have a handler (like
> for menus), so you couldn't just attach handlers from an object I
> create.
> 
> My personal preference is to only derive from widgets when needed, so
> I prefer to use connect methods, but I would also like to abstract
> more from the contents of the glade file so users can make custom
> interfaces, and all they have to know is what handlers my program
> provides/attachs to the glade interface.
> 
> On Sat, 01 Jan 2005 10:25:59 +0100, Alberto Paro
> <alberto paro homeunix org> wrote:
> > Il giorno sab, 01-01-2005 alle 00:16 -0800, leyland needham ha scritto:
> > > Like instead of having to get the widget and signal connect it
> > > yourself, do something like this :
> > > GladeXml->signal_connect( "HandlerName", ptr_fun(&my_signal_handler));
> > > GladeXml->signal_connect( "Handler2Name", mem_fun(foo,&CFoo::bar));
> > >
> > > Would this be out of scope for the libglade wrapper?
> > In libglademm cvs there is connect_clicked()
> >
> > Usage from VariablesMap example:
> >
> >   //Connect button's signal handler:
> >   //Glade::Xml::connect_clicked() is a convenience method, which has
> > nothing to do with the VariablesMap.
> >   m_refGlade->connect_clicked("button", sigc::mem_fun(*this,
> > &ExampleWindow::on_button_clicked));
> >   m_refGlade->connect_clicked("file_new", sigc::mem_fun(*this,
> > &ExampleWindow::on_file_new));
> >   m_refGlade->connect_clicked("file_exit", sigc::mem_fun(*this,
> > &ExampleWindow::on_file_exit));
> >   m_refGlade->connect_clicked("help_info", sigc::mem_fun(*this,
> > &ExampleWindow::on_info));
> >
> > Hi,
> >         Alberto
> >
> >
> 

I've created my own version of a signal_connect function, that works
more the way I wanted it to, in case any one is interested in using
it, or if any one wants to look into integrating this into libglademm.

This is probably a big hack and I am not sure how safe it is (hasn't
crashed on me in my tests), most of it is hacked from the glibmm and
gtkmm in they handle signals. I tried using glibmm directly but it
wasn't working because it is designed to work with associated
wrappers, and I think glade widgets only get wrapped when you call
get_widget on them.

The main function to call is 

void signal_connect(Glib::RefPtr<Gnome::Glade::Xml> refXml, 
                    const Glib::ustring& handlername,
                    const sigc::slot<void> &slot);

An example is :

signal_connect(refXml, "OnQuitHandler", sigc::ptr_fun(&on_quit_handler));

The code for it is here :

#include <gtkmm.h>
#include <libglademm.h>
#include <glade/glade.h>

typedef struct {
    const sigc::slot_base *slot;
} connect_data_data;

static void
slot0_void_callback(GObject* self, void* data)
{
  // Do not try to call a signal on a disassociated wrapper.
  //if(Glib::ObjectBase::_get_current_wrapper(self))
  {
    try
    {
      if(sigc::slot_base *const slot = static_cast<sigc::slot_base*>(data))
        (*static_cast<sigc::slot<void>*>(slot))();
    }
    catch(...)
    {
      Glib::exception_handlers_invoke();
    }
  }
}

static void
destroy_notify_handler(gpointer data, GClosure*)
{
  //glib calls this when it has finished with a glib signal connection,
  //either when the emitting object dies, or when the connection has
been disconnected.
  
  // notification from gtk+.
  sigc::slot_base *slot = static_cast<sigc::slot_base*>(data);

  if(slot)
    delete slot; // if there are connection objects referring to slot_
they are notified during destruction of slot_
}

static void
connect_data_connect_func(const gchar *handler_name, GObject *object,
			  const gchar *signal_name, const gchar *signal_data,
			  GObject *connect_object, gboolean after,
			  gpointer user_data)
{
    const sigc::slot_base *slot = ((connect_data_data *)user_data)->slot;

    if (connect_object) {
       // don't know what to do about this
//	g_signal_connect_object(object, signal_name, data->func,
//	    connect_object, (after ? G_CONNECT_AFTER : 0) | G_CONNECT_SWAPPED);
    } else {
//        Glib::SignalProxyConnectionNode *const pConnectionNode =
//            new Glib::SignalProxyConnectionNode(*slot, object);
        // connect it to glib
        // pConnectionNode will be passed in the data argument to the callback.
//        pConnectionNode->connection_id_ = g_signal_connect_data(
//            object, signal_name,
//            (GCallback)&Glib::SignalProxyNormal::slot0_void_callback,
//            pConnectionNode,
//            &Glib::SignalProxyConnectionNode::destroy_notify_handler,
//            static_cast<GConnectFlags>((after) ? G_CONNECT_AFTER : 0));

        sigc::slot_base *slot_ = new sigc::slot_base(*slot);
        
        g_signal_connect_data( object, signal_name,
              (GCallback)&slot0_void_callback,
              slot_,
              destroy_notify_handler,
              static_cast<GConnectFlags>((after) ? G_CONNECT_AFTER : 0));

        g_print("%s %s\n", handler_name, signal_name);
            
    }
}

void signal_connect(Glib::RefPtr<Gnome::Glade::Xml> refXml, 
                    const Glib::ustring& handlername,
                    const sigc::slot<void> &slot)
{
    connect_data_data data;
    data.slot = &slot;
    glade_xml_signal_connect_full(refXml->gobj(), handlername.c_str(),
connect_data_connect_func, &data);
}


This all can be improved by maybe having a list of handlers, and then
passing it to each gladexml when you load an glade interface.

Lee



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