Re: destroy signal in a class derived from gtkwindow
- From: Stefan Kost <kost imn htwk-leipzig de>
- To: "David Necas (Yeti)" <yeti physics muni cz>
- Cc: gtk-app-devel-list gnome org
- Subject: Re: destroy signal in a class derived from gtkwindow
- Date: Fri, 20 Aug 2004 15:00:00 +0200
Hi hi,
thanks for replying so quickly. Attached is my class.
David Necas (Yeti) wrote:
On Wed, Aug 18, 2004 at 07:49:12PM +0200, Stefan Kost wrote:
I derived my main-window classs from GtkWindow (a top-level window).
I have connected a signal-handler to the "delete-event" for the window to show a
"are you sure" dialog.
When I return FALSE from the handler, the destroy signal was sent to my window
before I was deriving the winodw class.
Now I don't get the destoy signal. Do I need to emit the "destroy" signal myself
(to the parent object)?
Do I need to forward signal in general?
I'm not sure if I understand what you are doing... whether
you override delete event method in the class implementation,
or connect to it in application code...
I am not overiding it, but my class connects to it and handles it (or wants to
handle it).
but if you don't
have something else connected to "delete_event", the
"destroy" signal should be sent normally. See the attached
code and compare...
For testing I have overidden the destroy methods too (commented out in the
attached code) and it's not getting called.
And I thought I understand the gobject stuff :-(
Stefan
Two notes:
- the test does not do gtk_main_quit() on window close to
avoid any suspicion of interference
- The destroy() method is actually called twice ... who
knows why
Yeti
--
Do not use tab characters. Their effect is not predictable.
/* interface ****************************************************************/
#include <gtk/gtk.h>
#define MY_TYPE_WINDOW (my_window_get_type())
#define MY_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), MY_TYPE_WINDOW, MyWindow))
#define MY_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), MY_TYPE_WINDOW, MyWindowClass))
#define IS_MY_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), MY_TYPE_WINDOW))
#define IS_MY_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), MY_TYPE_WINDOW))
#define MY_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), MY_TYPE_WINDOW, MyWindowClass))
typedef struct _MyWindow MyWindow;
typedef struct _MyWindowClass MyWindowClass;
struct _MyWindow {
GtkWindow parent_instance;
};
struct _MyWindowClass {
GtkWindowClass parent_class;
};
GtkWidget* my_window_new (void);
GType my_window_get_type (void) G_GNUC_CONST;
/* implementation ************************************************************/
#define MY_WINDOW_TYPE_NAME "MyWindow"
static void my_window_class_init (MyWindowClass *klass);
static void my_window_init (MyWindow *mywindow);
static void my_window_destroy (GtkObject *object);
static GtkWindowClass *parent_class = NULL;
GType
my_window_get_type(void)
{
static GType my_window_type = 0;
if (!my_window_type) {
static const GTypeInfo my_window_info = {
sizeof(MyWindowClass),
NULL,
NULL,
(GClassInitFunc)my_window_class_init,
NULL,
NULL,
sizeof(MyWindow),
0,
(GInstanceInitFunc)my_window_init,
NULL,
};
my_window_type = g_type_register_static(GTK_TYPE_WINDOW,
MY_WINDOW_TYPE_NAME,
&my_window_info,
0);
}
return my_window_type;
}
static void
my_window_class_init(MyWindowClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass*)klass;
widget_class = (GtkWidgetClass*)klass;
parent_class = g_type_class_peek_parent(klass);
object_class->destroy = my_window_destroy;
}
static void
my_window_init(MyWindow *mywindow)
{
}
GtkWidget*
my_window_new(void)
{
MyWindow *mywindow;
mywindow = (MyWindow*)g_object_new(MY_TYPE_WINDOW, NULL);
return GTK_WIDGET(mywindow);
}
static void
my_window_destroy(GtkObject *object)
{
g_printerr("Aargh! I'm finished.\n");
GTK_OBJECT_CLASS(parent_class)->destroy(object);
}
/* test **********************************************************************/
static gboolean
delete_event_handler(GtkWidget *window)
{
GtkWidget *dialog;
gboolean res;
dialog = gtk_message_dialog_new(GTK_WINDOW(window), 0,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"Really close?");
gtk_window_present(GTK_WINDOW(dialog));
res = gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_YES;
gtk_widget_destroy(dialog);
return res;
}
int
main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = my_window_new();
gtk_container_add(GTK_CONTAINER(window),
gtk_label_new("Mirror, mirror on the wall,\n"
"tell me if I am the most HIG 2.0\n"
"compliant of all..."));
g_signal_connect(window, "delete_event",
G_CALLBACK(delete_event_handler), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
--
\|/ Stefan Kost
<@ @> private business
+-oOO-(_)-OOo------------------------------------------------------ - - - - -
| __ Address Simildenstr. 5 HTWK Leipzig, Fb IMN, Postfach 301166
| /// 04277 Leipzig 04251 Leipzig
| __ /// Germany Germany
| \\\/// Phone +49341 2253538 +49341 30766101
| \__/ EMail st_kost_at_gmx.net kost_at_imn.htwk-leipzig.de
| WWW www.sonicpulse.de www.imn.htwk-leipzig.de/~kost/about.html
===-=-=--=---=---------------------------------- - - - - -
/* $Id: main-window.c,v 1.16 2004/08/19 17:03:44 ensonic Exp $
* class for the editor main window
*/
#define BT_EDIT
#define BT_MAIN_WINDOW_C
#include "bt-edit.h"
enum {
MAIN_WINDOW_APP=1,
};
struct _BtMainWindowPrivate {
/* used to validate if dispose has run */
gboolean dispose_has_run;
/* the application */
BtEditApplication *app;
/* the menu of the window */
BtMainMenu *menu;
/* the toolbar of the window */
BtMainToolbar *toolbar;
/* the content pages of the window */
BtMainPages *pages;
/* the statusbar of the window */
BtMainStatusbar *statusbar;
/* the keyboard shortcut table for the window */
GtkAccelGroup *accel_group;
};
//-- event handler
static gboolean on_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
BtMainWindow *self=BT_MAIN_WINDOW(user_data);
gboolean res=TRUE;
GST_INFO("delete event occurred\n");
// returning TRUE means, we don't want the window to be destroyed
if(bt_main_window_check_quit(BT_MAIN_WINDOW(user_data))) {
res=FALSE;
//GST_INFO(" prepare to exit\n");
//gtk_object_destroy(G_OBJECT(self));
//gtk_widget_destroy(GTK_WIDGET(self));
}
return(res);
}
static void on_window_destroy(GtkWidget *widget, gpointer user_data) {
GST_INFO("destroy occurred\n");
gtk_main_quit();
}
static void on_song_changed(const BtEditApplication *app, gpointer user_data) {
BtMainWindow *self=BT_MAIN_WINDOW(user_data);
static gchar *title;
BtSong *song;
GST_INFO("song has changed : app=%p, window=%p\n",song,user_data);
// get song from app
song=BT_SONG(bt_g_object_get_object_property(G_OBJECT(app),"song"));
// compose title
title=g_strdup_printf(PACKAGE_NAME":
%s",bt_g_object_get_string_property(G_OBJECT(bt_song_get_song_info(song)),"name"));
gtk_window_set_title(GTK_WINDOW(self), title);
}
//-- helper methods
static gboolean bt_main_window_init_ui(const BtMainWindow *self) {
GtkWidget *box;
GdkPixbuf *main_icon;
self->private->accel_group=gtk_accel_group_new();
// create and set window icon
if((main_icon=create_pixbuf("buzztard.png"))) {
gtk_window_set_icon(GTK_WINDOW(self),main_icon);
}
// create main layout container
box=gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(self),box);
// add the menu-bar
self->private->menu=bt_main_menu_new(self->private->app,self->private->accel_group);
gtk_box_pack_start(GTK_BOX(box),GTK_WIDGET(self->private->menu),FALSE,FALSE,0);
// add the tool-bar
self->private->toolbar=bt_main_toolbar_new(self->private->app);
gtk_box_pack_start(GTK_BOX(box),GTK_WIDGET(self->private->toolbar),FALSE,FALSE,0);
// add the window content pages
self->private->pages=bt_main_pages_new(self->private->app);
gtk_box_pack_start(GTK_BOX(box),GTK_WIDGET(self->private->pages),TRUE,TRUE,0);
// add the status bar
self->private->statusbar=bt_main_statusbar_new(self->private->app);
gtk_box_pack_start(GTK_BOX(box),GTK_WIDGET(self->private->statusbar),FALSE,FALSE,0);
g_signal_connect(G_OBJECT(self->private->app), "song-changed", (GCallback)on_song_changed, (gpointer)self);
gtk_window_add_accel_group(GTK_WINDOW(self),self->private->accel_group);
g_signal_connect(G_OBJECT(self),"delete-event", G_CALLBACK(on_window_delete_event),(gpointer)self);
g_signal_connect(G_OBJECT(self),"destroy", G_CALLBACK(on_window_destroy),(gpointer)self);
return(TRUE);
}
//-- constructor methods
/**
* bt_main_window_new:
* @app: the application the window belongs to
*
* Create a new instance
*
* Return: the new instance or NULL in case of an error
*/
BtMainWindow *bt_main_window_new(const BtEditApplication *app) {
BtMainWindow *self;
if(!(self=BT_MAIN_WINDOW(g_object_new(BT_TYPE_MAIN_WINDOW,"app",app,"type",GTK_WINDOW_TOPLEVEL,NULL)))) {
goto Error;
}
// generate UI
if(!bt_main_window_init_ui(self)) {
goto Error;
}
gtk_widget_show_all(GTK_WIDGET(self));
return(self);
Error:
if(self) g_object_unref(self);
return(NULL);
}
//-- methods
/**
* bt_main_window_run:
* @self: the window instance to setup and run
*
* build, show and run the main window
*
* Returns: true for success
*/
gboolean bt_main_window_run(const BtMainWindow *self) {
gboolean res=TRUE;
GST_INFO("before running the UI\n");
gtk_main();
GST_INFO("after running the UI\n");
return(res);
}
/**
* bt_main_window_check_quit:
* @self: the main window instance
*
* Displays a dialog box, that asks the user to confirm exiting the application.
*
* Return: TRUE if the user has confirmed to exit
*/
gboolean bt_main_window_check_quit(const BtMainWindow *self) {
gboolean quit=FALSE;
gint result;
GtkWidget *label,*icon,*box;
GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Really quit ?"),
GTK_WINDOW(self),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
box=gtk_hbox_new(FALSE,0);
icon=gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,GTK_ICON_SIZE_DIALOG);
gtk_container_add(GTK_CONTAINER(box),icon);
label=gtk_label_new(_("Really quit ?"));
gtk_container_add(GTK_CONTAINER(box),label);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),box);
gtk_widget_show_all(dialog);
result=gtk_dialog_run(GTK_DIALOG(dialog));
switch(result) {
case GTK_RESPONSE_ACCEPT:
quit=TRUE;
break;
case GTK_RESPONSE_REJECT:
quit=FALSE;
break;
default:
GST_WARNING("unhandled response code = %d\n",result);
}
gtk_widget_destroy(dialog);
GST_INFO("menu quit result = %d\n",quit);
return(quit);
}
/**
* bt_main_window_new_song:
* @self: the main window instance
*
* Prepares a new song. Triggers cleaning up the old song and refreshes the ui.
*/
void bt_main_window_new_song(const BtMainWindow *self) {
// @todo if unsaved ask the use, if we should save the song
if(!bt_edit_application_new_song(self->private->app)) {
// @todo show error message
}
}
/**
* bt_main_window_open_song:
* @self: the main window instance
*
* Opens a dialog box, where the user can choose a song to load.
* If the dialog is not canceld, the old song will be freed, the new song will
* be loaded and the ui will be refreshed upon success.
*/
void bt_main_window_open_song(const BtMainWindow *self) {
GtkWidget *dialog=gtk_file_selection_new(_("Choose a song"));
gint result;
/* Lets set the filename, as if this were a save dialog, and we are giving
a default filename */
gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog),DATADIR""G_DIR_SEPARATOR_S"songs"G_DIR_SEPARATOR_S);
result=gtk_dialog_run(GTK_DIALOG(dialog));
switch(result) {
case GTK_RESPONSE_ACCEPT:
case GTK_RESPONSE_OK:
if(!bt_edit_application_load_song(self->private->app,gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog))))
{
// @todo show error message
}
break;
case GTK_RESPONSE_REJECT:
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_CLOSE:
break;
default:
GST_WARNING("unhandled response code = %d\n",result);
}
gtk_widget_destroy(dialog);
}
//-- wrapper
//-- class internals
/* returns a property for the given property_id for this object */
static void bt_main_window_get_property(GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
BtMainWindow *self = BT_MAIN_WINDOW(object);
return_if_disposed();
switch (property_id) {
case MAIN_WINDOW_APP: {
g_value_set_object(value, G_OBJECT(self->private->app));
} break;
default: {
g_assert(FALSE);
break;
}
}
}
/* sets the given properties for this object */
static void bt_main_window_set_property(GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
BtMainWindow *self = BT_MAIN_WINDOW(object);
return_if_disposed();
switch (property_id) {
case MAIN_WINDOW_APP: {
self->private->app = g_object_ref(G_OBJECT(g_value_get_object(value)));
//GST_DEBUG("set the app for main_window: %p",self->private->app);
} break;
default: {
g_assert(FALSE);
break;
}
}
}
static void bt_main_window_dispose(GObject *object) {
BtMainWindow *self = BT_MAIN_WINDOW(object);
return_if_disposed();
self->private->dispose_has_run = TRUE;
}
static void bt_main_window_finalize(GObject *object) {
BtMainWindow *self = BT_MAIN_WINDOW(object);
g_object_unref(G_OBJECT(self->private->app));
g_free(self->private);
}
//static void bt_main_window_destroy(GtkObject *object) {
// BtMainWindow *self = BT_MAIN_WINDOW(object);
//
// GST_INFO(" someone is killing me");
//}
static void bt_main_window_init(GTypeInstance *instance, gpointer g_class) {
BtMainWindow *self = BT_MAIN_WINDOW(instance);
self->private = g_new0(BtMainWindowPrivate,1);
self->private->dispose_has_run = FALSE;
}
static void bt_main_window_class_init(BtMainWindowClass *klass) {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS(klass);
GParamSpec *g_param_spec;
gobject_class->set_property = bt_main_window_set_property;
gobject_class->get_property = bt_main_window_get_property;
gobject_class->dispose = bt_main_window_dispose;
gobject_class->finalize = bt_main_window_finalize;
//gtkobject_class->destroy = bt_main_window_destroy;
g_object_class_install_property(gobject_class,MAIN_WINDOW_APP,
g_param_spec_object("app",
"app contruct prop",
"Set application object, the window belongs to",
BT_TYPE_EDIT_APPLICATION, /* object type */
G_PARAM_CONSTRUCT_ONLY |G_PARAM_READWRITE));
}
GType bt_main_window_get_type(void) {
static GType type = 0;
if (type == 0) {
static const GTypeInfo info = {
sizeof (BtMainWindowClass),
NULL, // base_init
NULL, // base_finalize
(GClassInitFunc)bt_main_window_class_init, // class_init
NULL, // class_finalize
NULL, // class_data
sizeof (BtMainWindow),
0, // n_preallocs
(GInstanceInitFunc)bt_main_window_init, // instance_init
};
type = g_type_register_static(GTK_TYPE_WINDOW,"BtMainWindow",&info,0);
}
return type;
}
/* $Id: main-window.h,v 1.2 2004/08/11 15:50:04 ensonic Exp $
* class for the editor main window
*/
#ifndef BT_MAIN_WINDOW_H
#define BT_MAIN_WINDOW_H
#include <glib.h>
#include <glib-object.h>
/**
* BT_TYPE_MAIN_WINDOW:
*
* #GType for BtMainWindow instances
*/
#define BT_TYPE_MAIN_WINDOW (bt_main_window_get_type ())
#define BT_MAIN_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BT_TYPE_MAIN_WINDOW,
BtMainWindow))
#define BT_MAIN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BT_TYPE_MAIN_WINDOW,
BtMainWindowClass))
#define BT_IS_MAIN_WINDOW(obj) (G_TYPE_CHECK_TYPE ((obj), BT_TYPE_MAIN_WINDOW))
#define BT_IS_MAIN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BT_TYPE_MAIN_WINDOW))
#define BT_MAIN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BT_TYPE_MAIN_WINDOW,
BtMainWindowClass))
/* type macros */
typedef struct _BtMainWindow BtMainWindow;
typedef struct _BtMainWindowClass BtMainWindowClass;
typedef struct _BtMainWindowPrivate BtMainWindowPrivate;
/**
* BtMainWindow:
*
* the root window for the editor application
*/
struct _BtMainWindow {
GtkWindow parent;
/* private */
BtMainWindowPrivate *private;
};
/* structure of the main-window class */
struct _BtMainWindowClass {
GtkWindowClass parent;
};
/* used by MAIN_WINDOW_TYPE */
GType bt_main_window_get_type(void);
#endif // BT_MAIN_WINDOW_H
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]