Problem with reparent (Gtk+-2.12)



Good day,

Few days ago we have downloaded latest packages to build Gtk+-2.12 and
Gtkmm-2.12 under Win32. The purpose was to fix our application when
running on Vista OS (selected menu items were blank - Gtk+2.8).

Now we have following problem.

When we are trying to reparent container with toolbar inside from one
window to another, and then reparent back again, application throws GTK-
Critical about some widget not ANCHORED or VISIBLE, and next we get
"widget is not realized" inside map/unmap signal handler.

Using GDB I found that widget is GtkImage inside GtkToolbar from first
GtkToolbutton.

I have an example where you may see GTK-Critical message when hit
DOCK/UNDOCK button. There is some work around getting accelerators
activated/deactivated. But our application have to use it.

First my thought was "They fixed GtkToolbar reparent problem, probably".
You know, when you reparent container with toolbar then you will find
toolbar elements inactive until hide() and show() it in some way. But
this problem is still here.

So, does someone know if this "new" problem with reparent is known
issue?

Where in bugzilla I could track it and, probably, attach simple example
to show the problem?

Regards,
-andrew

#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <gtkmm/label.h>
#include <gtkmm/button.h>
#include <gtkmm/notebook.h>
#include <gtkmm/box.h>
#include <gtkmm/frame.h>
#include <gtkmm/accelgroup.h>
#include <gtkmm/action.h>
#include <gtkmm/actiongroup.h>
#include <gtkmm/toolbar.h>
#include <gtkmm/tooltips.h>
#include <gtkmm/stock.h>
#include <gdk/gdkkeysyms.h>

#include <list>
#include <iostream>

#if ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 4 )
#define SigC_bind sigc::bind
#define SigC_slot sigc::mem_fun
#else
#define SigC_bind SigC::bind
#define SigC_slot SigC::slot
#endif

using namespace std;

class MyApp;

MyApp* main_window;
Gtk::Tooltips* tooltips = 0;

class MyWin : public Gtk::Window
{
    public:
	MyWin() : Gtk::Window( Gtk::WINDOW_TOPLEVEL ), docked( false )
	{
	    Glib::RefPtr< Gtk::AccelGroup > ag = get_accel_group();

	    Gtk::VBox* vbox = manage( new Gtk::VBox );
	    add( *vbox );
	    child_widget = vbox;

	    Gtk::Label* l = Gtk::manage( new Gtk::Label( "single window" ) );
	    vbox->pack_start( *l, Gtk::PACK_EXPAND_WIDGET );

	    Gtk::Toolbar* bar = Gtk::manage( new Gtk::Toolbar() );
	    bar->set_tooltips();

	    action = Gtk::Action::create( "new", Gtk::Stock::NEW, "", "Create New Window" );
	    cout << action->gobj() << " action created" << endl;

	    Glib::RefPtr< Gtk::ActionGroup > actGrp = Gtk::ActionGroup::create( "MainGroup" );

	    actGrp->add( action,
			 Gtk::AccelKey( "<control>N" ),
			 SigC_slot( *this, &MyWin::actions_handler ) );
	    Gtk::ToolItem* item = action->create_tool_item();
	    item->set_tooltip( *tooltips, "Create New Window" );
	    item->set_expand( false );
	    item->set_homogeneous( false );
	    bar->append( *item );
	    bar->show();
	    bar->set_toolbar_style( Gtk::TOOLBAR_ICONS );

	    action->set_accel_group( ag );
	    action->connect_accelerator();

	    vbox->pack_start( *bar, Gtk::PACK_SHRINK );

	    {
		Gtk::Button* b = Gtk::manage( new Gtk::Button( "DOCK/UNDOCK" ) );
		vbox->pack_start( *b, Gtk::PACK_SHRINK );
		b->signal_clicked().connect( SigC_slot( *this, &MyWin::dock_cb ) );

		b->signal_hierarchy_changed().connect( SigC_bind( SigC_slot( *this, &MyWin::hier_cb ), b ) );

		b->add_accelerator( "clicked", ag, GDK_F2,
				    ( Gdk::ModifierType )0,
				    Gtk::ACCEL_VISIBLE );
		b->signal_map().connect
			( SigC_bind( SigC_slot( *this, &MyWin::map_cb ), b ) );
		b->signal_unmap().connect
			( SigC_bind( SigC_slot( *this, &MyWin::unmap_cb ), b ) );
	    }

	    {
		Gtk::Button* b = Gtk::manage( new Gtk::Button( "New Window" ) );
		vbox->pack_start( *b, Gtk::PACK_SHRINK );
		b->signal_clicked().connect( SigC_slot( *this, &MyWin::add_win ) );
	    }

	    show_all_children();
	}
	~MyWin()
	{
	}
	void dock_cb();
	void map_cb( Gtk::Widget* b );
	void unmap_cb( Gtk::Widget* b );
	void hier_cb( Gtk::Widget* old_parent, Gtk::Widget* b );

	void actions_handler()
	{
	    cout << action->gobj() << " action toggled" << endl;
	}

	void add_win()
	{
	    MyWin* win = new MyWin();
	    win->show();
	}

    private:
	Gtk::Widget* parent_widget;
	Gtk::Widget* child_widget;
	Glib::RefPtr< Gtk::Action > action;
	bool docked;
};

class MyApp : public Gtk::Window
{
    public:
	MyApp()
	{
	    Gtk::VBox* vbox = Gtk::manage( new Gtk::VBox );
	    add( *vbox );
	    Gtk::Button* b = Gtk::manage( new Gtk::Button( "New Window" ) );
	    vbox->pack_start( *b, Gtk::PACK_SHRINK );
	    b->signal_clicked().connect( SigC_slot( *this, &MyApp::add_win ) );
	    vbox->pack_start( notebook, Gtk::PACK_EXPAND_WIDGET );
	    notebook.set_show_border( true );

	    tooltips = new Gtk::Tooltips();
	    tooltips->enable();

	    show_all_children();
	}
	~MyApp ()
	{
	}
	void add_win()
	{
	    MyWin* win = new MyWin();
	    win->show();
	}
	Gtk::Widget* get_table_widget ()
	{
	    char buff[32];
	    Gtk::Frame* f = manage( new Gtk::Frame() );
	    f->show();
	    pages.push_back (f);
	    sprintf( buff, "Screen _%d", pages.size() );
	    notebook.append_page( *f, Glib::ustring( buff ), true );
	    int num = notebook.page_num( *f );
	    notebook.set_current_page( num );
	    return f;
	}
	void free_page( Gtk::Widget* widget )
	{
	    pages.remove( widget );
	    notebook.remove_page( *widget );
	}

    private:
	Gtk::Notebook notebook;
	std::list< Gtk::Widget* > pages;
};

void MyWin::dock_cb()
{
    if( docked )
    {
	action->disconnect_accelerator();

	child_widget->reparent( *this );
	main_window->free_page( parent_widget );
	docked = false;
	show();

	action->set_accel_group( get_accel_group() );
	action->connect_accelerator();
    }
    else
    {
	action->disconnect_accelerator();

	parent_widget = main_window->get_table_widget();
	child_widget->reparent( *parent_widget );
	docked = true;
	hide();

	action->set_accel_group( main_window->get_accel_group() );
	action->connect_accelerator();
    }
}

void MyWin::hier_cb( Gtk::Widget* old_parent, Gtk::Widget* b )
{
    cout << "hier changed from: " << old_parent
	    << " this=" << this << " main=" << main_window << endl;
    if( old_parent == 0 )
	return;
    if( old_parent == this )
    {
	b->add_accelerator( "clicked", main_window->get_accel_group(),
			    GDK_F2, (Gdk::ModifierType)0,
			    Gtk::ACCEL_VISIBLE );
    }
    else
    {
	b->remove_accelerator( main_window->get_accel_group(),
			       GDK_F2, (Gdk::ModifierType)0 );
    }
}

void MyWin::map_cb( Gtk::Widget* b )
{
    if( !docked )
	return;

    cout << b << " - map" << endl;

    b->add_accelerator( "clicked", main_window->get_accel_group(),
			GDK_F2, (Gdk::ModifierType)0,
			Gtk::ACCEL_VISIBLE );

    action->set_accel_group( main_window->get_accel_group() );
    action->connect_accelerator();
}

void MyWin::unmap_cb( Gtk::Widget* b )
{
    if( !docked )
	return;

    cout << b << " - unmap" << endl;

    b->remove_accelerator( main_window->get_accel_group(),
			   GDK_F2, (Gdk::ModifierType)0 );

    action->disconnect_accelerator();
}

int main( int argc, char* argv[] )
{
    Gtk::Main kit( &argc, &argv );
    MyApp app;
    main_window = &app;

    kit.run( app );

    return 0;
}


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