mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-12 20:03:28 +01:00
7b14d03a24
Update the distribution package information.
863 lines
68 KiB
HTML
863 lines
68 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="generator" content="pandoc" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
|
||
<title>GTK 4 tutorial</title>
|
||
<style>
|
||
code{white-space: pre-wrap;}
|
||
span.smallcaps{font-variant: small-caps;}
|
||
span.underline{text-decoration: underline;}
|
||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||
ul.task-list{list-style: none;}
|
||
pre{overflow: visible;}
|
||
pre > code.sourceCode { white-space: pre; position: relative; }
|
||
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||
div.sourceCode { margin: 1em 0; }
|
||
pre.sourceCode { margin: 0; }
|
||
@media screen {
|
||
div.sourceCode { overflow: auto; }
|
||
}
|
||
@media print {
|
||
pre > code.sourceCode { white-space: pre-wrap; }
|
||
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||
}
|
||
pre.numberSource code
|
||
{ counter-reset: source-line 0; }
|
||
pre.numberSource code > span
|
||
{ position: relative; left: -4em; counter-increment: source-line; }
|
||
pre.numberSource code > span > a:first-child::after
|
||
{ content: counter(source-line);
|
||
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||
border: none; display: inline-block;
|
||
-webkit-touch-callout: none; -webkit-user-select: none;
|
||
-khtml-user-select: none; -moz-user-select: none;
|
||
-ms-user-select: none; user-select: none;
|
||
padding: 0 4px; width: 4em;
|
||
color: #aaaaaa;
|
||
}
|
||
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
||
div.sourceCode
|
||
{ }
|
||
@media screen {
|
||
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||
}
|
||
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
||
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||
code span.at { color: #7d9029; } /* Attribute */
|
||
code span.bn { color: #40a070; } /* BaseN */
|
||
code span.bu { } /* BuiltIn */
|
||
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
||
code span.ch { color: #4070a0; } /* Char */
|
||
code span.cn { color: #880000; } /* Constant */
|
||
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
||
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||
code span.dt { color: #902000; } /* DataType */
|
||
code span.dv { color: #40a070; } /* DecVal */
|
||
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
||
code span.ex { } /* Extension */
|
||
code span.fl { color: #40a070; } /* Float */
|
||
code span.fu { color: #06287e; } /* Function */
|
||
code span.im { } /* Import */
|
||
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
||
code span.op { color: #666666; } /* Operator */
|
||
code span.ot { color: #007020; } /* Other */
|
||
code span.pp { color: #bc7a00; } /* Preprocessor */
|
||
code span.sc { color: #4070a0; } /* SpecialChar */
|
||
code span.ss { color: #bb6688; } /* SpecialString */
|
||
code span.st { color: #4070a0; } /* String */
|
||
code span.va { color: #19177c; } /* Variable */
|
||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||
div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
|
||
pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
|
||
table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
|
||
th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
|
||
td {padding: 2px 6px; border: 1px solid;}
|
||
img {display: block; margin-left: auto; margin-right: auto;}
|
||
figcaption {text-align: center;}
|
||
</style>
|
||
</head>
|
||
<body style="padding-top: 70px;">
|
||
<div class="container">
|
||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
|
||
<div class="container-fluid">
|
||
<span class="navbar-brand">Gtk4 tutorial</span>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="index.html">Home</a>
|
||
</li>
|
||
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="sec20.html">Prev: section20</a>
|
||
</li>
|
||
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="sec22.html">Next: section22</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
<div class="row justify-content-center">
|
||
<div class="col-xl-10 col-xxl-9">
|
||
<h1 id="gtkfontdialogbutton-and-gsettings">GtkFontDialogButton and
|
||
Gsettings</h1>
|
||
<h2 id="the-preference-dialog">The preference dialog</h2>
|
||
<p>If the user clicks on the preference menu, a preference dialog
|
||
appears.</p>
|
||
<figure>
|
||
<img src="image/pref_dialog.png" alt="Preference dialog" />
|
||
<figcaption aria-hidden="true">Preference dialog</figcaption>
|
||
</figure>
|
||
<p>It has only one button, which is a GtkFontDialogButton widget. You
|
||
can add more widgets on the dialog but this simple dialog isn’t so bad
|
||
for the first example program.</p>
|
||
<p>If the button is clicked, a FontDialog appears like this.</p>
|
||
<figure>
|
||
<img src="image/fontdialog.png" alt="Font dialog" />
|
||
<figcaption aria-hidden="true">Font dialog</figcaption>
|
||
</figure>
|
||
<p>If the user chooses a font and clicks on the select button, the font
|
||
is changed.</p>
|
||
<p>GtkFontDialogButton and GtkFontDialog are available since GTK version
|
||
4.10. They replace GtkFontButton and GtkFontChooserDialog, which are
|
||
deprecated since 4.10.</p>
|
||
<h2 id="a-composite-widget">A composite widget</h2>
|
||
<p>The preference dialog has GtkBox, GtkLabel and GtkFontButton in it
|
||
and is defined as a composite widget. The following is the template ui
|
||
file for TfePref.</p>
|
||
<div class="sourceCode" id="cb1"><pre
|
||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb1-1"><a href="#cb1-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
||
<span id="cb1-2"><a href="#cb1-2"></a><<span class="kw">interface</span>></span>
|
||
<span id="cb1-3"><a href="#cb1-3"></a> <<span class="kw">template</span><span class="ot"> class=</span><span class="st">"TfePref"</span><span class="ot"> parent=</span><span class="st">"GtkWindow"</span>></span>
|
||
<span id="cb1-4"><a href="#cb1-4"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"title"</span>>Preferences</<span class="kw">property</span>></span>
|
||
<span id="cb1-5"><a href="#cb1-5"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"resizable"</span>>FALSE</<span class="kw">property</span>></span>
|
||
<span id="cb1-6"><a href="#cb1-6"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"modal"</span>>TRUE</<span class="kw">property</span>></span>
|
||
<span id="cb1-7"><a href="#cb1-7"></a> <<span class="kw">child</span>></span>
|
||
<span id="cb1-8"><a href="#cb1-8"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkBox"</span>></span>
|
||
<span id="cb1-9"><a href="#cb1-9"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"orientation"</span>>GTK_ORIENTATION_HORIZONTAL</<span class="kw">property</span>></span>
|
||
<span id="cb1-10"><a href="#cb1-10"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"spacing"</span>>12</<span class="kw">property</span>></span>
|
||
<span id="cb1-11"><a href="#cb1-11"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"halign"</span>>GTK_ALIGN_CENTER</<span class="kw">property</span>></span>
|
||
<span id="cb1-12"><a href="#cb1-12"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"margin-start"</span>>12</<span class="kw">property</span>></span>
|
||
<span id="cb1-13"><a href="#cb1-13"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"margin-end"</span>>12</<span class="kw">property</span>></span>
|
||
<span id="cb1-14"><a href="#cb1-14"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"margin-top"</span>>12</<span class="kw">property</span>></span>
|
||
<span id="cb1-15"><a href="#cb1-15"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"margin-bottom"</span>>12</<span class="kw">property</span>></span>
|
||
<span id="cb1-16"><a href="#cb1-16"></a> <<span class="kw">child</span>></span>
|
||
<span id="cb1-17"><a href="#cb1-17"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkLabel"</span>></span>
|
||
<span id="cb1-18"><a href="#cb1-18"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"label"</span>>Font:</<span class="kw">property</span>></span>
|
||
<span id="cb1-19"><a href="#cb1-19"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"xalign"</span>>1</<span class="kw">property</span>></span>
|
||
<span id="cb1-20"><a href="#cb1-20"></a> </<span class="kw">object</span>></span>
|
||
<span id="cb1-21"><a href="#cb1-21"></a> </<span class="kw">child</span>></span>
|
||
<span id="cb1-22"><a href="#cb1-22"></a> <<span class="kw">child</span>></span>
|
||
<span id="cb1-23"><a href="#cb1-23"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkFontDialogButton"</span><span class="ot"> id=</span><span class="st">"font_dialog_btn"</span>></span>
|
||
<span id="cb1-24"><a href="#cb1-24"></a> <<span class="kw">property</span><span class="ot"> name=</span><span class="st">"dialog"</span>></span>
|
||
<span id="cb1-25"><a href="#cb1-25"></a> <<span class="kw">object</span><span class="ot"> class=</span><span class="st">"GtkFontDialog"</span>/></span>
|
||
<span id="cb1-26"><a href="#cb1-26"></a> </<span class="kw">property</span>></span>
|
||
<span id="cb1-27"><a href="#cb1-27"></a> </<span class="kw">object</span>></span>
|
||
<span id="cb1-28"><a href="#cb1-28"></a> </<span class="kw">child</span>></span>
|
||
<span id="cb1-29"><a href="#cb1-29"></a> </<span class="kw">object</span>></span>
|
||
<span id="cb1-30"><a href="#cb1-30"></a> </<span class="kw">child</span>></span>
|
||
<span id="cb1-31"><a href="#cb1-31"></a> </<span class="kw">template</span>></span>
|
||
<span id="cb1-32"><a href="#cb1-32"></a></<span class="kw">interface</span>></span></code></pre></div>
|
||
<ul>
|
||
<li>Template tag specifies a composite widget. The class attribute
|
||
specifies the class name, which is “TfePref”. The parent attribute is
|
||
<code>GtkWindow</code>. Therefore. <code>TfePref</code> is a child class
|
||
of <code>GtkWindow</code>. A parent attribute is optional but it is
|
||
recommended to write it explicitly. You can make TfePref as a child of
|
||
<code>GtkDialog</code>, but <code>GtkDialog</code> is deprecated since
|
||
version 4.10.</li>
|
||
<li>There are three properties, title, resizable and modal.</li>
|
||
<li>TfePref has a child widget GtkBox which is horizontal. The box has
|
||
two children GtkLabel and GtkFontDialogButton.</li>
|
||
</ul>
|
||
<h2 id="the-header-file">The header file</h2>
|
||
<p>The file <code>tfepref.h</code> defines types and declares a public
|
||
function.</p>
|
||
<div class="sourceCode" id="cb2"><pre
|
||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#pragma once</span></span>
|
||
<span id="cb2-2"><a href="#cb2-2"></a></span>
|
||
<span id="cb2-3"><a href="#cb2-3"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||
<span id="cb2-4"><a href="#cb2-4"></a></span>
|
||
<span id="cb2-5"><a href="#cb2-5"></a><span class="pp">#define TFE_TYPE_PREF tfe_pref_get_type ()</span></span>
|
||
<span id="cb2-6"><a href="#cb2-6"></a>G_DECLARE_FINAL_TYPE <span class="op">(</span>TfePref<span class="op">,</span> tfe_pref<span class="op">,</span> TFE<span class="op">,</span> PREF<span class="op">,</span> GtkWindow<span class="op">)</span></span>
|
||
<span id="cb2-7"><a href="#cb2-7"></a></span>
|
||
<span id="cb2-8"><a href="#cb2-8"></a>GtkWidget <span class="op">*</span></span>
|
||
<span id="cb2-9"><a href="#cb2-9"></a>tfe_pref_new <span class="op">(</span><span class="dt">void</span><span class="op">);</span></span></code></pre></div>
|
||
<ul>
|
||
<li>5: Defines the type <code>TFE_TYPE_PREF</code>, which is a macro
|
||
replaced by <code>tfe_pref_get_type ()</code>.</li>
|
||
<li>6: The macro <code>G_DECLAER_FINAL_TYPE</code> expands to:
|
||
<ul>
|
||
<li>The function <code>tfe_pref_get_type ()</code> is declared.</li>
|
||
<li>TfePrep type is defined as a typedef of
|
||
<code>struct _TfePrep</code>.</li>
|
||
<li>TfePrepClass type is defined as a typedef of
|
||
<code>struct {GtkWindowClass *parent;}</code>.</li>
|
||
<li>Two functions <code>TFE_PREF ()</code> and
|
||
<code>TFE_IS_PREF ()</code> is defined.</li>
|
||
</ul></li>
|
||
<li>8-9:The function <code>tfe_pref_new</code> is declared. It creates a
|
||
new TfePref instance.</li>
|
||
</ul>
|
||
<h2 id="the-c-file-for-composite-widget">The C file for composite
|
||
widget</h2>
|
||
<p>The following codes are extracted from the file
|
||
<code>tfepref.c</code>.</p>
|
||
<div class="sourceCode" id="cb3"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"tfepref.h"</span></span>
|
||
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> _TfePref</span>
|
||
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
|
||
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> GtkWindow parent<span class="op">;</span></span>
|
||
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> GtkFontDialogButton <span class="op">*</span>font_dialog_btn<span class="op">;</span></span>
|
||
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
|
||
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>G_DEFINE_FINAL_TYPE <span class="op">(</span>TfePref<span class="op">,</span> tfe_pref<span class="op">,</span> GTK_TYPE_WINDOW<span class="op">);</span></span>
|
||
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>tfe_pref_dispose <span class="op">(</span>GObject <span class="op">*</span>gobject<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a> TfePref <span class="op">*</span>pref <span class="op">=</span> TFE_PREF <span class="op">(</span>gobject<span class="op">);</span></span>
|
||
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a> gtk_widget_dispose_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>pref<span class="op">),</span> TFE_TYPE_PREF<span class="op">);</span></span>
|
||
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a> G_OBJECT_CLASS <span class="op">(</span>tfe_pref_parent_class<span class="op">)-></span>dispose <span class="op">(</span>gobject<span class="op">);</span></span>
|
||
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>tfe_pref_init <span class="op">(</span>TfePref <span class="op">*</span>pref<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a> gtk_widget_init_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>pref<span class="op">));</span></span>
|
||
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>tfe_pref_class_init <span class="op">(</span>TfePrefClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a> G_OBJECT_CLASS <span class="op">(</span>class<span class="op">)-></span>dispose <span class="op">=</span> tfe_pref_dispose<span class="op">;</span></span>
|
||
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a> gtk_widget_class_set_template_from_resource <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> <span class="st">"/com/github/ToshioCP/tfe/tfepref.ui"</span><span class="op">);</span></span>
|
||
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfePref<span class="op">,</span> font_dialog_btn<span class="op">);</span></span>
|
||
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
|
||
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>GtkWidget <span class="op">*</span></span>
|
||
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>tfe_pref_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_PREF<span class="op">,</span> NULL<span class="op">));</span></span>
|
||
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||
<ul>
|
||
<li>The structure <code>_TfePref</code> has <code>font_dialog_btn</code>
|
||
member. It points the GtkFontDialogButton object specified in the XML
|
||
file “tfepref.ui”. The member name <code>font_dialog_btn</code> must be
|
||
the same as the GtkFontDialogButton id attribute in the XML file.</li>
|
||
<li><code>G_DEFINE_FINAL_TYPE</code> macro expands to:
|
||
<ul>
|
||
<li>The declaration of the functions <code>tfe_pref_init</code> and
|
||
<code>tfe_pref_class_init</code>. They are defined in the following part
|
||
of the program.</li>
|
||
<li>The definition of the variable
|
||
<code>tfe_pref_parent_class</code>.</li>
|
||
<li>The definition of the function <code>tfe_pref_get_type</code>.</li>
|
||
</ul></li>
|
||
<li>The function <code>tfe_pref_class_init</code> initializes the
|
||
TfePref class. The function
|
||
<code>gtk_widget_class_set_template_from_resource</code> initializes the
|
||
composite widget template from the XML resource. The function
|
||
<code>gtk_widget_class_bind_template_child</code> connects the TfePref
|
||
structure member <code>font_dialog_btn</code> and the
|
||
GtkFontDialogButton in the XML. The member name and the id attribute
|
||
value must be the same.</li>
|
||
<li>The function <code>tfe_pref_init</code> initializes a newly created
|
||
instance. The function <code>gtk_widget_init_template</code> creates and
|
||
initializes child widgets.</li>
|
||
<li>The function <code>tfe_pref_dispose</code> releases objects. The
|
||
function <code>gtk_widget_dispose_template</code> releases child
|
||
widgets.</li>
|
||
</ul>
|
||
<h2 id="gtkfontdialogbutton-and-pango">GtkFontDialogButton and
|
||
Pango</h2>
|
||
<p>If the GtkFontDialogButton button is clicked, the GtkFontDialog
|
||
dialog appears. A user can choose a font on the dialog. If the user
|
||
clicks on the “select” button, the dialog disappears. And the font
|
||
information is given to the GtkFontDialogButton instance. The font data
|
||
is taken with the method
|
||
<code>gtk_font_dialog_button_get_font_desc</code>. It returns a pointer
|
||
to the PangoFontDescription structure.</p>
|
||
<p>Pango is a text layout engine. The <a
|
||
href="https://docs.gtk.org/Pango/index.html">documentation</a> is on the
|
||
internet.</p>
|
||
<p>PangoFontDescription is a C structure and it isn’t allowed to access
|
||
directly. The document is <a
|
||
href="https://docs.gtk.org/Pango/struct.FontDescription.html">here</a>.
|
||
If you want to retrieve the font information, there are several
|
||
functions.</p>
|
||
<ul>
|
||
<li><code>pango_font_description_to_string</code> returns a string like
|
||
“Jamrul Bold Italic Semi-Expanded 12”.</li>
|
||
<li><code>pango_font_description_get_family</code> returns a font family
|
||
like “Jamrul”.</li>
|
||
<li><code>pango_font_description_get_weight</code> returns a PangoWeight
|
||
constant like <code>PANGO_WEIGHT_BOLD</code>.</li>
|
||
<li><code>pango_font_description_get_style</code> returns a PangoStyle
|
||
constant like <code>PANGO_STYLE_ITALIC</code>.</li>
|
||
<li><code>pango_font_description_get_stretch</code> returns a
|
||
PangoStretch constant like
|
||
<code>PANGO_STRETCH_SEMI_EXPANDED</code>.</li>
|
||
<li><code>pango_font_description_get_size</code> returns an integer like
|
||
<code>12</code>. Its unit is point or pixel (device unit). The function
|
||
<code>pango_font_description_get_size_is_absolute</code> returns TRUE if
|
||
the unit is absolute that means device unit. Otherwise the unit is
|
||
point.</li>
|
||
</ul>
|
||
<h2 id="gsettings">GSettings</h2>
|
||
<p>We want to maintain the font data after the application quits. There
|
||
are some ways to implement.</p>
|
||
<ul>
|
||
<li>Make a configuration file. For example, a text file
|
||
“~/.config/tfe/font_desc.cfg” keeps font information.</li>
|
||
<li>Use GSettings object. The basic idea of GSettings are similar to
|
||
configuration file. Configuration information data is put into a
|
||
database file.</li>
|
||
</ul>
|
||
<p>GSettings is simple and easy to use but a bit hard to understand the
|
||
concept. This subsection describes the concept first and then how to
|
||
program it.</p>
|
||
<h3 id="gsettings-schema">GSettings schema</h3>
|
||
<p>GSettings schema describes a set of keys, value types and some other
|
||
information. GSettings object uses this schema and it writes/reads the
|
||
value of a key to/from the right place in the database.</p>
|
||
<ul>
|
||
<li>A schema has an id. The id must be unique. We often use the same
|
||
string as application id, but schema id and application id are
|
||
different. You can use different name from application id. Schema id is
|
||
a string delimited by periods. For example, “com.github.ToshioCP.tfe” is
|
||
a correct schema id.</li>
|
||
<li>A schema usually has a path. The path is a location in the database.
|
||
Each key is stored under the path. For example, if a key
|
||
<code>font-desc</code> is defined with a path
|
||
<code>/com/github/ToshioCP/tfe/</code>, the key’s location in the
|
||
database is <code>/com/github/ToshioCP/tfe/font-desc</code>. Path is a
|
||
string begins with and ends with a slash (<code>/</code>). And it is
|
||
delimited by slashes.</li>
|
||
<li>GSettings save information as key-value style. Key is a string
|
||
begins with a lower case character followed by lower case, digit or dash
|
||
(<code>-</code>) and ends with lower case or digit. No consecutive
|
||
dashes are allowed. Values can be any type. GSettings stores values as
|
||
GVariant type, which can be, for example, integer, double, boolean,
|
||
string or complex types like an array. The type of values needs to be
|
||
defined in the schema.</li>
|
||
<li>A default value needs to be set for each key.</li>
|
||
<li>A summery and description can be set for each key optionally.</li>
|
||
</ul>
|
||
<p>Schemas are described in an XML format. For example,</p>
|
||
<div class="sourceCode" id="cb4"><pre
|
||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb4-1"><a href="#cb4-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
||
<span id="cb4-2"><a href="#cb4-2"></a><<span class="kw">schemalist</span>></span>
|
||
<span id="cb4-3"><a href="#cb4-3"></a> <<span class="kw">schema</span><span class="ot"> path=</span><span class="st">"/com/github/ToshioCP/tfe/"</span><span class="ot"> id=</span><span class="st">"com.github.ToshioCP.tfe"</span>></span>
|
||
<span id="cb4-4"><a href="#cb4-4"></a> <<span class="kw">key</span><span class="ot"> name=</span><span class="st">"font-desc"</span><span class="ot"> type=</span><span class="st">"s"</span>></span>
|
||
<span id="cb4-5"><a href="#cb4-5"></a> <<span class="kw">default</span>>'Monospace 12'</<span class="kw">default</span>></span>
|
||
<span id="cb4-6"><a href="#cb4-6"></a> <<span class="kw">summary</span>>Font</<span class="kw">summary</span>></span>
|
||
<span id="cb4-7"><a href="#cb4-7"></a> <<span class="kw">description</span>>A font to be used for textview.</<span class="kw">description</span>></span>
|
||
<span id="cb4-8"><a href="#cb4-8"></a> </<span class="kw">key</span>></span>
|
||
<span id="cb4-9"><a href="#cb4-9"></a> </<span class="kw">schema</span>></span>
|
||
<span id="cb4-10"><a href="#cb4-10"></a></<span class="kw">schemalist</span>></span></code></pre></div>
|
||
<ul>
|
||
<li>4: The type attribute is “s”. It is GVariant type string. For
|
||
GVariant type string, see <a
|
||
href="https://docs.gtk.org/glib/struct.VariantType.html#gvariant-type-strings">GLib
|
||
API Reference – GVariant Type Strings</a>. Other common types are:
|
||
<ul>
|
||
<li>“b”: gboolean</li>
|
||
<li>“i”: gint32.</li>
|
||
<li>“d”: double.</li>
|
||
</ul></li>
|
||
</ul>
|
||
<p>Further information is in:</p>
|
||
<ul>
|
||
<li><a
|
||
href="https://docs.gtk.org/glib/gvariant-format-strings.html">GLib API
|
||
Reference – GVariant Format Strings</a></li>
|
||
<li><a href="https://docs.gtk.org/glib/gvariant-text.html">GLib API
|
||
Reference – GVariant Text Format</a></li>
|
||
<li><a href="https://docs.gtk.org/glib/struct.Variant.html">GLib API
|
||
Reference – GVariant</a></li>
|
||
<li><a href="https://docs.gtk.org/glib/struct.VariantType.html">GLib API
|
||
Reference – VariantType</a></li>
|
||
</ul>
|
||
<h3 id="gsettings-command">Gsettings command</h3>
|
||
<p>First, let’s try <code>gsettings</code> application. It is a
|
||
configuration tool for GSettings.</p>
|
||
<pre><code>$ gsettings help
|
||
Usage:
|
||
gsettings --version
|
||
gsettings [--schemadir SCHEMADIR] COMMAND [ARGS?]
|
||
|
||
Commands:
|
||
help Show this information
|
||
list-schemas List installed schemas
|
||
list-relocatable-schemas List relocatable schemas
|
||
list-keys List keys in a schema
|
||
list-children List children of a schema
|
||
list-recursively List keys and values, recursively
|
||
range Queries the range of a key
|
||
describe Queries the description of a key
|
||
get Get the value of a key
|
||
set Set the value of a key
|
||
reset Reset the value of a key
|
||
reset-recursively Reset all values in a given schema
|
||
writable Check if a key is writable
|
||
monitor Watch for changes
|
||
|
||
Use "gsettings help COMMAND" to get detailed help.</code></pre>
|
||
<p>List schemas.</p>
|
||
<pre><code>$ gsettings list-schemas
|
||
org.gnome.rhythmbox.podcast
|
||
ca.desrt.dconf-editor.Demo.Empty
|
||
org.gnome.gedit.preferences.ui
|
||
org.gnome.evolution-data-server.calendar
|
||
org.gnome.rhythmbox.plugins.generic-player
|
||
|
||
... ...
|
||
</code></pre>
|
||
<p>Each line is an id of a schema. Each schema has a key-value
|
||
configuration data. You can see them with list-recursively command.
|
||
Let’s look at the keys and values of <code>org.gnome.calculator</code>
|
||
schema.</p>
|
||
<pre><code>$ gsettings list-recursively org.gnome.calculator
|
||
org.gnome.calculator accuracy 9
|
||
org.gnome.calculator angle-units 'degrees'
|
||
org.gnome.calculator base 10
|
||
org.gnome.calculator button-mode 'basic'
|
||
org.gnome.calculator number-format 'automatic'
|
||
org.gnome.calculator precision 2000
|
||
org.gnome.calculator refresh-interval 604800
|
||
org.gnome.calculator show-thousands false
|
||
org.gnome.calculator show-zeroes false
|
||
org.gnome.calculator source-currency ''
|
||
org.gnome.calculator source-units 'degree'
|
||
org.gnome.calculator target-currency ''
|
||
org.gnome.calculator target-units 'radian'
|
||
org.gnome.calculator window-position (-1, -1)
|
||
org.gnome.calculator word-size 64</code></pre>
|
||
<p>This schema is used by GNOME Calculator. Run the calculator and
|
||
change the mode, then check the schema again.</p>
|
||
<pre><code>$ gnome-calculator</code></pre>
|
||
<figure>
|
||
<img src="image/gnome_calculator_basic.png"
|
||
alt="gnome-calculator basic mode" />
|
||
<figcaption aria-hidden="true">gnome-calculator basic mode</figcaption>
|
||
</figure>
|
||
<p>Change the mode to advanced and quit.</p>
|
||
<figure>
|
||
<img src="image/gnome_calculator_advanced.png"
|
||
alt="gnome-calculator advanced mode" />
|
||
<figcaption aria-hidden="true">gnome-calculator advanced
|
||
mode</figcaption>
|
||
</figure>
|
||
<p>Run gsettings and check the value of <code>button-mode</code>.</p>
|
||
<pre><code>$ gsettings list-recursively org.gnome.calculator
|
||
|
||
... ...
|
||
|
||
org.gnome.calculator button-mode 'advanced'
|
||
|
||
... ...
|
||
</code></pre>
|
||
<p>Now we know that GNOME Calculator used gsettings and it has set
|
||
<code>button-mode</code> key to “advanced”. The value remains even the
|
||
calculator quits. So when the calculator runs again, it will appear as
|
||
an advanced mode.</p>
|
||
<h3 id="glib-compile-schemas-utility">Glib-compile-schemas utility</h3>
|
||
<p>GSettings schemas are specified with an XML format. The XML schema
|
||
files must have the filename extension <code>.gschema.xml</code>. The
|
||
following is the XML schema file for the application
|
||
<code>tfe</code>.</p>
|
||
<div class="sourceCode" id="cb10"><pre
|
||
class="sourceCode numberSource xml numberLines"><code class="sourceCode xml"><span id="cb10-1"><a href="#cb10-1"></a><span class="fu"><?xml</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> encoding=</span><span class="st">"UTF-8"</span><span class="fu">?></span></span>
|
||
<span id="cb10-2"><a href="#cb10-2"></a><<span class="kw">schemalist</span>></span>
|
||
<span id="cb10-3"><a href="#cb10-3"></a> <<span class="kw">schema</span><span class="ot"> path=</span><span class="st">"/com/github/ToshioCP/tfe/"</span><span class="ot"> id=</span><span class="st">"com.github.ToshioCP.tfe"</span>></span>
|
||
<span id="cb10-4"><a href="#cb10-4"></a> <<span class="kw">key</span><span class="ot"> name=</span><span class="st">"font-desc"</span><span class="ot"> type=</span><span class="st">"s"</span>></span>
|
||
<span id="cb10-5"><a href="#cb10-5"></a> <<span class="kw">default</span>>'Monospace 12'</<span class="kw">default</span>></span>
|
||
<span id="cb10-6"><a href="#cb10-6"></a> <<span class="kw">summary</span>>Font</<span class="kw">summary</span>></span>
|
||
<span id="cb10-7"><a href="#cb10-7"></a> <<span class="kw">description</span>>A font to be used for textview.</<span class="kw">description</span>></span>
|
||
<span id="cb10-8"><a href="#cb10-8"></a> </<span class="kw">key</span>></span>
|
||
<span id="cb10-9"><a href="#cb10-9"></a> </<span class="kw">schema</span>></span>
|
||
<span id="cb10-10"><a href="#cb10-10"></a></<span class="kw">schemalist</span>></span></code></pre></div>
|
||
<p>The filename is “com.github.ToshioCP.tfe.gschema.xml”. Schema XML
|
||
filenames are usually the schema id followed by “.gschema.xml” suffix.
|
||
You can use different name from schema id, but it is not
|
||
recommended.</p>
|
||
<ul>
|
||
<li>2: The top level element is <code><schemalist></code>.</li>
|
||
<li>3: schema tag has <code>path</code> and <code>id</code> attributes.
|
||
A path determines where the settings are stored in the conceptual global
|
||
tree of settings. An id identifies the schema.</li>
|
||
<li>4: Key tag has two attributes. Name is the name of the key. Type is
|
||
the type of the value of the key and it is a GVariant Format
|
||
String.</li>
|
||
<li>5: default value of the key <code>font-desc</code> is
|
||
<code>Monospace 12</code>.</li>
|
||
<li>6: Summery and description elements describes the key. They are
|
||
optional, but it is recommended to add them in the XML file.</li>
|
||
</ul>
|
||
<p>The XML file is compiled by glib-compile-schemas. When compiling,
|
||
<code>glib-compile-schemas</code> compiles all the XML files which have
|
||
“.gschema.xml” file extension in the directory given as an argument. It
|
||
converts the XML file into a binary file <code>gschemas.compiled</code>.
|
||
Suppose the XML file above is under <code>tfe6</code> directory.</p>
|
||
<pre><code>$ glib-compile-schemas tfe6</code></pre>
|
||
<p>Then, <code>gschemas.compiled</code> is generated under
|
||
<code>tfe6</code>. When you test your application, set
|
||
<code>GSETTINGS_SCHEMA_DIR</code> environment variable so that GSettings
|
||
objet can find <code>gschemas.compiled</code>.</p>
|
||
<pre><code>$ GSETTINGS_SCHEMA_DIR=(the directory gschemas.compiled is located):$GSETTINGS_SCHEMA_DIR (your application name)</code></pre>
|
||
<p>GSettings object looks for this file by the following process.</p>
|
||
<ul>
|
||
<li>It searches <code>glib-2.0/schemas</code> subdirectories of all the
|
||
directories specified in the environment variable
|
||
<code>XDG_DATA_DIRS</code>. Common directores are
|
||
<code>/usr/share/glib-2.0/schemas</code> and
|
||
<code>/usr/local/share/glib-2.0/schemas</code>.</li>
|
||
<li>If <code>$HOME/.local/share/glib-2.0/schemas</code> exists, it is
|
||
also searched.</li>
|
||
<li>If <code>GSETTINGS_SCHEMA_DIR</code> environment variable is
|
||
defined, it searches all the directories specified in the variable.
|
||
<code>GSETTINGS_SCHEMA_DIR</code> can specify multiple directories
|
||
delimited by colon (:).</li>
|
||
</ul>
|
||
<p>The directories above includes more than one
|
||
<code>.gschema.xml</code> file. Therefore, when you install your
|
||
application, follow the instruction below to install your schemas.</p>
|
||
<ol type="1">
|
||
<li>Make <code>.gschema.xml</code> file.</li>
|
||
<li>Copy it to one of the directories above. For example,
|
||
<code>$HOME/.local/share/glib-2.0/schemas</code>.</li>
|
||
<li>Run <code>glib-compile-schemas</code> on the directory. It compiles
|
||
all the schema files in the directory and creates or updates the
|
||
database file <code>gschemas.compiled</code>.</li>
|
||
</ol>
|
||
<h3 id="gsettings-object-and-binding">GSettings object and binding</h3>
|
||
<p>Now, we go on to the next topic, how to program GSettings.</p>
|
||
<p>You need to compile your schema file in advance.</p>
|
||
<p>Suppose id, key, class name and a property name are:</p>
|
||
<ul>
|
||
<li>GSettings id: com.github.ToshioCP.sample</li>
|
||
<li>GSettings key: sample_key</li>
|
||
<li>The class name: Sample</li>
|
||
<li>The property to bind: sample_property</li>
|
||
</ul>
|
||
<p>The example below uses <code>g_settings_bind</code>. If you use it,
|
||
GSettings key and instance property must have the same the type. In the
|
||
example, it is assumed that the type of “sample_key” and
|
||
“sample_property” are the same.</p>
|
||
<div class="sourceCode" id="cb13"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>GSettings <span class="op">*</span>settings<span class="op">;</span></span>
|
||
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>Sample <span class="op">*</span>sample_object<span class="op">;</span></span>
|
||
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>settings <span class="op">=</span> g_settings_new <span class="op">(</span><span class="st">"com.github.ToshioCP.sample"</span><span class="op">);</span></span>
|
||
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>sample_object <span class="op">=</span> sample_new <span class="op">();</span></span>
|
||
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>g_settings_bind <span class="op">(</span>settings<span class="op">,</span> <span class="st">"sample_key"</span><span class="op">,</span> sample_object<span class="op">,</span> <span class="st">"sample_property"</span><span class="op">,</span> G_SETTINGS_BIND_DEFAULT<span class="op">);</span></span></code></pre></div>
|
||
<p>The function <code>g_settings_bind</code> binds the GSettings value
|
||
and the property of the instance. If the property value is changed, the
|
||
GSettings value is also changed, and vice versa. The two values are
|
||
always the same.</p>
|
||
<p>The function <code>g_settings_bind</code> is simple and easy but it
|
||
isn’t always possible. The type of GSettings are restricted to the type
|
||
GVariant has. Some property types are out of GVariant. For example,
|
||
GtkFontDialogButton has “font-desc” property and its type is
|
||
PangoFontDescription. PangoFontDescription is a C structure and it is
|
||
wrapped in a boxed type GValue to store in the property. GVariant
|
||
doesn’t support boxed type.</p>
|
||
<p>In that case, another function
|
||
<code>g_settings_bind_with_mapping</code> is used. It binds GSettings
|
||
GVariant value and object property via GValue with mapping
|
||
functions.</p>
|
||
<div class="sourceCode" id="cb14"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span></span>
|
||
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>g_settings_bind_with_mapping <span class="op">(</span></span>
|
||
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> GSettings<span class="op">*</span> settings<span class="op">,</span></span>
|
||
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">const</span> gchar<span class="op">*</span> key<span class="op">,</span></span>
|
||
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a> GObject<span class="op">*</span> object<span class="op">,</span></span>
|
||
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">const</span> gchar<span class="op">*</span> property<span class="op">,</span></span>
|
||
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a> GSettingsBindFlags flags<span class="op">,</span> <span class="co">// G_SETTINGS_BIND_DEFAULT is commonly used</span></span>
|
||
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a> GSettingsBindGetMapping get_mapping<span class="op">,</span> <span class="co">// GSettings => property, See the example below</span></span>
|
||
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> GSettingsBindSetMapping set_mapping<span class="op">,</span> <span class="co">// property => GSettings, See the example below</span></span>
|
||
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a> gpointer user_data<span class="op">,</span> <span class="co">// NULL if unnecessary</span></span>
|
||
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a> GDestroyNotify destroy <span class="co">//NULL if unnecessary</span></span>
|
||
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
||
<p>The mapping functions are defined like these:</p>
|
||
<div class="sourceCode" id="cb15"><pre class="sourceCode C"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>gboolean</span>
|
||
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="op">(*</span> GSettingsBindGetMapping<span class="op">)</span> <span class="op">(</span></span>
|
||
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a> GValue<span class="op">*</span> value<span class="op">,</span></span>
|
||
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a> GVariant<span class="op">*</span> variant<span class="op">,</span></span>
|
||
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a> gpointer user_data</span>
|
||
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span>
|
||
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>GVariant<span class="op">*</span></span>
|
||
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a><span class="op">(*</span> GSettingsBindSetMapping<span class="op">)</span> <span class="op">(</span></span>
|
||
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">const</span> GValue<span class="op">*</span> value<span class="op">,</span></span>
|
||
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">const</span> GVariantType<span class="op">*</span> expected_type<span class="op">,</span></span>
|
||
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a> gpointer user_data</span>
|
||
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="op">)</span></span></code></pre></div>
|
||
<p>The following codes are extracted from <code>tfepref.c</code>.</p>
|
||
<div class="sourceCode" id="cb16"><pre
|
||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb16-1"><a href="#cb16-1"></a><span class="dt">static</span> gboolean <span class="co">// GSettings => property</span></span>
|
||
<span id="cb16-2"><a href="#cb16-2"></a>get_mapping <span class="op">(</span>GValue<span class="op">*</span> value<span class="op">,</span> GVariant<span class="op">*</span> variant<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb16-3"><a href="#cb16-3"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>s <span class="op">=</span> g_variant_get_string <span class="op">(</span>variant<span class="op">,</span> NULL<span class="op">);</span></span>
|
||
<span id="cb16-4"><a href="#cb16-4"></a> PangoFontDescription <span class="op">*</span>font_desc <span class="op">=</span> pango_font_description_from_string <span class="op">(</span>s<span class="op">);</span></span>
|
||
<span id="cb16-5"><a href="#cb16-5"></a> g_value_take_boxed <span class="op">(</span>value<span class="op">,</span> font_desc<span class="op">);</span></span>
|
||
<span id="cb16-6"><a href="#cb16-6"></a> <span class="cf">return</span> TRUE<span class="op">;</span></span>
|
||
<span id="cb16-7"><a href="#cb16-7"></a><span class="op">}</span></span>
|
||
<span id="cb16-8"><a href="#cb16-8"></a></span>
|
||
<span id="cb16-9"><a href="#cb16-9"></a><span class="dt">static</span> GVariant<span class="op">*</span> <span class="co">// Property => GSettings</span></span>
|
||
<span id="cb16-10"><a href="#cb16-10"></a>set_mapping <span class="op">(</span><span class="dt">const</span> GValue<span class="op">*</span> value<span class="op">,</span> <span class="dt">const</span> GVariantType<span class="op">*</span> expected_type<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb16-11"><a href="#cb16-11"></a> <span class="dt">char</span><span class="op">*</span>font_desc_string <span class="op">=</span> pango_font_description_to_string <span class="op">(</span>g_value_get_boxed <span class="op">(</span>value<span class="op">));</span></span>
|
||
<span id="cb16-12"><a href="#cb16-12"></a> <span class="cf">return</span> g_variant_new_take_string <span class="op">(</span>font_desc_string<span class="op">);</span></span>
|
||
<span id="cb16-13"><a href="#cb16-13"></a><span class="op">}</span></span>
|
||
<span id="cb16-14"><a href="#cb16-14"></a></span>
|
||
<span id="cb16-15"><a href="#cb16-15"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb16-16"><a href="#cb16-16"></a>tfe_pref_init <span class="op">(</span>TfePref <span class="op">*</span>pref<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb16-17"><a href="#cb16-17"></a> gtk_widget_init_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>pref<span class="op">));</span></span>
|
||
<span id="cb16-18"><a href="#cb16-18"></a> pref<span class="op">-></span>settings <span class="op">=</span> g_settings_new <span class="op">(</span><span class="st">"com.github.ToshioCP.tfe"</span><span class="op">);</span></span>
|
||
<span id="cb16-19"><a href="#cb16-19"></a> g_settings_bind_with_mapping <span class="op">(</span>pref<span class="op">-></span>settings<span class="op">,</span> <span class="st">"font-desc"</span><span class="op">,</span> pref<span class="op">-></span>font_dialog_btn<span class="op">,</span> <span class="st">"font-desc"</span><span class="op">,</span> G_SETTINGS_BIND_DEFAULT<span class="op">,</span></span>
|
||
<span id="cb16-20"><a href="#cb16-20"></a> get_mapping<span class="op">,</span> set_mapping<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||
<span id="cb16-21"><a href="#cb16-21"></a><span class="op">}</span></span></code></pre></div>
|
||
<ul>
|
||
<li>15-21: This function <code>tfe_pref_init</code> initializes the new
|
||
TfePref instance.</li>
|
||
<li>18: Creates a new GSettings instance. The id is
|
||
“com.github.ToshioCP.tfe”.</li>
|
||
<li>19-20: Binds the GSettings “font-desc” and the GtkFontDialogButton
|
||
property “font-desc”. The mapping functions are <code>get_mapping</code>
|
||
and <code>set_mapping</code>.</li>
|
||
<li>1-7: The mapping function from GSettings to the property. The first
|
||
argument <code>value</code> is a GValue to be stored in the property.
|
||
The second argument <code>variant</code> is a GVarinat structure that
|
||
comes from the GSettings value.</li>
|
||
<li>3: Retrieves a string from the GVariant structure.</li>
|
||
<li>4: Build a PangoFontDescription structure from the string and
|
||
assigns its address to <code>font_desc</code>.</li>
|
||
<li>5: Puts <code>font_desc</code> into the GValue <code>value</code>.
|
||
The ownership of <code>font_desc</code> moves to
|
||
<code>value</code>.</li>
|
||
<li>6: Returns TRUE that means the mapping succeeds.</li>
|
||
<li>9-13: The mapping function from the property to GSettings. The first
|
||
argument <code>value</code> holds the property data. The second argument
|
||
<code>expected_type</code> is the type of GVariant that the GSettings
|
||
value has. It isn’t used in this function.</li>
|
||
<li>11: Gets the PangoFontDescription structure from <code>value</code>
|
||
and converts it to string.</li>
|
||
<li>12: The string is inserted to a GVariant structure. The ownership of
|
||
the string <code>font_desc_string</code> moves to the returned
|
||
value.</li>
|
||
</ul>
|
||
<h2 id="c-file">C file</h2>
|
||
<p>The following is the full codes of <code>tfepref.c</code></p>
|
||
<div class="sourceCode" id="cb17"><pre
|
||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||
<span id="cb17-2"><a href="#cb17-2"></a><span class="pp">#include </span><span class="im">"tfepref.h"</span></span>
|
||
<span id="cb17-3"><a href="#cb17-3"></a></span>
|
||
<span id="cb17-4"><a href="#cb17-4"></a><span class="kw">struct</span> _TfePref</span>
|
||
<span id="cb17-5"><a href="#cb17-5"></a><span class="op">{</span></span>
|
||
<span id="cb17-6"><a href="#cb17-6"></a> GtkWindow parent<span class="op">;</span></span>
|
||
<span id="cb17-7"><a href="#cb17-7"></a> GSettings <span class="op">*</span>settings<span class="op">;</span></span>
|
||
<span id="cb17-8"><a href="#cb17-8"></a> GtkFontDialogButton <span class="op">*</span>font_dialog_btn<span class="op">;</span></span>
|
||
<span id="cb17-9"><a href="#cb17-9"></a><span class="op">};</span></span>
|
||
<span id="cb17-10"><a href="#cb17-10"></a></span>
|
||
<span id="cb17-11"><a href="#cb17-11"></a>G_DEFINE_FINAL_TYPE <span class="op">(</span>TfePref<span class="op">,</span> tfe_pref<span class="op">,</span> GTK_TYPE_WINDOW<span class="op">);</span></span>
|
||
<span id="cb17-12"><a href="#cb17-12"></a></span>
|
||
<span id="cb17-13"><a href="#cb17-13"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb17-14"><a href="#cb17-14"></a>tfe_pref_dispose <span class="op">(</span>GObject <span class="op">*</span>gobject<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb17-15"><a href="#cb17-15"></a> TfePref <span class="op">*</span>pref <span class="op">=</span> TFE_PREF <span class="op">(</span>gobject<span class="op">);</span></span>
|
||
<span id="cb17-16"><a href="#cb17-16"></a></span>
|
||
<span id="cb17-17"><a href="#cb17-17"></a> <span class="co">/* GSetting bindings are automatically removed when the object is finalized, so it isn't necessary to unbind them explicitly.*/</span></span>
|
||
<span id="cb17-18"><a href="#cb17-18"></a> g_clear_object <span class="op">(&</span>pref<span class="op">-></span>settings<span class="op">);</span></span>
|
||
<span id="cb17-19"><a href="#cb17-19"></a> gtk_widget_dispose_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>pref<span class="op">),</span> TFE_TYPE_PREF<span class="op">);</span></span>
|
||
<span id="cb17-20"><a href="#cb17-20"></a> G_OBJECT_CLASS <span class="op">(</span>tfe_pref_parent_class<span class="op">)-></span>dispose <span class="op">(</span>gobject<span class="op">);</span></span>
|
||
<span id="cb17-21"><a href="#cb17-21"></a><span class="op">}</span></span>
|
||
<span id="cb17-22"><a href="#cb17-22"></a></span>
|
||
<span id="cb17-23"><a href="#cb17-23"></a><span class="co">/* ---------- get_mapping/set_mapping ---------- */</span></span>
|
||
<span id="cb17-24"><a href="#cb17-24"></a><span class="dt">static</span> gboolean <span class="co">// GSettings => property</span></span>
|
||
<span id="cb17-25"><a href="#cb17-25"></a>get_mapping <span class="op">(</span>GValue<span class="op">*</span> value<span class="op">,</span> GVariant<span class="op">*</span> variant<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb17-26"><a href="#cb17-26"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>s <span class="op">=</span> g_variant_get_string <span class="op">(</span>variant<span class="op">,</span> NULL<span class="op">);</span></span>
|
||
<span id="cb17-27"><a href="#cb17-27"></a> PangoFontDescription <span class="op">*</span>font_desc <span class="op">=</span> pango_font_description_from_string <span class="op">(</span>s<span class="op">);</span></span>
|
||
<span id="cb17-28"><a href="#cb17-28"></a> g_value_take_boxed <span class="op">(</span>value<span class="op">,</span> font_desc<span class="op">);</span></span>
|
||
<span id="cb17-29"><a href="#cb17-29"></a> <span class="cf">return</span> TRUE<span class="op">;</span></span>
|
||
<span id="cb17-30"><a href="#cb17-30"></a><span class="op">}</span></span>
|
||
<span id="cb17-31"><a href="#cb17-31"></a></span>
|
||
<span id="cb17-32"><a href="#cb17-32"></a><span class="dt">static</span> GVariant<span class="op">*</span> <span class="co">// Property => GSettings</span></span>
|
||
<span id="cb17-33"><a href="#cb17-33"></a>set_mapping <span class="op">(</span><span class="dt">const</span> GValue<span class="op">*</span> value<span class="op">,</span> <span class="dt">const</span> GVariantType<span class="op">*</span> expected_type<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb17-34"><a href="#cb17-34"></a> <span class="dt">char</span><span class="op">*</span>font_desc_string <span class="op">=</span> pango_font_description_to_string <span class="op">(</span>g_value_get_boxed <span class="op">(</span>value<span class="op">));</span></span>
|
||
<span id="cb17-35"><a href="#cb17-35"></a> <span class="cf">return</span> g_variant_new_take_string <span class="op">(</span>font_desc_string<span class="op">);</span></span>
|
||
<span id="cb17-36"><a href="#cb17-36"></a><span class="op">}</span></span>
|
||
<span id="cb17-37"><a href="#cb17-37"></a></span>
|
||
<span id="cb17-38"><a href="#cb17-38"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb17-39"><a href="#cb17-39"></a>tfe_pref_init <span class="op">(</span>TfePref <span class="op">*</span>pref<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb17-40"><a href="#cb17-40"></a> gtk_widget_init_template <span class="op">(</span>GTK_WIDGET <span class="op">(</span>pref<span class="op">));</span></span>
|
||
<span id="cb17-41"><a href="#cb17-41"></a> pref<span class="op">-></span>settings <span class="op">=</span> g_settings_new <span class="op">(</span><span class="st">"com.github.ToshioCP.tfe"</span><span class="op">);</span></span>
|
||
<span id="cb17-42"><a href="#cb17-42"></a> g_settings_bind_with_mapping <span class="op">(</span>pref<span class="op">-></span>settings<span class="op">,</span> <span class="st">"font-desc"</span><span class="op">,</span> pref<span class="op">-></span>font_dialog_btn<span class="op">,</span> <span class="st">"font-desc"</span><span class="op">,</span> G_SETTINGS_BIND_DEFAULT<span class="op">,</span></span>
|
||
<span id="cb17-43"><a href="#cb17-43"></a> get_mapping<span class="op">,</span> set_mapping<span class="op">,</span> NULL<span class="op">,</span> NULL<span class="op">);</span></span>
|
||
<span id="cb17-44"><a href="#cb17-44"></a><span class="op">}</span></span>
|
||
<span id="cb17-45"><a href="#cb17-45"></a></span>
|
||
<span id="cb17-46"><a href="#cb17-46"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb17-47"><a href="#cb17-47"></a>tfe_pref_class_init <span class="op">(</span>TfePrefClass <span class="op">*</span>class<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb17-48"><a href="#cb17-48"></a> G_OBJECT_CLASS <span class="op">(</span>class<span class="op">)-></span>dispose <span class="op">=</span> tfe_pref_dispose<span class="op">;</span></span>
|
||
<span id="cb17-49"><a href="#cb17-49"></a> gtk_widget_class_set_template_from_resource <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> <span class="st">"/com/github/ToshioCP/tfe/tfepref.ui"</span><span class="op">);</span></span>
|
||
<span id="cb17-50"><a href="#cb17-50"></a> gtk_widget_class_bind_template_child <span class="op">(</span>GTK_WIDGET_CLASS <span class="op">(</span>class<span class="op">),</span> TfePref<span class="op">,</span> font_dialog_btn<span class="op">);</span></span>
|
||
<span id="cb17-51"><a href="#cb17-51"></a><span class="op">}</span></span>
|
||
<span id="cb17-52"><a href="#cb17-52"></a></span>
|
||
<span id="cb17-53"><a href="#cb17-53"></a>GtkWidget <span class="op">*</span></span>
|
||
<span id="cb17-54"><a href="#cb17-54"></a>tfe_pref_new <span class="op">(</span><span class="dt">void</span><span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb17-55"><a href="#cb17-55"></a> <span class="cf">return</span> GTK_WIDGET <span class="op">(</span>g_object_new <span class="op">(</span>TFE_TYPE_PREF<span class="op">,</span> NULL<span class="op">));</span></span>
|
||
<span id="cb17-56"><a href="#cb17-56"></a><span class="op">}</span></span></code></pre></div>
|
||
<h2 id="test-program">Test program</h2>
|
||
<p>There’s a test program located at <code>src/tfe6/test</code>
|
||
directory.</p>
|
||
<div class="sourceCode" id="cb18"><pre
|
||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb18-1"><a href="#cb18-1"></a><span class="pp">#include </span><span class="im"><gtk/gtk.h></span></span>
|
||
<span id="cb18-2"><a href="#cb18-2"></a><span class="pp">#include </span><span class="im">"../tfepref.h"</span></span>
|
||
<span id="cb18-3"><a href="#cb18-3"></a></span>
|
||
<span id="cb18-4"><a href="#cb18-4"></a>GSettings <span class="op">*</span>settings<span class="op">;</span></span>
|
||
<span id="cb18-5"><a href="#cb18-5"></a></span>
|
||
<span id="cb18-6"><a href="#cb18-6"></a><span class="co">// "changed::font-desc" signal handler</span></span>
|
||
<span id="cb18-7"><a href="#cb18-7"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb18-8"><a href="#cb18-8"></a>changed_font_desc_cb <span class="op">(</span>GSettings <span class="op">*</span>settings<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>key<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb18-9"><a href="#cb18-9"></a> <span class="dt">char</span> <span class="op">*</span>s<span class="op">;</span></span>
|
||
<span id="cb18-10"><a href="#cb18-10"></a> s <span class="op">=</span> g_settings_get_string <span class="op">(</span>settings<span class="op">,</span> key<span class="op">);</span></span>
|
||
<span id="cb18-11"><a href="#cb18-11"></a> g_print <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> s<span class="op">);</span></span>
|
||
<span id="cb18-12"><a href="#cb18-12"></a> g_free <span class="op">(</span>s<span class="op">);</span></span>
|
||
<span id="cb18-13"><a href="#cb18-13"></a><span class="op">}</span></span>
|
||
<span id="cb18-14"><a href="#cb18-14"></a></span>
|
||
<span id="cb18-15"><a href="#cb18-15"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb18-16"><a href="#cb18-16"></a>app_shutdown <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb18-17"><a href="#cb18-17"></a> g_object_unref <span class="op">(</span>settings<span class="op">);</span></span>
|
||
<span id="cb18-18"><a href="#cb18-18"></a><span class="op">}</span></span>
|
||
<span id="cb18-19"><a href="#cb18-19"></a></span>
|
||
<span id="cb18-20"><a href="#cb18-20"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb18-21"><a href="#cb18-21"></a>app_activate <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb18-22"><a href="#cb18-22"></a> GtkWidget <span class="op">*</span>pref <span class="op">=</span> tfe_pref_new <span class="op">();</span></span>
|
||
<span id="cb18-23"><a href="#cb18-23"></a></span>
|
||
<span id="cb18-24"><a href="#cb18-24"></a> gtk_window_set_application <span class="op">(</span>GTK_WINDOW <span class="op">(</span>pref<span class="op">),</span> GTK_APPLICATION <span class="op">(</span>application<span class="op">));</span></span>
|
||
<span id="cb18-25"><a href="#cb18-25"></a> gtk_window_present <span class="op">(</span>GTK_WINDOW <span class="op">(</span>pref<span class="op">));</span></span>
|
||
<span id="cb18-26"><a href="#cb18-26"></a><span class="op">}</span></span>
|
||
<span id="cb18-27"><a href="#cb18-27"></a></span>
|
||
<span id="cb18-28"><a href="#cb18-28"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||
<span id="cb18-29"><a href="#cb18-29"></a>app_startup <span class="op">(</span>GApplication <span class="op">*</span>application<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb18-30"><a href="#cb18-30"></a> settings <span class="op">=</span> g_settings_new <span class="op">(</span><span class="st">"com.github.ToshioCP.tfe"</span><span class="op">);</span></span>
|
||
<span id="cb18-31"><a href="#cb18-31"></a> g_signal_connect <span class="op">(</span>settings<span class="op">,</span> <span class="st">"changed::font-desc"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>changed_font_desc_cb<span class="op">),</span> NULL<span class="op">);</span></span>
|
||
<span id="cb18-32"><a href="#cb18-32"></a> g_print <span class="op">(</span><span class="st">"%s</span><span class="sc">\n</span><span class="st">"</span><span class="op">,</span> <span class="st">"Change the font with the font button. Then the new font will be printed out.</span><span class="sc">\n</span><span class="st">"</span><span class="op">);</span></span>
|
||
<span id="cb18-33"><a href="#cb18-33"></a><span class="op">}</span></span>
|
||
<span id="cb18-34"><a href="#cb18-34"></a></span>
|
||
<span id="cb18-35"><a href="#cb18-35"></a><span class="pp">#define APPLICATION_ID "com.github.ToshioCP.test_tfe_pref"</span></span>
|
||
<span id="cb18-36"><a href="#cb18-36"></a></span>
|
||
<span id="cb18-37"><a href="#cb18-37"></a><span class="dt">int</span></span>
|
||
<span id="cb18-38"><a href="#cb18-38"></a>main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
|
||
<span id="cb18-39"><a href="#cb18-39"></a> GtkApplication <span class="op">*</span>app<span class="op">;</span></span>
|
||
<span id="cb18-40"><a href="#cb18-40"></a> <span class="dt">int</span> stat<span class="op">;</span></span>
|
||
<span id="cb18-41"><a href="#cb18-41"></a></span>
|
||
<span id="cb18-42"><a href="#cb18-42"></a> app <span class="op">=</span> gtk_application_new <span class="op">(</span>APPLICATION_ID<span class="op">,</span> G_APPLICATION_DEFAULT_FLAGS<span class="op">);</span></span>
|
||
<span id="cb18-43"><a href="#cb18-43"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"startup"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_startup<span class="op">),</span> NULL<span class="op">);</span></span>
|
||
<span id="cb18-44"><a href="#cb18-44"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"activate"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_activate<span class="op">),</span> NULL<span class="op">);</span></span>
|
||
<span id="cb18-45"><a href="#cb18-45"></a> g_signal_connect <span class="op">(</span>app<span class="op">,</span> <span class="st">"shutdown"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>app_shutdown<span class="op">),</span> NULL<span class="op">);</span></span>
|
||
<span id="cb18-46"><a href="#cb18-46"></a> stat <span class="op">=</span>g_application_run <span class="op">(</span>G_APPLICATION <span class="op">(</span>app<span class="op">),</span> argc<span class="op">,</span> argv<span class="op">);</span></span>
|
||
<span id="cb18-47"><a href="#cb18-47"></a> g_object_unref <span class="op">(</span>app<span class="op">);</span></span>
|
||
<span id="cb18-48"><a href="#cb18-48"></a> <span class="cf">return</span> stat<span class="op">;</span></span>
|
||
<span id="cb18-49"><a href="#cb18-49"></a><span class="op">}</span></span></code></pre></div>
|
||
<p>This program sets its active window to TfePref instance, which is a
|
||
child object of GtkWindow.</p>
|
||
<p>It sets the “changed::font-desc” signal handler in the startup
|
||
function. The process from the user’s font selection to the handler
|
||
is:</p>
|
||
<ul>
|
||
<li>The user clicked on the GtkFontDialogButton and GtkFontDialog
|
||
appears.</li>
|
||
<li>He/she selects a new font.</li>
|
||
<li>The “font-desc” property of the GtkFontDialogButton instance is
|
||
changed.</li>
|
||
<li>The value of “font-desc” key on the GSettings database is changed
|
||
since it is bound to the property.</li>
|
||
<li>The “changed::font-desc” signal on the GSettings instance is
|
||
emitted.</li>
|
||
<li>The handler is called.</li>
|
||
</ul>
|
||
<p>The program building is divided into four steps.</p>
|
||
<ul>
|
||
<li>Compile the schema file</li>
|
||
<li>Compile the XML file to a resource (C source file)</li>
|
||
<li>Compile the C files</li>
|
||
<li>Run the executable file</li>
|
||
</ul>
|
||
<p>Commands are shown in the next four sub-subsections. You don’t need
|
||
to try them. The final sub-subsection shows the meson-ninja way, which
|
||
is the easiest.</p>
|
||
<h3 id="compile-the-schema-file">Compile the schema file</h3>
|
||
<pre><code>$ cd src/tef6/test
|
||
$ cp ../com.github.ToshioCP.tfe.gschema.xml com.github.ToshioCP.tfe.gschema.xml
|
||
$ glib-compile-schemas .</code></pre>
|
||
<p>Be careful. The commands <code>glib-compile-schemas</code> has an
|
||
argument “.”, which means the current directory. This results in
|
||
creating <code>gschemas.compiled</code> file.</p>
|
||
<h3 id="compile-the-xml-file">Compile the XML file</h3>
|
||
<pre><code>$ glib-compile-resources --sourcedir=.. --generate-source --target=resource.c ../tfe.gresource.xml</code></pre>
|
||
<h3 id="compile-the-c-file">Compile the C file</h3>
|
||
<pre><code>$ gcc `pkg-config --cflags gtk4` test_pref.c ../tfepref.c resource.c `pkg-config --libs gtk4`</code></pre>
|
||
<h3 id="run-the-executable-file">Run the executable file</h3>
|
||
<pre><code>$ GSETTINGS_SCHEMA_DIR=. ./a.out
|
||
|
||
Jamrul Italic Semi-Expanded 12 # <= select Jamrul Italic 12
|
||
Monospace 12 #<= select Monospace Regular 12</code></pre>
|
||
<h3 id="meson-ninja-way">Meson-ninja way</h3>
|
||
<p>Meson wraps up the commands above. Create the following text and save
|
||
it to <code>meson.build</code>.</p>
|
||
<p>Note: Gtk4-tutorial repository has meson.build file that defines
|
||
several tests. So you can try it instead of the following text.</p>
|
||
<pre><code>project('tfe_pref_test', 'c')
|
||
|
||
gtkdep = dependency('gtk4')
|
||
|
||
gnome=import('gnome')
|
||
resources = gnome.compile_resources('resources','../tfe.gresource.xml', source_dir: '..')
|
||
gnome.compile_schemas(build_by_default: true, depend_files: 'com.github.ToshioCP.tfe.gschema.xml')
|
||
|
||
executable('test_pref', ['test_pref.c', '../tfepref.c'], resources, dependencies: gtkdep, export_dynamic: true, install: false)</code></pre>
|
||
<ul>
|
||
<li>Project name is ‘tfe_pref_test’ and it is written in C
|
||
language.</li>
|
||
<li>It depends on GTK4 library.</li>
|
||
<li>It uses GNOME module. Modules are prepared by Meson.</li>
|
||
<li>GNOME module has <code>compile_resources</code> method. When you
|
||
call this method, you need the prefix “gnome.”.
|
||
<ul>
|
||
<li>The target filename is resources.</li>
|
||
<li>The definition XML file is ‘../tfe.gresource.xml’.</li>
|
||
<li>The source dir is ‘..’. All the ui files are located there.</li>
|
||
</ul></li>
|
||
<li>GNOME module has <code>compile_schemas</code> method. It compiles
|
||
the schema file ‘com.github.ToshioCP.tfe.gschema.xml’. You need to copy
|
||
‘../com.github.ToshioCP.tfe.gschema.xml’ to the current directory in
|
||
advance.</li>
|
||
<li>It creates an executable file ‘test_pref’. The source files are
|
||
‘test_pref.c’, ‘../tfepref.c’ and <code>resources</code>, which is made
|
||
by <code>gnome.compile_resources</code>. It depends on
|
||
<code>gtkdep</code>, which is GTK4 library. The symbols are exported and
|
||
no installation support.</li>
|
||
</ul>
|
||
<p>Type like this to build and test the program.</p>
|
||
<pre><code>$ cd src/tef6/test
|
||
$ cp ../com.github.ToshioCP.tfe.gschema.xml com.github.ToshioCP.tfe.gschema.xml
|
||
$ meson setup _build
|
||
$ ninja -C _build
|
||
$ GSETTINGS_SCHEMA_DIR=_build _build/test_pref</code></pre>
|
||
<p>A window appears and you can choose a font via GtkFontDialog. If you
|
||
select a new font, the font string is output through the standard
|
||
output.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||
</body>
|
||
</html>
|