Custom container on_remove



Hi,

I'm trying to create a custom container derived directly from Gtk::Container.  However, if a child widget is destroyed, on_remove() doesn't get called.

According to the Gtk+ and gtkmm doco (http://library.gnome.org/devel/gtk/stable/GtkContainer.html#gtk-container-remove, and http://www..gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Object.html), when a child widget is destroyed it is automatically removed from its parent.  The automatic removal appears to work just fine for all the gtkmm widgets and my own derived widgets when added to any of the gtkmm containers (Gtk::Bin, Gtk::VBox, ...).

Adding any of those widgets to my own derived container and then deleting the child widget leaves the derived container with a dangling pointer -> segfault.

I've looked at the custom container example in the tutorial (http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/chapter-customwidgets.html) and it has this problem too.

Attached is a modified ExampleWindow (and svn diff) for use with the example to illustrate the problem.  Pressing the "quit" button deletes a child before quiting.

I've come across two bugs that I think are relevant:
http://bugzilla.gnome.org/show_bug.cgi?id=518002  (gtkmm)
With gtkmm prior to that bug fix, my modified example prints the warning message (as listed in the bug report) before segfaulting:
Gtk-WARNING **: GtkContainerClass::remove not implemented for `gtkmm__GtkContainer'
If I interpret the change correctly, the fix basically tests for non-gtkmm containers to silence the warning.

http://bugzilla.gnome.org/show_bug.cgi?id=315874  (glibmm Note: bug is still marked as NEW)
Looks like it's describing the same problem from a slightly different perspective.  Reading the comments there, I question whether "it's perfectly valid for the container to listen for the remove signal and to be notified at delete time" because logically it's the container (itself) that emits signal_remove() in response to a child being destroyed.  It would make more sense to me if an external destroy/delete of a child resulted in on_remove() being called on the container so there is symmetry between on_add()/signal_add() and on_remove()/signal_remove().

If on_remove() should be getting called, then perhaps this is just more material for bug #315874 which I don't know how to fix, but might be able to help (e.g. test cases etc).  If this isn't a bug in the library then I'd be happy to provide a patch for the example after I'm set on the right track.

Regards,
Clive


      Get the name you always wanted with the new y7mail email address.
www.yahoo7.com.au/mail
//$Id: examplewindow.h 705 2006-07-19 02:55:32Z jjongsma $ -*- c++ -*-

/* gtkmm example Copyright (C) 2004 gtkmm development team
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>
#include "mycontainer.h"

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //Signal handlers:
  virtual void on_button_quit();

  //Child widgets:
  Gtk::VBox m_VBox;
  MyContainer m_MyContainer;
  Gtk::Button* m_Button_One;
  Gtk::Label m_Button_Two;
  Gtk::HButtonBox m_ButtonBox;
  Gtk::Button m_Button_Quit;
};

#endif //GTKMM_EXAMPLEWINDOW_H
//$Id: examplewindow.cc 836 2007-05-09 03:02:38Z jjongsma $ -*- c++ -*-

/* gtkmm example Copyright (C) 2004 gtkmm development team
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <iostream>
#include "examplewindow.h"

ExampleWindow::ExampleWindow()
: m_Button_One(new Gtk::Button("Child One")),
  m_Button_Two("Child 2"),
  m_Button_Quit("Quit")
{
  set_title("Custom Container example");
  set_border_width(6);
  set_default_size(400, 200);

  add(m_VBox);

  //Add the child widgets to the custom container:
  m_MyContainer.set_child_widgets(*m_Button_One, m_Button_Two);
  m_Button_One->show();
  m_Button_Two.show();

#ifdef GLIBMM_PROPERTIES_ENABLED
  m_Button_Two.property_xalign() = 1.0f; 
#else
  m_Button_Two.set_property("xalign", 1.0f); 
#endif //GLIBMM_PROPERTIES_ENABLED

  m_VBox.pack_start(m_MyContainer, Gtk::PACK_EXPAND_WIDGET);
  m_MyContainer.show();

  m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);

  m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
  m_ButtonBox.set_border_width(6);
  m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
  m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this,
              &ExampleWindow::on_button_quit) );

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
  if (m_Button_One)
    delete m_Button_One;
}

void ExampleWindow::on_button_quit()
{
  if (m_Button_One) {
    delete m_Button_One;
    m_Button_One = 0;
  }
  hide();
}

Attachment: custom_container_remove.diff-r53
Description: Binary data



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