gtkvalagenie

Revealing and hiding search entry - Gtk


Background

This is part of an exercise, in which I am creating a small text editor in genie. The app so far is working very well.

Aim

I got stuck in creating a search entry box that is revealed upon clicking in a search button at the headerbar.

Code

init
    Gtk.init (ref args)

    var app = new Application ()
    app.show_all ()
    Gtk.main ()

// This class holds all the elements from the GUI
class Application : Gtk.Window

    _view:Gtk.TextView
    _filename:string
    _search_button:Gtk.Button
    _search_entry:Gtk.SearchEntry
    _search_entry_revealer:Gtk.Revealer
    _search_button_revealer:Gtk.Revealer
    _search_visible:bool = false

    construct ()

        // Prepare Gtk.Window:
        this.window_position = Gtk.WindowPosition.CENTER
        this.destroy.connect (Gtk.main_quit)
        this.set_default_size (400, 400)


        // Headerbar definition
        headerbar:Gtk.HeaderBar = new Gtk.HeaderBar()
        headerbar.show_close_button = true
        headerbar.set_title("My text editor")

        // Headerbar buttons
        open_button:Gtk.ToolButton = new ToolButton.from_stock(Stock.OPEN)
        open_button.clicked.connect (openfile)

        new_button:Gtk.ToolButton = new ToolButton.from_stock(Stock.NEW)
        new_button.clicked.connect (createNew)

        save_button:Gtk.ToolButton = new ToolButton.from_stock(Stock.SAVE)
        save_button.clicked.connect (saveFile)

        var search_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
        _search_entry:Gtk.SearchEntry = new Gtk.SearchEntry();
        _search_entry.editable = true;
        _search_entry.visibility = true;
        _search_entry.expand = true;
        _search_entry.max_width_chars = 30;
        _search_entry.margin_right = 12;

        _search_entry_revealer:Gtk.Revealer = new Gtk.Revealer();
        _search_button_revealer:Gtk.Revealer = new Gtk.Revealer();
        _search_entry_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT;
        _search_button_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT;

        _search_button:Gtk.Button = new Gtk.Button.from_icon_name ("edit-find-symbolic", Gtk.IconSize.LARGE_TOOLBAR)
        _search_button.has_tooltip = true
        _search_button.tooltip_text = "Search your current notebook"
        _search_button.clicked.connect(show_search)

        _search_button_revealer.add(_search_button)
        _search_entry_revealer.add(_search_entry)
        _search_entry_revealer.reveal_child = false
        _search_button_revealer.reveal_child = true

        // Add everything to the toolbar
        headerbar.pack_start (save_button)
        headerbar.pack_start (open_button)
        headerbar.pack_start (new_button)
        search_box.add (_search_button_revealer)
        search_box.add (_search_entry_revealer)
        headerbar.pack_end (search_box)

        show_all ()
        this.set_titlebar(headerbar)

        // Box:
        box:Gtk.Box = new Gtk.Box (Gtk.Orientation.VERTICAL, 1)
        this.add (box)

        // A ScrolledWindow:
        scrolled:Gtk.ScrolledWindow = new Gtk.ScrolledWindow (null, null)
        box.pack_start (scrolled, true, true, 0)

        // The TextView:
        _view = new Gtk.TextView ()
        _view.set_wrap_mode (Gtk.WrapMode.WORD)
        _view.buffer.text = "Lorem Ipsum"
        scrolled.add (_view)


    def show_search()
        _search_button_revealer.reveal_child = false
        _search_entry_revealer.reveal_child = true
        show_all()
        _search_visible = true
        _search_entry.can_focus = true
        _search_entry.grab_focus()

Problem

My approach was to create a little function (show_search) in order to implement the revealing/hiding of the search entry. The program compiles OK, but I get errors at execution time:

(text_editor-exercise_7_1:9732): Gtk-CRITICAL **: gtk_revealer_set_reveal_child: assertion 'GTK_IS_REVEALER (revealer)' failed

(text_editor-exercise_7_1:9732): Gtk-CRITICAL **: gtk_revealer_set_reveal_child: assertion 'GTK_IS_REVEALER (revealer)' failed

(text_editor-exercise_7_1:9732): GLib-GObject-CRITICAL **: g_object_set: assertion 'G_IS_OBJECT (object)' failed

(text_editor-exercise_7_1:9732): Gtk-CRITICAL **: gtk_widget_grab_focus: assertion 'GTK_IS_WIDGET (widget)' failed

These happens when I click the search button. Can someone point me to my error in this code? What is this error complaining about? GTK_IS_WIDGET assertion failed?


Solution

  • I extracted the problematic part of your code:

    class Application : Gtk.Window
    
        _search_entry_revealer:Gtk.Revealer
        _search_button_revealer:Gtk.Revealer
    
        construct ()
            _search_entry_revealer:Gtk.Revealer = new Gtk.Revealer();
            _search_button_revealer:Gtk.Revealer = new Gtk.Revealer();
    
        def show_search()
            _search_button_revealer.reveal_child = false
            _search_entry_revealer.reveal_child = true
    

    You are declaring two attributes of type Gtk.Revealer in your class.

    You then declare two local variables of type Gtk.Revealer in your construct method.

    Therefore the attributes are never set to any value.

    The access to the attributes then yields the errors you are getting.

    The solution is simple, you have to leave the type out of the assignments in the construct method in order to not declare local variables, but to use the attributes (as you probably intended) instead:

    class Application : Gtk.Window
    
        _search_entry_revealer:Gtk.Revealer
        _search_button_revealer:Gtk.Revealer
    
        construct ()
            // No type annotation here, so no local variables are declared
            _search_entry_revealer = new Gtk.Revealer();
            _search_button_revealer = new Gtk.Revealer();
    
        def show_search()
            _search_button_revealer.reveal_child = false
            _search_entry_revealer.reveal_child = true