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

Re: [gnome-love] example request



On Fri, 2004-06-04 at 07:11 -0400, ethan zimmerman wrote:
> I'm having trouble finding useful GNOME/GTK+/Libglade examples so I
> thought I'd see if anyone here could make one for me. I don't think
> it'll be too hard, for people who know what they're doing that is. :-)
> 
> This is what I would like to see...
> 1. A "Main" window with a menubar and a TextView
>    + menubar contents
>      - File->Quit
>      - Edit->Preferences
> 
> 2. A "Preferences" dialog with a close button
> 
> 3. An "Are you sure you want to quit?" dialog with cancel and quit
> buttons

Attached are a C file and a GLADE XML file that should do all of this.
It's not the most polished application in the world, but you should be
able to use it as a starting point.

I developed this on my Fedora Core 2 system, but it should run on any
GTK+ 2.x system.  I only used GTK+ widgets, no GNOME stuff.

> Adding Edit->cut/copy/paste functionality would be nice too but what I'm
> most interested in is how multiple window stuff like the above works. 

I'll leave this as an exercise for you :-)

> frustrated and confused

Hopefully a little less frustrated and confused now,

Keith.
/*
    An example of a multi-window application using GTK+ and GLADE.
    Written by Keith Sharp <kms passback co uk>, Fri 04 Jun 2004 15:20:01 BST 
    
    Note that a real preferences dialog would use GConf to store and retrieve values
    
    This code is Public Domain - do what you want with it.

    To compile:
    
        gcc -o app app.c `pkg-config --cflags --libs gtk+-2.0 libglade-2.0`
        
*/

#include <gtk/gtk.h>
#include <glade/glade.h>


/* Callback for the delete-event signal, do nothing but return FALSE so
   that the destroy signal is emitted, and do the work in that callback */
gboolean
delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
    return FALSE;
}


/* Callback for the destroy signal, all we do is quit.  Other apps might
   do something more complex */
void
destroy_event_cb (GtkWidget *widget, gpointer data)
{
    gtk_main_quit ();
}


/* Callback for clicking on the prefs close button.  All we do is hide the
   widget for later reuse */
void
close_button_cb (GtkButton *button, gpointer data)
{
    gtk_widget_hide (GTK_WIDGET(data));
}


/* Callback for the activate signal on the entry widget.  We connect to
   this so that we can do instant apply which is the recommendation for
   preferences in GNOME */
void
entry_activate_cb (GtkEntry *entry, gpointer data)
{
    const gchar *name;
    
    name = gtk_entry_get_text (entry);
    g_print ("Name: %s\n", name);
}


/* Callback for the clicked signal on the cancel button. All we do is hide
   the widget for later reuse */
void
cancel_button_cb (GtkButton *button, gpointer data)
{
    gtk_widget_hide (GTK_WIDGET(data));
}


/* Callback for the clicked signal on the quit button.  All we do is quit */
void
quit_button_cb (GtkButton *button, gpointer data)
{
    gtk_main_quit ();
}


/* Callback for the activate signal on the quit menu item.  We show the 
   should we quit window */
void
quit_menu_cb (GtkMenuItem *menuitem, gpointer data)
{
    gtk_widget_show_all (GTK_WIDGET(data));
}


/* Callback for the activate signal on the prefs menu item.  We show the
   preferences window */
void
pref_menu_cb (GtkMenuItem *menuitem, gpointer data)
{
    gtk_widget_show_all (GTK_WIDGET(data));
}


/* The main function, initialise GTK, load the GLADE file, hook up the
   callbacks, and into the main loop */
gint
main (gint argc, gchar *argv[])
{
    GladeXML *xml;
    GtkWidget *main, *quitmenu, *prefmenu;
    GtkWidget *prefs, *close, *entry;
    GtkWidget *quit, *cancelbutton, *quitbutton;
    
    /* All GTK apps need to initialise GTK */
    gtk_init(&argc, &argv);
    
    /* Load the GLADE file, exit if this fails. */
    xml = glade_xml_new ("app.glade", NULL, NULL);
    if (!xml)
        g_error ("Failed to load glade file\n");


    /* First we setup the preferences window */
    /* Find the widget for the prefs window */
    prefs = glade_xml_get_widget (xml, "prefs-win");
    if (!prefs)
        g_error ("Could not get prefs window widget\n");

    /* Find the close button widget and connect up the clicked 
       signal handler */
    close = glade_xml_get_widget (xml, "close-button");
    if (!close)
        g_error ("Could not get close button widget\n");
    g_signal_connect (G_OBJECT(close), "clicked", G_CALLBACK(close_button_cb), prefs);

    /* Find the entry widget and connect up the activate signal handler */
    entry = glade_xml_get_widget (xml, "name-entry");
    if (!entry)
        g_error ("Could not get username entry widget\n");
    g_signal_connect (G_OBJECT(entry), "activate", G_CALLBACK(entry_activate_cb), NULL);


    /* Now we setup the quit window */
    /* Get the quit window widget */
    quit = glade_xml_get_widget (xml, "quit-win");
    if (!quit)
        g_error ("Could noy get quit window widget\n");
        
    /* Find the quit button widget and connect the signal handler */
    quitbutton = glade_xml_get_widget (xml, "quit-button");
    if (!quitbutton)
        g_error ("Could not get quit button widget\n");
    g_signal_connect (G_OBJECT(quitbutton), "clicked", G_CALLBACK(quit_button_cb), NULL);
    
    /* Find the cancel button widget and connect the signal handler */
    cancelbutton = glade_xml_get_widget (xml, "cancel-button");
    if (!cancelbutton)
        g_error ("Could not get cancel button widget\n");
    g_signal_connect (G_OBJECT(cancelbutton), "clicked", G_CALLBACK(cancel_button_cb), quit);


    /* Finally we setup the main window */    
    /* Get the main window widget and connect destroy and delete signal handers */
    main = glade_xml_get_widget (xml, "main-win");
    if (!main)
        g_error ("Could not get main window widget\n");
    g_signal_connect (G_OBJECT(main), "delete-event", G_CALLBACK(delete_event_cb), NULL);
    g_signal_connect (G_OBJECT(main), "destroy", G_CALLBACK(destroy_event_cb), NULL);

    /* Get the quit menu option and connect signal handler */
    quitmenu = glade_xml_get_widget (xml, "quit-menu");
    if (!quitmenu)
        g_error ("Could not get quit menu widget\n");
    g_signal_connect (G_OBJECT(quitmenu), "activate", G_CALLBACK(quit_menu_cb), quit);
    
    /* Get the prefs menu option and connect signal handler */
    prefmenu = glade_xml_get_widget (xml, "pref-menu");
    if (!prefmenu)
        g_error ("Could not get pref menu widget\n");
    g_signal_connect (G_OBJECT(prefmenu), "activate", G_CALLBACK(pref_menu_cb), prefs);

    /* Enter the main loop */
    gtk_main ();

    /* We are finished, lets go home */  
    return 0;
}
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd";>

<glade-interface>
<requires lib="gnome"/>

<widget class="GtkDialog" id="prefs-win">
  <property name="border_width">12</property>
  <property name="title" translatable="yes">Preferences</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
  <property name="modal">False</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
  <property name="has_separator">True</property>

  <child internal-child="vbox">
    <widget class="GtkVBox" id="dialog-vbox1">
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">0</property>

      <child internal-child="action_area">
	<widget class="GtkHButtonBox" id="dialog-action_area1">
	  <property name="visible">True</property>
	  <property name="layout_style">GTK_BUTTONBOX_END</property>

	  <child>
	    <widget class="GtkButton" id="close-button">
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-close</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <property name="response_id">-7</property>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	  <property name="pack_type">GTK_PACK_END</property>
	</packing>
      </child>

      <child>
	<widget class="GtkVBox" id="vbox1">
	  <property name="visible">True</property>
	  <property name="homogeneous">False</property>
	  <property name="spacing">18</property>

	  <child>
	    <widget class="GtkVBox" id="vbox2">
	      <property name="visible">True</property>
	      <property name="homogeneous">False</property>
	      <property name="spacing">6</property>

	      <child>
		<widget class="GtkLabel" id="label1">
		  <property name="visible">True</property>
		  <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;User Name&lt;/span&gt;</property>
		  <property name="use_underline">False</property>
		  <property name="use_markup">True</property>
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
		  <property name="wrap">False</property>
		  <property name="selectable">False</property>
		  <property name="xalign">0</property>
		  <property name="yalign">0.5</property>
		  <property name="xpad">0</property>
		  <property name="ypad">0</property>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">False</property>
		  <property name="fill">False</property>
		</packing>
	      </child>

	      <child>
		<widget class="GtkHBox" id="hbox1">
		  <property name="visible">True</property>
		  <property name="homogeneous">False</property>
		  <property name="spacing">0</property>

		  <child>
		    <widget class="GtkLabel" id="label2">
		      <property name="visible">True</property>
		      <property name="label" translatable="yes">    </property>
		      <property name="use_underline">False</property>
		      <property name="use_markup">False</property>
		      <property name="justify">GTK_JUSTIFY_LEFT</property>
		      <property name="wrap">False</property>
		      <property name="selectable">False</property>
		      <property name="xalign">0.5</property>
		      <property name="yalign">0.5</property>
		      <property name="xpad">0</property>
		      <property name="ypad">0</property>
		    </widget>
		    <packing>
		      <property name="padding">0</property>
		      <property name="expand">False</property>
		      <property name="fill">False</property>
		    </packing>
		  </child>

		  <child>
		    <widget class="GtkVBox" id="vbox3">
		      <property name="visible">True</property>
		      <property name="homogeneous">False</property>
		      <property name="spacing">0</property>

		      <child>
			<widget class="GtkHBox" id="hbox2">
			  <property name="visible">True</property>
			  <property name="homogeneous">False</property>
			  <property name="spacing">6</property>

			  <child>
			    <widget class="GtkLabel" id="label3">
			      <property name="visible">True</property>
			      <property name="label" translatable="yes">User name:</property>
			      <property name="use_underline">False</property>
			      <property name="use_markup">False</property>
			      <property name="justify">GTK_JUSTIFY_LEFT</property>
			      <property name="wrap">False</property>
			      <property name="selectable">False</property>
			      <property name="xalign">0.5</property>
			      <property name="yalign">0.5</property>
			      <property name="xpad">0</property>
			      <property name="ypad">0</property>
			    </widget>
			    <packing>
			      <property name="padding">0</property>
			      <property name="expand">False</property>
			      <property name="fill">False</property>
			    </packing>
			  </child>

			  <child>
			    <widget class="GtkEntry" id="name-entry">
			      <property name="visible">True</property>
			      <property name="can_focus">True</property>
			      <property name="editable">True</property>
			      <property name="visibility">True</property>
			      <property name="max_length">0</property>
			      <property name="text" translatable="yes"></property>
			      <property name="has_frame">True</property>
			      <property name="invisible_char" translatable="yes">*</property>
			      <property name="activates_default">False</property>
			    </widget>
			    <packing>
			      <property name="padding">0</property>
			      <property name="expand">True</property>
			      <property name="fill">True</property>
			    </packing>
			  </child>
			</widget>
			<packing>
			  <property name="padding">0</property>
			  <property name="expand">True</property>
			  <property name="fill">True</property>
			</packing>
		      </child>
		    </widget>
		    <packing>
		      <property name="padding">0</property>
		      <property name="expand">True</property>
		      <property name="fill">True</property>
		    </packing>
		  </child>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">True</property>
		  <property name="fill">True</property>
		</packing>
	      </child>
	    </widget>
	    <packing>
	      <property name="padding">0</property>
	      <property name="expand">True</property>
	      <property name="fill">True</property>
	    </packing>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">True</property>
	  <property name="fill">True</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

<widget class="GtkWindow" id="main-win">
  <property name="visible">True</property>
  <property name="title" translatable="yes">My First Application</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_CENTER</property>
  <property name="modal">False</property>
  <property name="default_width">500</property>
  <property name="default_height">400</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>

  <child>
    <widget class="GtkVBox" id="vbox4">
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">0</property>

      <child>
	<widget class="GtkMenuBar" id="menubar1">
	  <property name="visible">True</property>

	  <child>
	    <widget class="GtkMenuItem" id="menuitem1">
	      <property name="visible">True</property>
	      <property name="label" translatable="yes">_File</property>
	      <property name="use_underline">True</property>

	      <child>
		<widget class="GtkMenu" id="menuitem1_menu">

		  <child>
		    <widget class="GtkMenuItem" id="quit-menu">
		      <property name="visible">True</property>
		      <property name="label" translatable="yes">_Quit</property>
		      <property name="use_underline">True</property>
		      <accelerator key="q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
		    </widget>
		  </child>
		</widget>
	      </child>
	    </widget>
	  </child>

	  <child>
	    <widget class="GtkMenuItem" id="menuitem2">
	      <property name="visible">True</property>
	      <property name="label" translatable="yes">_Edit</property>
	      <property name="use_underline">True</property>

	      <child>
		<widget class="GtkMenu" id="menuitem2_menu">

		  <child>
		    <widget class="GtkMenuItem" id="pref-menu">
		      <property name="visible">True</property>
		      <property name="label" translatable="yes">Prefere_nces</property>
		      <property name="use_underline">True</property>
		      <accelerator key="p" modifiers="GDK_MOD1_MASK" signal="activate"/>
		    </widget>
		  </child>
		</widget>
	      </child>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">False</property>
	</packing>
      </child>

      <child>
	<widget class="GtkScrolledWindow" id="scrolledwindow1">
	  <property name="visible">True</property>
	  <property name="can_focus">True</property>
	  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
	  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
	  <property name="shadow_type">GTK_SHADOW_NONE</property>
	  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>

	  <child>
	    <widget class="GtkTextView" id="textview1">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="editable">True</property>
	      <property name="overwrite">False</property>
	      <property name="accepts_tab">True</property>
	      <property name="justification">GTK_JUSTIFY_LEFT</property>
	      <property name="wrap_mode">GTK_WRAP_NONE</property>
	      <property name="cursor_visible">True</property>
	      <property name="pixels_above_lines">0</property>
	      <property name="pixels_below_lines">0</property>
	      <property name="pixels_inside_wrap">0</property>
	      <property name="left_margin">0</property>
	      <property name="right_margin">0</property>
	      <property name="indent">0</property>
	      <property name="text" translatable="yes">This textview does nothing....</property>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">True</property>
	  <property name="fill">True</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

<widget class="GtkDialog" id="quit-win">
  <property name="border_width">18</property>
  <property name="title" translatable="yes">Really quit?</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
  <property name="modal">False</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
  <property name="has_separator">True</property>

  <child internal-child="vbox">
    <widget class="GtkVBox" id="dialog-vbox2">
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">0</property>

      <child internal-child="action_area">
	<widget class="GtkHButtonBox" id="dialog-action_area2">
	  <property name="visible">True</property>
	  <property name="layout_style">GTK_BUTTONBOX_END</property>

	  <child>
	    <widget class="GtkButton" id="cancel-button">
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-cancel</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <property name="response_id">-6</property>
	    </widget>
	  </child>

	  <child>
	    <widget class="GtkButton" id="quit-button">
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-quit</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <property name="response_id">-5</property>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	  <property name="pack_type">GTK_PACK_END</property>
	</packing>
      </child>

      <child>
	<widget class="GtkLabel" id="label4">
	  <property name="visible">True</property>
	  <property name="label" translatable="yes">Do you really want to quit?</property>
	  <property name="use_underline">False</property>
	  <property name="use_markup">False</property>
	  <property name="justify">GTK_JUSTIFY_LEFT</property>
	  <property name="wrap">False</property>
	  <property name="selectable">False</property>
	  <property name="xalign">0.5</property>
	  <property name="yalign">0.5</property>
	  <property name="xpad">0</property>
	  <property name="ypad">0</property>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">False</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

</glade-interface>


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