Setting Properties to a costume Widget (GTK3)

I am creating a costume widget (derived) and I have a problem with setting its properties and the error message is:

(QuitButton:4292): GLib-GObject-WARNING **: 12:40:47.435: g_object_set_is_valid_property: object class 'GtkButton' has no property named 'active_show'

(QuitButton:4292): GLib-GObject-WARNING **: 12:40:47.435: g_object_get_is_valid_property: object class 'GtkButton' has no property named 'active_show'

    The property is (null)

I reduced the code to can be verified:
main.c:

#include <gtk/gtk.h>
#include "quit_button.h"

void load_css ( void );
GtkWidget *createWindow ( const gint width, const gint height );

int main ( void )
{
    GtkWidget *window;
    GtkWidget *quitButton;
    guint get_property;
    /// ***
    gtk_init ( NULL, NULL );
    load_css();
    /// ***
    window = createWindow ( 200, 200 );
    /// ***
    quitButton = quit_button_new ( "Quit" );
    /// ***
    g_object_set( quitButton, "active_show", TRUE,          NULL );
    g_object_get( quitButton, "active_show", &get_property, NULL );
    /// ***
    g_print( "\n\tThe property is %d\n", get_property );
    /// ***
    gtk_container_add ( GTK_CONTAINER ( window ), quitButton );
    /// ***
    gtk_widget_show_all ( window );
    gtk_main ();
}

void load_css ( void )
{
    GtkCssProvider *provider;
    GdkDisplay     *display;
    GdkScreen      *screen;
    /// ***
    const gchar *css_style_file = "style.css";
    GFile *css_fp               = g_file_new_for_path ( css_style_file );
    GError *error               = 0;
    /// ***
    provider = gtk_css_provider_new ();
    display  = gdk_display_get_default ();
    screen   = gdk_display_get_default_screen ( display );
    /// ***
    gtk_style_context_add_provider_for_screen   ( screen, GTK_STYLE_PROVIDER ( provider ), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION );
    gtk_css_provider_load_from_file             ( provider, css_fp, &error );
    /// ***
}

GtkWidget *createWindow ( const gint width, const gint height )
{
    GtkWidget *window;
    window = gtk_window_new         ( GTK_WINDOW_TOPLEVEL );
    g_signal_connect                ( window, "destroy", gtk_main_quit, window );
    gtk_window_set_default_size     ( GTK_WINDOW ( window ), width, height );
    gtk_container_set_border_width  ( GTK_CONTAINER ( window ), 25 );
    return window;
}

quit_button.c:

#include <gtk/gtk.h>
#include "quit_button.h"

#define QUIT_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), QUIT_BUTTON_TYPE, QuitButtonPrivate ) )

typedef struct _QuitButtonPrivate  QuitButtonPrivate;

struct _QuitButtonPrivate
{
    guint visibility : 1;
};

enum
{
    PROP_0,
    PROP_1_ACTIVE,
    LAST_PROP
};

/// ***
static GParamSpec *quit_button_props[LAST_PROP] = { NULL, };
G_DEFINE_TYPE_WITH_CODE ( QuitButton, quit_button, QUIT_BUTTON_TYPE, G_ADD_PRIVATE ( QuitButton ) )

/// ***
void quit_button_init                 ( QuitButton *ipaddress );
void quit_button_class_init           ( QuitButtonClass *klass );
static void quit_button_set_property  ( GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec );
static void quit_button_get_property  ( GObject *object, guint prop_id, GValue *value, GParamSpec *pspec );

/// *** Overriding standard functions,
void quit_button_class_init ( QuitButtonClass *klass )
{
    GObjectClass    *gobject_class = G_OBJECT_CLASS ( klass );
    GtkWidgetClass  *widget_class  = GTK_WIDGET_CLASS ( klass );

    /// *** Override the standard functions set_property and get_property
    gobject_class->set_property = quit_button_set_property;
    gobject_class->get_property = quit_button_get_property;

    /// *** Installing the Properties
    quit_button_props[PROP_1_ACTIVE] = g_param_spec_boolean ( "active_show",
                                                               "Active",
                                                               "The button active State",
                                                               FALSE,
                                                               G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY );

    /// *** Register the GObject propertie
    g_object_class_install_properties ( gobject_class, LAST_PROP, quit_button_props );

    /// *** Set CSS name for CSS File
    gtk_widget_class_set_css_name ( widget_class, "quitbutton");
}

/// Initialize the QuitButton widget.
void quit_button_init ( QuitButton *quitButton )
{
    QuitButtonPrivate *priv = QUIT_BUTTON_GET_PRIVATE ( quitButton );
    /* Set default values */
    priv->visibility = FALSE;
}

/* This function is called when the programmer gives a new value for a widget
 * property with g_object_set(). */
void quit_button_set_property ( GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec )
{
    QuitButton *quitbutton = QUIT_BUTTON ( object );
    switch ( prop_id )
    {
    case PROP_1_ACTIVE:
        quit_button_set_active ( quitbutton, g_value_get_boolean ( value ) );
        break;

    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
        break;
    }
}

/* This function is called when the programmer requests the value of a widget
 * property with g_object_get(). */
void quit_button_get_property ( GObject *object, guint prop_id, GValue *value, GParamSpec *pspec )
{
    QuitButton *qButton     = QUIT_BUTTON ( object );
    QuitButtonPrivate *priv = QUIT_BUTTON_GET_PRIVATE ( qButton );
    switch ( prop_id )
    {
    case PROP_1_ACTIVE:
        g_value_set_boolean (value, priv->visibility);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
        break;
    }
}

/* Create and return a new instance of the QuitButton widget. */
GtkWidget* quit_button_new ( const gchar *label )
{
    return g_object_new (GTK_TYPE_BUTTON, "label", label, NULL);
}


void quit_button_set_active( QuitButton *qButton, gboolean is_active )
{
    QuitButtonPrivate *priv = QUIT_BUTTON_GET_PRIVATE ( qButton );;

    g_return_if_fail (GTK_IS_BUTTON ( qButton ) );

    is_active = ( is_active != FALSE );

    if (priv->visibility != is_active)
    {
        g_signal_emit_by_name ( qButton, "clicked");
        g_object_notify_by_pspec (G_OBJECT ( qButton ), quit_button_props[PROP_1_ACTIVE] );
    }
}

quit_button.h:

 #ifndef QUIT_BUTTON_H_INCLUDED
#define QUIT_BUTTON_H_INCLUDED

G_BEGIN_DECLS

#define QUIT_BUTTON_TYPE            (quit_button_get_type ())
#define QUIT_BUTTON(obj)            (G_TYPE_CHECK_INSTANCE_CAST ( ( obj ),  QUIT_BUTTON_TYPE, QuitButton ) )
#define QUIT_BUTTON_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ( ( klass ),   QUIT_BUTTON_TYPE, QuitButtonClass ) )
#define IS_QUIT_BUTTON(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ( ( obj ),  QUIT_BUTTON_TYPE))
#define IS_QUIT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ( ( klass ),   QUIT_BUTTON_TYPE))

typedef struct _QuitButton         QuitButton;
typedef struct _QuitButtonClass    QuitButtonClass;

struct _QuitButton
{
    GtkButton quitbutton;
};

struct _QuitButtonClass
{
    GtkButtonClass parent_class;

    void ( *active_state ) ( QuitButton *ipaddress );
};

GType      quit_button_get_type ( void ) G_GNUC_CONST;
GtkWidget* quit_button_new      ( const gchar *label );
/// ***
void quit_button_set_active( QuitButton *qButton, gboolean is_active );
/// ***
G_END_DECLS

#endif // QUIT_BUTTON_H_INCLUDED

style.css:

quitbutton
{
    background-color: red;
    color:            yellow;
}

From a quick look I can see your constructor is effectively returning a GtkButton (you can infer it also from your error message). I suppose you want to use QUICK_BUTTON_TYPE here instead of GTK_TYPE_BUTTON.

Oh I forgot to mention that.

If I use QUIT_BUTTON_TYPE then compiles fine, with no error, but the window itself it is not printed on the screen anymore.

Any suggestions?

The third parameter to G_DEFINE_TYPE_WITH_CODE() should be the parent type, that is GTK_TYPE_BUTTON.

I changed:

G_DEFINE_TYPE_WITH_CODE ( QuitButton, quit_button, QUIT_BUTTON_TYPE, G_ADD_PRIVATE ( QuitButton ) )

To

G_DEFINE_TYPE_WITH_CODE ( QuitButton, quit_button, GTK_TYPE_BUTTON, G_ADD_PRIVATE ( QuitButton ) )

and I also changed:

return g_object_new (GTK_TYPE_BUTTON, "label", label, NULL); 

To:

return g_object_new ( QUIT_BUTTON_TYPE, "label", label, NULL);

And works fine.

But there is another problem now.
Inside the class_init function if I use this Line:

gtk_widget_class_set_css_name ( widget_class, "quitbutton");

The CSS works, but the button is insensitive.

This means that the way I designed my widget is wrong. Could you please take a closer look at the whole code with the actual changes included?

Can someone please take a closer look to the Code with the actual changes?

I think I am missing some important thing in creating this Widget.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.