GTK GUI with PyGObject (8)

Date: 2021/07/21 (initial publish), 2021/07/25 (last update)

Source: en/note-00021.md

Previous Post Top Next Post

TOC

Example: Multiline Text Editor with GtkSource.View

Next exercise is to create a modal dialog window with Glade similar to Multiline Text Editor

Doing this with the Gtk.TextView widget is not so challenging. I decided to use GtkSource.View instead to gain access to capability of regex and case sensitivity.

I didn’t see GtkSource.View related widgets in the Glade’s available choice list, I first created Multiline Text Editor with Gtk.TextView just to get the general design done. Since we have 2 toplevel widgets, 2 XML files were created by Glade to allow us to use Gtk.Template.

Then I removed Gtk.TextView and Gtk.TextBuffer from Glade and left empty container and wrote code in Python which uses GtkSource.View and attach it to empty container with self.scrollwin.add(self.textview).

In order to get proper response upon exiting from dialog.run(), I enabled Response ID for buttons in modal window using Glade. (It was not so obvious for me.)

Search window with regex and case sensitivity selection

Since this program uses UTF-8 text, this program can handle Japanese and French, too.

The resulting code is long as below but it is relatively easy to reconfigure its graphic components using Glade.

editor.py:

import gi

gi.require_version("Gtk", "3.0")
gi.require_version('GtkSource', '3.0')
from gi.repository import Gtk, Pango, GtkSource


@Gtk.Template(filename="editor-main.ui")
class TextViewWindow(Gtk.Window):
    # corresponding name in XML 'class' attribute for this class
    __gtype_name__ = "main"
    # corresponding name in XML 'id' attribute sets this class member variable
    editable = Gtk.Template.Child()
    invisible = Gtk.Template.Child()
    mono = Gtk.Template.Child()
    one = Gtk.Template.Child()
    char = Gtk.Template.Child()
    word = Gtk.Template.Child()
    left = Gtk.Template.Child()
    center = Gtk.Template.Child()
    right = Gtk.Template.Child()
    fill = Gtk.Template.Child()
    scrollwin = Gtk.Template.Child()

    def __init__(self):
        super().__init__()
        #################################################################################
        # Let's add widgets and buffer not supported by Glade
        # (replacing GtkTextView and GtkTextBuffer)
        #    s/text/source/ later
        #################################################################################
        self.textview = GtkSource.View()
        self.textbuffer = self.textview.get_buffer()
        self.textbuffer.set_text(
            "This is some text inside of a Gtk.SourceView. "
            + "Select text and click one of the buttons 'bold', 'italic', "
            + "or 'underline' to modify the text accordingly.\n\n"
            + "	• This search can be one with case insensitive match.\n"
            + "	• This search can be one with regular expression match.\n\n"
            + "日本国民は、正当に選挙された国会における代表者を通じて行動し、"
            + "われらとわれらの子孫のために、諸国民との協和による成果と、"
            + "わが国全土にわたつて自由のもたらす恵沢を確保し、"
            + "政府の行為によつて再び戦争の惨禍が起ることのないやうにすることを決意し、"
            + "ここに主権が国民に存することを宣言し、この憲法を確定する。"
            + "そもそも国政は、国民の厳粛な信託によるものであつて、その権威は国民に由来し、"
            + "その権力は国民の代表者がこれを行使し、その福利は国民がこれを享受する。"
            + "これは人類普遍の原理であり、この憲法は、かかる原理に基くものである。"
            + "われらは、これに反する一切の憲法、法令及び詔勅を排除する。\n\n"
            + "日本国民は、恒久の平和を念願し、人間相互の関係を支配する崇高な理想を深く自覚するのであつて、"
            + "平和を愛する諸国民の公正と信義に信頼して、われらの安全と生存を保持しようと決意した。"
            + "われらは、平和を維持し、専制と隷従、圧迫と偏狭を地上から永遠に除去しようと努めてゐる国際社会において、"
            + "名誉ある地位を占めたいと思ふ。われらは、全世界の国民が、"
            + "ひとしく恐怖と欠乏から免かれ、平和のうちに生存する権利を有することを確認する。\n\n"
            + "われらは、いづれの国家も、自国のことのみに専念して他国を無視してはならないのであつて、"
            + "政治道徳の法則は、普遍的なものであり、この法則に従ふことは、自国の主権を維持し、"
            + "他国と対等関係に立たうとする各国の責務であると信ずる。\n\n"
            + "日本国民は、国家の名誉にかけ、全力をあげてこの崇高な理想と目的を達成することを誓ふ。\n\n"
            + "« L'Assemblée nationale décrète qu'elle borne quant à présent la Déclaration des droits "
            + "de l'homme et du citoyen aux dix-sept articles qu'elle a arrêtés, et qu'elle va procéder "
            + "sans délai à fixer la Constitution de la France pour assurer la prospérité publique, sauf "
            + "à ajouter après le travail de la Constitution les articles qu'elle croirait nécessaires "
            + "pour compléter la Déclaration des droits. »"
        )
        self.scrollwin.add(self.textview)
        #################################################################################
        self.tag_bold = self.textbuffer.create_tag("bold", weight=Pango.Weight.BOLD)
        self.tag_italic = self.textbuffer.create_tag("italic", style=Pango.Style.ITALIC)
        self.tag_under = self.textbuffer.create_tag(
            "underline", underline=Pango.Underline.SINGLE
        )
        self.tag_found = self.textbuffer.create_tag("found", background="yellow")
        # check Glade XML initial settings and set them so
        if self.editable.get_active():
            self.editable = self.editable.get_active()
            self.textview.set_editable(self.editable)
        if self.invisible.get_active():
            self.invisible = self.invisible.get_active()
            self.textview.set_visible(not self.invisible)
        if self.mono.get_active():
            self.mono = self.mono.get_active()
            self.textview.set_monospace(self.mono)
        if self.one.get_active():
            self.textview.set_wrap_mode(Gtk.WrapMode.NONE)
        if self.char.get_active():
            self.textview.set_wrap_mode(Gtk.WrapMode.CHAR)
        if self.word.get_active():
            self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        if self.left.get_active():
            self.textview.set_justification(Gtk.Justification.LEFT)
        if self.center.get_active():
            self.textview.set_justification(Gtk.Justification.CENTER)
        if self.right.get_active():
            self.textview.set_justification(Gtk.Justification.RIGHT)
        if self.fill.get_active():
            self.textview.set_justification(Gtk.Justification.FILL)

    # common function for callbacks
    def button_apply_tag(self, tag):
        bounds = self.textbuffer.get_selection_bounds()
        if len(bounds) != 0 and self.editable:
            start, end = bounds
            self.textbuffer.apply_tag(tag, start, end)

    @Gtk.Template.Callback()
    def on_bold_clicked(self, widget):
        self.button_apply_tag(self.tag_bold)

    @Gtk.Template.Callback()
    def on_italic_clicked(self, widget):
        self.button_apply_tag(self.tag_italic)

    @Gtk.Template.Callback()
    def on_under_clicked(self, widget):
        self.button_apply_tag(self.tag_under)

    @Gtk.Template.Callback()
    def on_clear_clicked(self, widget):
        start = self.textbuffer.get_start_iter()
        end = self.textbuffer.get_end_iter()
        self.textbuffer.remove_all_tags(start, end)

    @Gtk.Template.Callback()
    def on_editable_toggled(self, widget):
        self.editable = widget.get_active()
        self.textview.set_editable(self.editable)

    @Gtk.Template.Callback()
    def on_invisible_toggled(self, widget):
        self.invisible = widget.get_active()
        self.textview.set_cursor_visible(not self.invisible)

    @Gtk.Template.Callback()
    def on_mono_toggled(self, widget):
        self.mono = widget.get_active()
        self.textview.set_monospace(self.mono)

    @Gtk.Template.Callback()
    def on_one_toggled(self, widget):
        if widget.get_active():
            self.textview.set_wrap_mode(Gtk.WrapMode.NONE)

    @Gtk.Template.Callback()
    def on_char_toggled(self, widget):
        if widget.get_active():
            self.textview.set_wrap_mode(Gtk.WrapMode.CHAR)

    @Gtk.Template.Callback()
    def on_word_toggled(self, widget):
        if widget.get_active():
            self.textview.set_wrap_mode(Gtk.WrapMode.WORD)

    @Gtk.Template.Callback()
    def on_left_toggled(self, widget):
        if widget.get_active():
            self.textview.set_justification(Gtk.Justification.LEFT)

    @Gtk.Template.Callback()
    def on_center_toggled(self, widget):
        if widget.get_active():
            self.textview.set_justification(Gtk.Justification.CENTER)

    @Gtk.Template.Callback()
    def on_right_toggled(self, widget):
        if widget.get_active():
            self.textview.set_justification(Gtk.Justification.RIGHT)

    @Gtk.Template.Callback()
    def on_fill_toggled(self, widget):
        if widget.get_active():
            self.textview.set_justification(Gtk.Justification.FILL)

    @Gtk.Template.Callback()
    def on_search_clicked(self, widget):
        dialog = SearchDialog(self)
        dialog.set_transient_for(self)
        dialog.set_modal(True)
        dialog.show_all()
        # ==== This is important part for *dialog =====
        # Clicking button placed in the particular *dialog makes dialog to
        # exit the event loop while emitting a response signal if the
        # Response ID entry in Glade is activated.
        response = dialog.run()
        search_settings = GtkSource.SearchSettings()
        search_settings.set_case_sensitive(dialog.case_sensitive)
        search_settings.set_regex_enabled(dialog.regex_enabled)
        search_settings.set_search_text(dialog.searchbox.get_text())
        # buffer (GtkSource.Buffer) – a GtkSource.Buffer.
        # settings (GtkSource.SearchSettings or None) – a GtkSource.SearchSettings, or None.
        self.search_context = GtkSource.SearchContext(buffer=self.textbuffer, settings=search_settings)
        if response == Gtk.ResponseType.OK:
            cursor_mark = self.textbuffer.get_insert()
            start = self.textbuffer.get_iter_at_mark(cursor_mark)
            if start.get_offset() == self.textbuffer.get_char_count():
                start = self.textbuffer.get_start_iter()
            self.search_and_mark(start)
        dialog.destroy()

    def search_and_mark(self, start):
        end = self.textbuffer.get_end_iter()
        flag, match_start, match_end, has_wrapped_around = self.search_context.forward2(start)
        if flag:
            self.textbuffer.apply_tag(self.tag_found, match_start, match_end)
            self.search_and_mark(match_end)


@Gtk.Template(filename="editor-search.ui")
class SearchDialog(Gtk.Dialog):
    # corresponding name in XML 'class' attribute for this class
    __gtype_name__ = "search_win"
    # corresponding name in XML 'id' attribute sets this class member variable
    find = Gtk.Template.Child()
    cancel = Gtk.Template.Child()
    label = Gtk.Template.Child()
    searchbox = Gtk.Template.Child()
    nocase = Gtk.Template.Child()
    regex = Gtk.Template.Child()

    def __init__(self, parent):
        super().__init__()
        # initialize from Glade XML settings
        if self.nocase.get_active():
            self.case_sensitive = False
        else:
            self.case_sensitive = True
        if self.regex.get_active():
            self.regex_enabled = False
        else:
            self.regex_enabled = True

    @Gtk.Template.Callback()
    def on_cancel_clicked(self, widget):
        print("I: cancel clicked")

    @Gtk.Template.Callback()
    def on_searchbox_search_changed(self, widget):
        pass

    @Gtk.Template.Callback()
    def on_regex_toggled(self, widget):
        if widget.get_active():
            self.regex_enabled = True
        else:
            self.regex_enabled = False

    @Gtk.Template.Callback()
    def on_nocase_toggled(self, widget):
        if widget.get_active():
            self.case_sensitive = False
        else:
            self.case_sensitive = True


win = TextViewWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

editor-main.ui:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkTextTagTable"/>
  <object class="GtkImage" id="image1">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-text-bold</property>
  </object>
  <object class="GtkImage" id="image2">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-text-italic</property>
  </object>
  <object class="GtkImage" id="image3">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-text-underline</property>
  </object>
  <object class="GtkImage" id="image4">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-justify-left</property>
  </object>
  <object class="GtkImage" id="image5">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-justify-center</property>
  </object>
  <object class="GtkImage" id="image6">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-justify-right</property>
  </object>
  <object class="GtkImage" id="image7">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">format-justify-fill</property>
  </object>
  <object class="GtkImage" id="image8">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">edit-clear-symbolic</property>
  </object>
  <object class="GtkImage" id="image9">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="icon-name">edit-find</property>
  </object>
  <template class="main" parent="GtkWindow">
    <property name="can-focus">False</property>
    <property name="title" translatable="yes">Editor</property>
    <property name="default-width">640</property>
    <property name="default-height">400</property>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <child>
              <object class="GtkButton" id="bold">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image1</property>
                <property name="always-show-image">True</property>
                <signal name="clicked" handler="on_bold_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="italic">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image2</property>
                <property name="always-show-image">True</property>
                <signal name="clicked" handler="on_italic_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="under">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image3</property>
                <property name="always-show-image">True</property>
                <signal name="clicked" handler="on_under_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkSeparator">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">3</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="left">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image4</property>
                <property name="always-show-image">True</property>
                <property name="active">True</property>
                <property name="draw-indicator">False</property>
                <signal name="toggled" handler="on_left_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">4</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="center">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image5</property>
                <property name="always-show-image">True</property>
                <property name="active">True</property>
                <property name="draw-indicator">False</property>
                <property name="group">left</property>
                <signal name="toggled" handler="on_center_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">5</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="right">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image6</property>
                <property name="always-show-image">True</property>
                <property name="active">True</property>
                <property name="draw-indicator">False</property>
                <property name="group">left</property>
                <signal name="toggled" handler="on_right_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">6</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="fill">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image7</property>
                <property name="always-show-image">True</property>
                <property name="active">True</property>
                <property name="draw-indicator">False</property>
                <property name="group">left</property>
                <signal name="toggled" handler="on_fill_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">7</property>
              </packing>
            </child>
            <child>
              <object class="GtkSeparator">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">8</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="clear">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image8</property>
                <property name="always-show-image">True</property>
                <signal name="clicked" handler="on_clear_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">9</property>
              </packing>
            </child>
            <child>
              <object class="GtkSeparator">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">False</property>
                <property name="position">10</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="search">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="image">image9</property>
                <property name="always-show-image">True</property>
                <signal name="clicked" handler="on_search_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">11</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkScrolledWindow" id="scrollwin">
            <property name="visible">True</property>
            <property name="can-focus">True</property>
            <property name="shadow-type">in</property>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <!-- n-columns=3 n-rows=2 -->
          <object class="GtkGrid">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="row-homogeneous">True</property>
            <property name="column-homogeneous">True</property>
            <child>
              <object class="GtkCheckButton" id="editable">
                <property name="label" translatable="yes">Editable</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="active">True</property>
                <property name="draw-indicator">True</property>
                <signal name="toggled" handler="on_editable_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="left-attach">0</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkCheckButton" id="invisible">
                <property name="label" translatable="yes">Invisible</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="draw-indicator">True</property>
                <signal name="toggled" handler="on_invisible_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="left-attach">1</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="one">
                <property name="label" translatable="yes">No wrap</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="active">True</property>
                <property name="draw-indicator">True</property>
                <property name="group">word</property>
                <signal name="toggled" handler="on_one_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="left-attach">0</property>
                <property name="top-attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="char">
                <property name="label" translatable="yes">Char. wrap</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="active">True</property>
                <property name="draw-indicator">True</property>
                <property name="group">word</property>
                <signal name="toggled" handler="on_char_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="left-attach">1</property>
                <property name="top-attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkRadioButton" id="word">
                <property name="label" translatable="yes">Word wrap</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="active">True</property>
                <property name="draw-indicator">True</property>
                <signal name="toggled" handler="on_word_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="left-attach">2</property>
                <property name="top-attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkCheckButton" id="mono">
                <property name="label" translatable="yes">Mono</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="draw-indicator">True</property>
                <signal name="toggled" handler="on_mono_toggled" swapped="no"/>
              </object>
              <packing>
                <property name="left-attach">2</property>
                <property name="top-attach">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
      </object>
    </child>
  </template>
</interface>

editor-search.ui:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <template class="search_win" parent="GtkDialog">
    <property name="can-focus">False</property>
    <property name="title" translatable="yes">Search</property>
    <property name="type-hint">dialog</property>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">2</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can-focus">False</property>
            <property name="layout-style">end</property>
            <child>
              <object class="GtkButton" id="find">
                <property name="label" translatable="yes">Find All Matches</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="cancel">
                <property name="label" translatable="yes">Cancel Search</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <signal name="clicked" handler="on_cancel_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="label" translatable="yes">Input search word.</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkSearchEntry" id="searchbox">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="primary-icon-name">edit-find-symbolic</property>
                <property name="primary-icon-activatable">False</property>
                <property name="primary-icon-sensitive">False</property>
                <signal name="search-changed" handler="on_searchbox_search_changed" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="search_opt">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="homogeneous">True</property>
                <child>
                  <object class="GtkCheckButton" id="nocase">
                    <property name="label" translatable="yes">Ignore case</property>
                    <property name="visible">True</property>
                    <property name="can-focus">True</property>
                    <property name="receives-default">False</property>
                    <property name="draw-indicator">True</property>
                    <signal name="toggled" handler="on_nocase_toggled" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkCheckButton" id="regex">
                    <property name="label" translatable="yes">Regular expr.</property>
                    <property name="visible">True</property>
                    <property name="can-focus">True</property>
                    <property name="receives-default">False</property>
                    <property name="draw-indicator">True</property>
                    <signal name="toggled" handler="on_regex_toggled" swapped="no"/>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <action-widgets>
      <action-widget response="-5">find</action-widget>
      <action-widget response="-6">cancel</action-widget>
    </action-widgets>
  </template>
</interface>

Previous Post Top Next Post