Gtk4-tutorial/docs/sec29.html
2022-04-24 12:13:40 +09:00

513 lines
52 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Gtk4 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="sec28.html">Prev: section28</a>
</li>
</ul>
</div>
</div>
</nav>
<h1 id="gtkcolumnview">GtkColumnView</h1>
<h2 id="gtkcolumnview-1">GtkColumnView</h2>
<p>GtkColumnView is like GtkListView, but it has multiple columns. Each column is GtkColumnViewColumn.</p>
<figure>
<img src="image/column_view.png" alt="" /><figcaption>Column View</figcaption>
</figure>
<ul>
<li>GtkColumnView has “model” property. The property points a GtkSelectionModel object.</li>
<li>Each GtkColumnViewColumn has “factory” property. The property points a GtkListItemFactory (GtkSignalListItemFactory or GtkBuilderListItemFactory).</li>
<li>The factory connects GtkListItem, which belongs to GtkColumnViewColumn, and items of GtkSelectionModel. And the factory builds the descendants widgets of GtkColumnView to display the item on the display. This process is the same as the one in GtkListView.</li>
</ul>
<p>The following diagram shows the image how it works.</p>
<figure>
<img src="image/column.png" alt="" /><figcaption>ColumnView</figcaption>
</figure>
<p>The example in this section is a window that displays information of files in a current directory. The information is the name, size and last modified datetime of files. So, there are three columns.</p>
<p>In addition, the example uses GtkSortListModel and GtkSorter to sort the information.</p>
<h2 id="column.ui">column.ui</h2>
<p>Ui file specifies whole widgets and their structure.</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="kw">&lt;?xml</span> version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;<span class="kw">?&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">&lt;interface&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkApplicationWindow&quot;</span><span class="ot"> id=</span><span class="st">&quot;win&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-4"><a href="#cb1-4"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span><span class="kw">&gt;</span>file list<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-5"><a href="#cb1-5"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;default-width&quot;</span><span class="kw">&gt;</span>800<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-6"><a href="#cb1-6"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;default-height&quot;</span><span class="kw">&gt;</span>600<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-7"><a href="#cb1-7"></a> <span class="kw">&lt;child&gt;</span></span>
<span id="cb1-8"><a href="#cb1-8"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkScrolledWindow&quot;</span><span class="ot"> id=</span><span class="st">&quot;scr&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;hexpand&quot;</span><span class="kw">&gt;</span>TRUE<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-10"><a href="#cb1-10"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;vexpand&quot;</span><span class="kw">&gt;</span>TRUE<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-11"><a href="#cb1-11"></a> <span class="kw">&lt;child&gt;</span></span>
<span id="cb1-12"><a href="#cb1-12"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkColumnView&quot;</span><span class="ot"> id=</span><span class="st">&quot;columnview&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-13"><a href="#cb1-13"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-14"><a href="#cb1-14"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkSingleSelection&quot;</span><span class="ot"> id=</span><span class="st">&quot;singleselection&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-15"><a href="#cb1-15"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-16"><a href="#cb1-16"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkSortListModel&quot;</span><span class="ot"> id=</span><span class="st">&quot;sortlist&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-17"><a href="#cb1-17"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-18"><a href="#cb1-18"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkDirectoryList&quot;</span><span class="ot"> id=</span><span class="st">&quot;directorylist&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-19"><a href="#cb1-19"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;attributes&quot;</span><span class="kw">&gt;</span>standard::name,standard::icon,standard::size,time::modified<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-20"><a href="#cb1-20"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-21"><a href="#cb1-21"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-22"><a href="#cb1-22"></a> <span class="kw">&lt;binding</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-23"><a href="#cb1-23"></a> <span class="kw">&lt;lookup</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span>columnview<span class="kw">&lt;/lookup&gt;</span></span>
<span id="cb1-24"><a href="#cb1-24"></a> <span class="kw">&lt;/binding&gt;</span></span>
<span id="cb1-25"><a href="#cb1-25"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-26"><a href="#cb1-26"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-27"><a href="#cb1-27"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-28"><a href="#cb1-28"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-29"><a href="#cb1-29"></a> <span class="kw">&lt;child&gt;</span></span>
<span id="cb1-30"><a href="#cb1-30"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkColumnViewColumn&quot;</span><span class="ot"> id=</span><span class="st">&quot;column1&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-31"><a href="#cb1-31"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span><span class="kw">&gt;</span>Name<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-32"><a href="#cb1-32"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expand&quot;</span><span class="kw">&gt;</span>TRUE<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-33"><a href="#cb1-33"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;factory&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-34"><a href="#cb1-34"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkBuilderListItemFactory&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-35"><a href="#cb1-35"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;bytes&quot;</span><span class="kw">&gt;</span><span class="bn">&lt;![CDATA[</span></span>
<span id="cb1-36"><a href="#cb1-36"></a>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span id="cb1-37"><a href="#cb1-37"></a>&lt;interface&gt;</span>
<span id="cb1-38"><a href="#cb1-38"></a> &lt;template class=&quot;GtkListItem&quot;&gt;</span>
<span id="cb1-39"><a href="#cb1-39"></a> &lt;property name=&quot;child&quot;&gt;</span>
<span id="cb1-40"><a href="#cb1-40"></a> &lt;object class=&quot;GtkBox&quot;&gt;</span>
<span id="cb1-41"><a href="#cb1-41"></a> &lt;property name=&quot;orientation&quot;&gt;GTK_ORIENTATION_HORIZONTAL&lt;/property&gt;</span>
<span id="cb1-42"><a href="#cb1-42"></a> &lt;property name=&quot;spacing&quot;&gt;20&lt;/property&gt;</span>
<span id="cb1-43"><a href="#cb1-43"></a> &lt;child&gt;</span>
<span id="cb1-44"><a href="#cb1-44"></a> &lt;object class=&quot;GtkImage&quot;&gt;</span>
<span id="cb1-45"><a href="#cb1-45"></a> &lt;binding name=&quot;gicon&quot;&gt;</span>
<span id="cb1-46"><a href="#cb1-46"></a> &lt;closure type=&quot;GIcon&quot; function=&quot;get_icon_factory&quot;&gt;</span>
<span id="cb1-47"><a href="#cb1-47"></a> &lt;lookup name=&quot;item&quot;&gt;GtkListItem&lt;/lookup&gt;</span>
<span id="cb1-48"><a href="#cb1-48"></a> &lt;/closure&gt;</span>
<span id="cb1-49"><a href="#cb1-49"></a> &lt;/binding&gt;</span>
<span id="cb1-50"><a href="#cb1-50"></a> &lt;/object&gt;</span>
<span id="cb1-51"><a href="#cb1-51"></a> &lt;/child&gt;</span>
<span id="cb1-52"><a href="#cb1-52"></a> &lt;child&gt;</span>
<span id="cb1-53"><a href="#cb1-53"></a> &lt;object class=&quot;GtkLabel&quot;&gt;</span>
<span id="cb1-54"><a href="#cb1-54"></a> &lt;property name=&quot;hexpand&quot;&gt;TRUE&lt;/property&gt;</span>
<span id="cb1-55"><a href="#cb1-55"></a> &lt;property name=&quot;xalign&quot;&gt;0&lt;/property&gt;</span>
<span id="cb1-56"><a href="#cb1-56"></a> &lt;binding name=&quot;label&quot;&gt;</span>
<span id="cb1-57"><a href="#cb1-57"></a> &lt;closure type=&quot;gchararray&quot; function=&quot;get_file_name_factory&quot;&gt;</span>
<span id="cb1-58"><a href="#cb1-58"></a> &lt;lookup name=&quot;item&quot;&gt;GtkListItem&lt;/lookup&gt;</span>
<span id="cb1-59"><a href="#cb1-59"></a> &lt;/closure&gt;</span>
<span id="cb1-60"><a href="#cb1-60"></a> &lt;/binding&gt;</span>
<span id="cb1-61"><a href="#cb1-61"></a> &lt;/object&gt;</span>
<span id="cb1-62"><a href="#cb1-62"></a> &lt;/child&gt;</span>
<span id="cb1-63"><a href="#cb1-63"></a> &lt;/object&gt;</span>
<span id="cb1-64"><a href="#cb1-64"></a> &lt;/property&gt;</span>
<span id="cb1-65"><a href="#cb1-65"></a> &lt;/template&gt;</span>
<span id="cb1-66"><a href="#cb1-66"></a>&lt;/interface&gt;</span>
<span id="cb1-67"><a href="#cb1-67"></a> <span class="bn">]]&gt;</span><span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-68"><a href="#cb1-68"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-69"><a href="#cb1-69"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-70"><a href="#cb1-70"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-71"><a href="#cb1-71"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkStringSorter&quot;</span><span class="ot"> id=</span><span class="st">&quot;sorter_name&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-72"><a href="#cb1-72"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expression&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-73"><a href="#cb1-73"></a> <span class="kw">&lt;closure</span><span class="ot"> type=</span><span class="st">&quot;gchararray&quot;</span><span class="ot"> function=</span><span class="st">&quot;get_file_name&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-74"><a href="#cb1-74"></a> <span class="kw">&lt;/closure&gt;</span></span>
<span id="cb1-75"><a href="#cb1-75"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-76"><a href="#cb1-76"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-77"><a href="#cb1-77"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-78"><a href="#cb1-78"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-79"><a href="#cb1-79"></a> <span class="kw">&lt;/child&gt;</span></span>
<span id="cb1-80"><a href="#cb1-80"></a> <span class="kw">&lt;child&gt;</span></span>
<span id="cb1-81"><a href="#cb1-81"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkColumnViewColumn&quot;</span><span class="ot"> id=</span><span class="st">&quot;column2&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-82"><a href="#cb1-82"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span><span class="kw">&gt;</span>Size<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-83"><a href="#cb1-83"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;factory&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-84"><a href="#cb1-84"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkBuilderListItemFactory&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-85"><a href="#cb1-85"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;bytes&quot;</span><span class="kw">&gt;</span><span class="bn">&lt;![CDATA[</span></span>
<span id="cb1-86"><a href="#cb1-86"></a>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span id="cb1-87"><a href="#cb1-87"></a>&lt;interface&gt;</span>
<span id="cb1-88"><a href="#cb1-88"></a> &lt;template class=&quot;GtkListItem&quot;&gt;</span>
<span id="cb1-89"><a href="#cb1-89"></a> &lt;property name=&quot;child&quot;&gt;</span>
<span id="cb1-90"><a href="#cb1-90"></a> &lt;object class=&quot;GtkLabel&quot;&gt;</span>
<span id="cb1-91"><a href="#cb1-91"></a> &lt;property name=&quot;hexpand&quot;&gt;TRUE&lt;/property&gt;</span>
<span id="cb1-92"><a href="#cb1-92"></a> &lt;property name=&quot;xalign&quot;&gt;0&lt;/property&gt;</span>
<span id="cb1-93"><a href="#cb1-93"></a> &lt;binding name=&quot;label&quot;&gt;</span>
<span id="cb1-94"><a href="#cb1-94"></a> &lt;closure type=&quot;gchararray&quot; function=&quot;get_file_size_factory&quot;&gt;</span>
<span id="cb1-95"><a href="#cb1-95"></a> &lt;lookup name=&quot;item&quot;&gt;GtkListItem&lt;/lookup&gt;</span>
<span id="cb1-96"><a href="#cb1-96"></a> &lt;/closure&gt;</span>
<span id="cb1-97"><a href="#cb1-97"></a> &lt;/binding&gt;</span>
<span id="cb1-98"><a href="#cb1-98"></a> &lt;/object&gt;</span>
<span id="cb1-99"><a href="#cb1-99"></a> &lt;/property&gt;</span>
<span id="cb1-100"><a href="#cb1-100"></a> &lt;/template&gt;</span>
<span id="cb1-101"><a href="#cb1-101"></a>&lt;/interface&gt;</span>
<span id="cb1-102"><a href="#cb1-102"></a> <span class="bn">]]&gt;</span><span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-103"><a href="#cb1-103"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-104"><a href="#cb1-104"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-105"><a href="#cb1-105"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-106"><a href="#cb1-106"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkNumericSorter&quot;</span><span class="ot"> id=</span><span class="st">&quot;sorter_size&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-107"><a href="#cb1-107"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expression&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-108"><a href="#cb1-108"></a> <span class="kw">&lt;closure</span><span class="ot"> type=</span><span class="st">&quot;gint64&quot;</span><span class="ot"> function=</span><span class="st">&quot;get_file_size&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-109"><a href="#cb1-109"></a> <span class="kw">&lt;/closure&gt;</span></span>
<span id="cb1-110"><a href="#cb1-110"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-111"><a href="#cb1-111"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sort-order&quot;</span><span class="kw">&gt;</span>GTK_SORT_ASCENDING<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-112"><a href="#cb1-112"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-113"><a href="#cb1-113"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-114"><a href="#cb1-114"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-115"><a href="#cb1-115"></a> <span class="kw">&lt;/child&gt;</span></span>
<span id="cb1-116"><a href="#cb1-116"></a> <span class="kw">&lt;child&gt;</span></span>
<span id="cb1-117"><a href="#cb1-117"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkColumnViewColumn&quot;</span><span class="ot"> id=</span><span class="st">&quot;column3&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-118"><a href="#cb1-118"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;title&quot;</span><span class="kw">&gt;</span>Date modified<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-119"><a href="#cb1-119"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;factory&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-120"><a href="#cb1-120"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkBuilderListItemFactory&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-121"><a href="#cb1-121"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;bytes&quot;</span><span class="kw">&gt;</span><span class="bn">&lt;![CDATA[</span></span>
<span id="cb1-122"><a href="#cb1-122"></a>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span id="cb1-123"><a href="#cb1-123"></a>&lt;interface&gt;</span>
<span id="cb1-124"><a href="#cb1-124"></a> &lt;template class=&quot;GtkListItem&quot;&gt;</span>
<span id="cb1-125"><a href="#cb1-125"></a> &lt;property name=&quot;child&quot;&gt;</span>
<span id="cb1-126"><a href="#cb1-126"></a> &lt;object class=&quot;GtkLabel&quot;&gt;</span>
<span id="cb1-127"><a href="#cb1-127"></a> &lt;property name=&quot;hexpand&quot;&gt;TRUE&lt;/property&gt;</span>
<span id="cb1-128"><a href="#cb1-128"></a> &lt;property name=&quot;xalign&quot;&gt;0&lt;/property&gt;</span>
<span id="cb1-129"><a href="#cb1-129"></a> &lt;binding name=&quot;label&quot;&gt;</span>
<span id="cb1-130"><a href="#cb1-130"></a> &lt;closure type=&quot;gchararray&quot; function=&quot;get_file_time_modified_factory&quot;&gt;</span>
<span id="cb1-131"><a href="#cb1-131"></a> &lt;lookup name=&quot;item&quot;&gt;GtkListItem&lt;/lookup&gt;</span>
<span id="cb1-132"><a href="#cb1-132"></a> &lt;/closure&gt;</span>
<span id="cb1-133"><a href="#cb1-133"></a> &lt;/binding&gt;</span>
<span id="cb1-134"><a href="#cb1-134"></a> &lt;/object&gt;</span>
<span id="cb1-135"><a href="#cb1-135"></a> &lt;/property&gt;</span>
<span id="cb1-136"><a href="#cb1-136"></a> &lt;/template&gt;</span>
<span id="cb1-137"><a href="#cb1-137"></a>&lt;/interface&gt;</span>
<span id="cb1-138"><a href="#cb1-138"></a> <span class="bn">]]&gt;</span><span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-139"><a href="#cb1-139"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-140"><a href="#cb1-140"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-141"><a href="#cb1-141"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-142"><a href="#cb1-142"></a> <span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkNumericSorter&quot;</span><span class="ot"> id=</span><span class="st">&quot;sorter_datetime_modified&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-143"><a href="#cb1-143"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expression&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-144"><a href="#cb1-144"></a> <span class="kw">&lt;closure</span><span class="ot"> type=</span><span class="st">&quot;gint64&quot;</span><span class="ot"> function=</span><span class="st">&quot;get_file_unixtime_modified&quot;</span><span class="kw">&gt;</span></span>
<span id="cb1-145"><a href="#cb1-145"></a> <span class="kw">&lt;/closure&gt;</span></span>
<span id="cb1-146"><a href="#cb1-146"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-147"><a href="#cb1-147"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sort-order&quot;</span><span class="kw">&gt;</span>GTK_SORT_ASCENDING<span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-148"><a href="#cb1-148"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-149"><a href="#cb1-149"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb1-150"><a href="#cb1-150"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-151"><a href="#cb1-151"></a> <span class="kw">&lt;/child&gt;</span></span>
<span id="cb1-152"><a href="#cb1-152"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-153"><a href="#cb1-153"></a> <span class="kw">&lt;/child&gt;</span></span>
<span id="cb1-154"><a href="#cb1-154"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-155"><a href="#cb1-155"></a> <span class="kw">&lt;/child&gt;</span></span>
<span id="cb1-156"><a href="#cb1-156"></a> <span class="kw">&lt;/object&gt;</span></span>
<span id="cb1-157"><a href="#cb1-157"></a><span class="kw">&lt;/interface&gt;</span></span></code></pre></div>
<ul>
<li>3-12: Widget parent-child relationship is GtkApplicationWindow =&gt; GtkScrolledWindow =&gt; GtkColumnView.</li>
<li>12-18: GtkColumnView has “model” property. It points GtkSelectionModel interface. In this ui file, GtkSingleSelection is used as GtkSelectionModel. GtkSingleSelection is an object that implements GtkSelectionModel. And again, it has “model” property. It points GtkSortListModel. This list model supports sorting the list. It will be explained in the later subsection. And it also has “model” property. It points GtkDirectoryList. Therefore, the chain is: GtkColumnView =&gt; GtkSingleSelection =&gt; GtkSortListModel =&gt; GtkDirectoryList.</li>
<li>18-20: GtkDirectoryList. It is a list of GFileInfo, which holds information of files under a directory. It has “attributes” property. It specifies what attributes is kept in each GFileInfo.
<ul>
<li>“standard::name” is a name of the file.</li>
<li>“standard::icon” is a GIcon object of the file</li>
<li>“standard::size” is the file size.</li>
<li>“time::modified” is the date and time the file was last modified.</li>
</ul></li>
<li>29-79: The first GtkColumnViewColumn object. There are four properties, “title”, “expand”, factory" and “sorter”.</li>
<li>31: Sets the “title” property with “Name”. This is the title on the header of the column.</li>
<li>32: Sets the “expand” property to TRUE to allow the column to expand as much as possible. (See the image above).</li>
<li>33- 69: Sets the “factory” property with GtkBuilderListItemFactory. The factory has “bytes” property which holds a ui string to define a template to build GtkListItem composite widget. The CDATA section (line 36-66) is the ui string to put into the “bytes” property. The contents are the same as the ui file <code>factory_list.ui</code> in the section 27.</li>
<li>70-77: Sets the “sorter” property with GtkStringSorter object. This object provides a sorter that compares strings. It has “expression” property which is set with GtkExpression. A closure tag with a string type function <code>get_file_name</code> is used here. The function will be explained later.</li>
<li>80-115: The second GtkColumnViewColumn object. Its “title”, “factory” and “sorter” properties are set. GtkNumericSorter is used.</li>
<li>116-151: The third GtkColumnViewColumn object. Its “title”, “factory” and “sorter” properties are set. GtkNumericSorter is used.</li>
</ul>
<h2 id="gtksortlistmodel-and-gtksorter">GtkSortListModel and GtkSorter</h2>
<p>GtkSortListModel is a list model that sorts its elements according to a GtkSorter. It has “sorter” property that is set with GtkSorter. The property is bound to “sorter” property of GtkColumnView in line 22 to 24.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkSortListModel&quot;</span><span class="ot"> id=</span><span class="st">&quot;sortlist&quot;</span><span class="kw">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>... ... ...</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a> <span class="kw">&lt;binding</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a> <span class="kw">&lt;lookup</span><span class="ot"> name=</span><span class="st">&quot;sorter&quot;</span><span class="kw">&gt;</span>columnview<span class="kw">&lt;/lookup&gt;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a> <span class="kw">&lt;/binding&gt;</span></span></code></pre></div>
<p>Therefore, <code>columnview</code> determines the way how to sort the list model. The “sorter” property of GtkColumnView is read-only property and it is a special sorter. It reflects the users sorting choice. If a user clicks the header of a column, then the sorter (“sorter” property) of the column is referenced by “sorter” property of the GtkColumnView. If the user clicks the header of another column, then the “sorter” property of the GtkColumnView refers to the newly clicked columns “sorter” property.</p>
<p>The binding above makes a indirect connection between the “sorter” property of GtkSortListModel and the “sorter” property of each column.</p>
<p>GtkSorter has several child objects.</p>
<ul>
<li>GtkStringSorter compares strings.</li>
<li>GtkNumericSorter compares numbers.</li>
<li>GtkCustomSorter uses a callback to compare.</li>
<li>GtkMultiSorter combines multiple sorters.</li>
</ul>
<p>The example uses GtkStringSorter and GtkNumericSorter.</p>
<p>GtkStringSorter uses GtkExpression to get the strings from the objects. The GtkExpression is stored in the “expression” property of GtkStringSorter. For example, in the ui file above, the GtkExpression is in the line 71 to 76.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkStringSorter&quot;</span><span class="ot"> id=</span><span class="st">&quot;sorter_name&quot;</span><span class="kw">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expression&quot;</span><span class="kw">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a> <span class="kw">&lt;closure</span><span class="ot"> type=</span><span class="st">&quot;gchararray&quot;</span><span class="ot"> function=</span><span class="st">&quot;get_file_name&quot;</span><span class="kw">&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a> <span class="kw">&lt;/closure&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="kw">&lt;/object&gt;</span></span></code></pre></div>
<p>The GtkExpression calls <code>get_file_name</code> function when it is evaluated.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">char</span> *</span>
<span id="cb4-2"><a href="#cb4-2"></a>get_file_name (GFileInfo *info) {</span>
<span id="cb4-3"><a href="#cb4-3"></a> g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);</span>
<span id="cb4-4"><a href="#cb4-4"></a></span>
<span id="cb4-5"><a href="#cb4-5"></a> <span class="cf">return</span> g_strdup(g_file_info_get_name (info));</span>
<span id="cb4-6"><a href="#cb4-6"></a>}</span></code></pre></div>
<p>The function is given the item (GFileInfo) of the GtkSortListModel as an argument (<code>this</code> object). The function retrieves a filename from <code>info</code>. The string is owned by <code>info</code> so it is necessary to duplicate it. And it returns the copied string. The string will be owned by the expression.</p>
<p>GtkNumericSorter compares numbers. It is used in the line 106 to 112 and line 142 to 148. The lines from 106 to 112 is:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkNumericSorter&quot;</span><span class="ot"> id=</span><span class="st">&quot;sorter_size&quot;</span><span class="kw">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expression&quot;</span><span class="kw">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a> <span class="kw">&lt;closure</span><span class="ot"> type=</span><span class="st">&quot;gint64&quot;</span><span class="ot"> function=</span><span class="st">&quot;get_file_size&quot;</span><span class="kw">&gt;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a> <span class="kw">&lt;/closure&gt;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sort-order&quot;</span><span class="kw">&gt;</span>GTK_SORT_ASCENDING<span class="kw">&lt;/property&gt;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a><span class="kw">&lt;/object&gt;</span></span></code></pre></div>
<p>The closure tag specifies a callback function <code>get_file_size</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1"></a>goffset</span>
<span id="cb6-2"><a href="#cb6-2"></a>get_file_size (GFileInfo *info) {</span>
<span id="cb6-3"><a href="#cb6-3"></a> g_return_val_if_fail (G_IS_FILE_INFO (info), -<span class="dv">1</span>);</span>
<span id="cb6-4"><a href="#cb6-4"></a></span>
<span id="cb6-5"><a href="#cb6-5"></a> <span class="cf">return</span> g_file_info_get_size (info);</span>
<span id="cb6-6"><a href="#cb6-6"></a>}</span></code></pre></div>
<p>It just returns the size of <code>info</code>. The type of the size is <code>goffset</code>. The type <code>goffset</code> is the same as <code>gint64</code>.</p>
<p>The lines from 142 to 148 is:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode xml"><code class="sourceCode xml"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="kw">&lt;object</span><span class="ot"> class=</span><span class="st">&quot;GtkNumericSorter&quot;</span><span class="ot"> id=</span><span class="st">&quot;sorter_datetime_modified&quot;</span><span class="kw">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;expression&quot;</span><span class="kw">&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a> <span class="kw">&lt;closure</span><span class="ot"> type=</span><span class="st">&quot;gint64&quot;</span><span class="ot"> function=</span><span class="st">&quot;get_file_unixtime_modified&quot;</span><span class="kw">&gt;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a> <span class="kw">&lt;/closure&gt;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a> <span class="kw">&lt;/property&gt;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a> <span class="kw">&lt;property</span><span class="ot"> name=</span><span class="st">&quot;sort-order&quot;</span><span class="kw">&gt;</span>GTK_SORT_ASCENDING<span class="kw">&lt;/property&gt;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a><span class="kw">&lt;/object&gt;</span></span></code></pre></div>
<p>The closure tag specifies a callback function <code>get_file_unixtime_modified</code>.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb8-1"><a href="#cb8-1"></a>gint64</span>
<span id="cb8-2"><a href="#cb8-2"></a>get_file_unixtime_modified (GFileInfo *info) {</span>
<span id="cb8-3"><a href="#cb8-3"></a> g_return_val_if_fail (G_IS_FILE_INFO (info), -<span class="dv">1</span>);</span>
<span id="cb8-4"><a href="#cb8-4"></a></span>
<span id="cb8-5"><a href="#cb8-5"></a> GDateTime *dt;</span>
<span id="cb8-6"><a href="#cb8-6"></a></span>
<span id="cb8-7"><a href="#cb8-7"></a> dt = g_file_info_get_modification_date_time (info);</span>
<span id="cb8-8"><a href="#cb8-8"></a> <span class="cf">return</span> g_date_time_to_unix (dt);</span>
<span id="cb8-9"><a href="#cb8-9"></a>}</span></code></pre></div>
<p>It gets the modification date and time (GDateTime type) of <code>info</code>. Then it gets a unix time from <code>dt</code>. Unix time, sometimes called unix epoch, is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970. It returns the unix time (gint64 type).</p>
<h2 id="column.c">column.c</h2>
<p><code>column.c</code> is as follows.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2"></a></span>
<span id="cb9-3"><a href="#cb9-3"></a><span class="co">/* functions (closures) for GtkBuilderListItemFactory */</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>GIcon *</span>
<span id="cb9-5"><a href="#cb9-5"></a>get_icon_factory (GtkListItem *item, GFileInfo *info) {</span>
<span id="cb9-6"><a href="#cb9-6"></a> GIcon *icon;</span>
<span id="cb9-7"><a href="#cb9-7"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
<span id="cb9-8"><a href="#cb9-8"></a> <span class="cf">return</span> NULL;</span>
<span id="cb9-9"><a href="#cb9-9"></a> <span class="cf">else</span> {</span>
<span id="cb9-10"><a href="#cb9-10"></a> icon = g_file_info_get_icon (info);</span>
<span id="cb9-11"><a href="#cb9-11"></a> g_object_ref (icon);</span>
<span id="cb9-12"><a href="#cb9-12"></a> <span class="cf">return</span> icon;</span>
<span id="cb9-13"><a href="#cb9-13"></a> }</span>
<span id="cb9-14"><a href="#cb9-14"></a>}</span>
<span id="cb9-15"><a href="#cb9-15"></a></span>
<span id="cb9-16"><a href="#cb9-16"></a><span class="dt">char</span> *</span>
<span id="cb9-17"><a href="#cb9-17"></a>get_file_name_factory (GtkListItem *item, GFileInfo *info) {</span>
<span id="cb9-18"><a href="#cb9-18"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
<span id="cb9-19"><a href="#cb9-19"></a> <span class="cf">return</span> NULL;</span>
<span id="cb9-20"><a href="#cb9-20"></a> <span class="cf">else</span></span>
<span id="cb9-21"><a href="#cb9-21"></a> <span class="cf">return</span> g_strdup (g_file_info_get_name (info));</span>
<span id="cb9-22"><a href="#cb9-22"></a>}</span>
<span id="cb9-23"><a href="#cb9-23"></a></span>
<span id="cb9-24"><a href="#cb9-24"></a><span class="dt">char</span> *</span>
<span id="cb9-25"><a href="#cb9-25"></a>get_file_size_factory (GtkListItem *item, GFileInfo *info) {</span>
<span id="cb9-26"><a href="#cb9-26"></a> <span class="co">/* goffset is gint64 */</span></span>
<span id="cb9-27"><a href="#cb9-27"></a> goffset size;</span>
<span id="cb9-28"><a href="#cb9-28"></a></span>
<span id="cb9-29"><a href="#cb9-29"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
<span id="cb9-30"><a href="#cb9-30"></a> <span class="cf">return</span> NULL;</span>
<span id="cb9-31"><a href="#cb9-31"></a> <span class="cf">else</span> {</span>
<span id="cb9-32"><a href="#cb9-32"></a> size = g_file_info_get_size (info);</span>
<span id="cb9-33"><a href="#cb9-33"></a> <span class="cf">return</span> g_strdup_printf (<span class="st">&quot;%ld&quot;</span>, (<span class="dt">long</span> <span class="dt">int</span>) size);</span>
<span id="cb9-34"><a href="#cb9-34"></a> }</span>
<span id="cb9-35"><a href="#cb9-35"></a>}</span>
<span id="cb9-36"><a href="#cb9-36"></a></span>
<span id="cb9-37"><a href="#cb9-37"></a><span class="dt">char</span> *</span>
<span id="cb9-38"><a href="#cb9-38"></a>get_file_time_modified_factory (GtkListItem *item, GFileInfo *info) {</span>
<span id="cb9-39"><a href="#cb9-39"></a> GDateTime *dt;</span>
<span id="cb9-40"><a href="#cb9-40"></a></span>
<span id="cb9-41"><a href="#cb9-41"></a> <span class="cf">if</span> (! G_IS_FILE_INFO (info))</span>
<span id="cb9-42"><a href="#cb9-42"></a> <span class="cf">return</span> NULL;</span>
<span id="cb9-43"><a href="#cb9-43"></a> <span class="cf">else</span> {</span>
<span id="cb9-44"><a href="#cb9-44"></a> dt = g_file_info_get_modification_date_time (info);</span>
<span id="cb9-45"><a href="#cb9-45"></a> <span class="cf">return</span> g_date_time_format (dt, <span class="st">&quot;%F&quot;</span>);</span>
<span id="cb9-46"><a href="#cb9-46"></a> }</span>
<span id="cb9-47"><a href="#cb9-47"></a>}</span>
<span id="cb9-48"><a href="#cb9-48"></a></span>
<span id="cb9-49"><a href="#cb9-49"></a><span class="co">/* Functions (closures) for GtkSorter */</span></span>
<span id="cb9-50"><a href="#cb9-50"></a><span class="dt">char</span> *</span>
<span id="cb9-51"><a href="#cb9-51"></a>get_file_name (GFileInfo *info) {</span>
<span id="cb9-52"><a href="#cb9-52"></a> g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);</span>
<span id="cb9-53"><a href="#cb9-53"></a></span>
<span id="cb9-54"><a href="#cb9-54"></a> <span class="cf">return</span> g_strdup(g_file_info_get_name (info));</span>
<span id="cb9-55"><a href="#cb9-55"></a>}</span>
<span id="cb9-56"><a href="#cb9-56"></a></span>
<span id="cb9-57"><a href="#cb9-57"></a>goffset</span>
<span id="cb9-58"><a href="#cb9-58"></a>get_file_size (GFileInfo *info) {</span>
<span id="cb9-59"><a href="#cb9-59"></a> g_return_val_if_fail (G_IS_FILE_INFO (info), -<span class="dv">1</span>);</span>
<span id="cb9-60"><a href="#cb9-60"></a></span>
<span id="cb9-61"><a href="#cb9-61"></a> <span class="cf">return</span> g_file_info_get_size (info);</span>
<span id="cb9-62"><a href="#cb9-62"></a>}</span>
<span id="cb9-63"><a href="#cb9-63"></a></span>
<span id="cb9-64"><a href="#cb9-64"></a>gint64</span>
<span id="cb9-65"><a href="#cb9-65"></a>get_file_unixtime_modified (GFileInfo *info) {</span>
<span id="cb9-66"><a href="#cb9-66"></a> g_return_val_if_fail (G_IS_FILE_INFO (info), -<span class="dv">1</span>);</span>
<span id="cb9-67"><a href="#cb9-67"></a></span>
<span id="cb9-68"><a href="#cb9-68"></a> GDateTime *dt;</span>
<span id="cb9-69"><a href="#cb9-69"></a></span>
<span id="cb9-70"><a href="#cb9-70"></a> dt = g_file_info_get_modification_date_time (info);</span>
<span id="cb9-71"><a href="#cb9-71"></a> <span class="cf">return</span> g_date_time_to_unix (dt);</span>
<span id="cb9-72"><a href="#cb9-72"></a>}</span>
<span id="cb9-73"><a href="#cb9-73"></a></span>
<span id="cb9-74"><a href="#cb9-74"></a><span class="co">/* ----- activate, open, startup handlers ----- */</span></span>
<span id="cb9-75"><a href="#cb9-75"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb9-76"><a href="#cb9-76"></a>app_activate (GApplication *application) {</span>
<span id="cb9-77"><a href="#cb9-77"></a> GtkApplication *app = GTK_APPLICATION (application);</span>
<span id="cb9-78"><a href="#cb9-78"></a> GFile *file;</span>
<span id="cb9-79"><a href="#cb9-79"></a></span>
<span id="cb9-80"><a href="#cb9-80"></a> GtkBuilder *build = gtk_builder_new_from_resource (<span class="st">&quot;/com/github/ToshioCP/column/column.ui&quot;</span>);</span>
<span id="cb9-81"><a href="#cb9-81"></a> GtkWidget *win = GTK_WIDGET (gtk_builder_get_object (build, <span class="st">&quot;win&quot;</span>));</span>
<span id="cb9-82"><a href="#cb9-82"></a> GtkDirectoryList *directorylist = GTK_DIRECTORY_LIST (gtk_builder_get_object (build, <span class="st">&quot;directorylist&quot;</span>));</span>
<span id="cb9-83"><a href="#cb9-83"></a> g_object_unref (build);</span>
<span id="cb9-84"><a href="#cb9-84"></a></span>
<span id="cb9-85"><a href="#cb9-85"></a> gtk_window_set_application (GTK_WINDOW (win), app);</span>
<span id="cb9-86"><a href="#cb9-86"></a></span>
<span id="cb9-87"><a href="#cb9-87"></a> file = g_file_new_for_path (<span class="st">&quot;.&quot;</span>);</span>
<span id="cb9-88"><a href="#cb9-88"></a> gtk_directory_list_set_file (directorylist, file);</span>
<span id="cb9-89"><a href="#cb9-89"></a> g_object_unref (file);</span>
<span id="cb9-90"><a href="#cb9-90"></a></span>
<span id="cb9-91"><a href="#cb9-91"></a> gtk_widget_show (win);</span>
<span id="cb9-92"><a href="#cb9-92"></a>}</span>
<span id="cb9-93"><a href="#cb9-93"></a></span>
<span id="cb9-94"><a href="#cb9-94"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb9-95"><a href="#cb9-95"></a>app_startup (GApplication *application) {</span>
<span id="cb9-96"><a href="#cb9-96"></a>}</span>
<span id="cb9-97"><a href="#cb9-97"></a></span>
<span id="cb9-98"><a href="#cb9-98"></a><span class="pp">#define APPLICATION_ID &quot;com.github.ToshioCP.columnview&quot;</span></span>
<span id="cb9-99"><a href="#cb9-99"></a></span>
<span id="cb9-100"><a href="#cb9-100"></a><span class="dt">int</span></span>
<span id="cb9-101"><a href="#cb9-101"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
<span id="cb9-102"><a href="#cb9-102"></a> GtkApplication *app;</span>
<span id="cb9-103"><a href="#cb9-103"></a> <span class="dt">int</span> stat;</span>
<span id="cb9-104"><a href="#cb9-104"></a></span>
<span id="cb9-105"><a href="#cb9-105"></a> app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);</span>
<span id="cb9-106"><a href="#cb9-106"></a></span>
<span id="cb9-107"><a href="#cb9-107"></a> g_signal_connect (app, <span class="st">&quot;startup&quot;</span>, G_CALLBACK (app_startup), NULL);</span>
<span id="cb9-108"><a href="#cb9-108"></a> g_signal_connect (app, <span class="st">&quot;activate&quot;</span>, G_CALLBACK (app_activate), NULL);</span>
<span id="cb9-109"><a href="#cb9-109"></a><span class="co">/* g_signal_connect (app, &quot;open&quot;, G_CALLBACK (app_open), NULL);*/</span></span>
<span id="cb9-110"><a href="#cb9-110"></a></span>
<span id="cb9-111"><a href="#cb9-111"></a> stat =g_application_run (G_APPLICATION (app), argc, argv);</span>
<span id="cb9-112"><a href="#cb9-112"></a> g_object_unref (app);</span>
<span id="cb9-113"><a href="#cb9-113"></a> <span class="cf">return</span> stat;</span>
<span id="cb9-114"><a href="#cb9-114"></a>}</span></code></pre></div>
<ul>
<li>4-47: Functions for the closure tag in the “bytes” property of GtkBuilderListItemFactory. These are almost same as the functions in section 26 and 26.</li>
<li>50-72: Functions for the closure in the expression property of GtkStringSorter or GtkNumericSorter.</li>
<li>75-92: <code>app_activate</code> is an “activate” handler of GApplication.</li>
<li>80-83: Builds objects with ui resource and gets <code>win</code> and <code>directorylist</code>.</li>
<li>85: Sets the application of the top level window with <code>app</code>.</li>
<li>87-89: Sets the file of <code>directorylist</code> with “.” (current directory).</li>
<li>94-96: Startup handler.</li>
<li>98-114: <code>main</code> function.</li>
</ul>
<p><code>exp.c</code> is simple and short thanks to <code>exp.ui</code>.</p>
<h2 id="compilation-and-execution.">Compilation and execution.</h2>
<p>All the source files are in src/column directory. Change your current directory to the directory and type the following.</p>
<pre><code>$ meson _build
$ ninja -C _build
$ _build/column</code></pre>
<p>Then, a window appears.</p>
<figure>
<img src="image/column_view.png" alt="" /><figcaption>Column View</figcaption>
</figure>
<p>If you click the header of a column, then the whole lists are sorted by the column. If you click the header of another column, then the whole lists are sorted by the newly selected column.</p>
<p>GtkColumnView is very useful and it can manage very big GListModel. It is possible to use it for file list, application list, database frontend and so on.</p>
</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>