mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-12 20:03:28 +01:00
22 KiB
22 KiB
Up: Readme.md, Prev: Section 15, Next: Section 17
tfe5 source files
How to compile and execute the text editor 'tfe'.
First, source files are shown in the later subsections. How to download them is written at the end of the previous section.
The following is the instruction of compilation and execution.
- You need meson and ninja.
- Set environment variables if necessary.
If you have installed gtk4 from the source and you preferred the option
--prefix $HOME/local
(see Section 2), type. env.sh
to set the environment variables.
$ . env.sh
- change your current directory to
src/tfe5
directory. - type
meson _build
for configuration. - type
ninja -C _build
for compilation. Then the applicationtfe
is built under the_build
directory. - type
_build/tfe
to execute it.
Then the window appears.
There are four buttons, New
, Open
, Save
and Close
.
- Click on
Open
button, then a FileChooserDialog appears. Choose a file in the list and click onOpen
button. Then the file is read and a new Notebook Page appears. - Edit the file and click on
Save
button, then the text is saved to the original file. - Click
Close
, then the Notebook Page disappears. - Click
Close
again, then theUntitled
Notebook Page disappears and at the same time the application quits.
This is a very simple editor. It is a good practice for you to add more features.
meson.build
1 project('tfe', 'c')
2
3 gtkdep = dependency('gtk4')
4
5 gnome=import('gnome')
6 resources = gnome.compile_resources('resources','tfe.gresource.xml')
7
8 sourcefiles=files('tfeapplication.c', 'tfenotebook.c', '../tfetextview/tfetextview.c')
9
10 executable('tfe', sourcefiles, resources, dependencies: gtkdep)
tfe.gresource.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <gresources>
3 <gresource prefix="/com/github/ToshioCP/tfe">
4 <file>tfe.ui</file>
5 </gresource>
6 </gresources>
tfe.ui
1 <?xml version="1.0" encoding="UTF-8"?>
2 <interface>
3 <object class="GtkApplicationWindow" id="win">
4 <property name="title">file editor</property>
5 <property name="default-width">600</property>
6 <property name="default-height">400</property>
7 <child>
8 <object class="GtkBox" id="boxv">
9 <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
10 <child>
11 <object class="GtkBox" id="boxh">
12 <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
13 <child>
14 <object class="GtkLabel" id="dmy1">
15 <property name="width-chars">10</property>
16 </object>
17 </child>
18 <child>
19 <object class="GtkButton" id="btnn">
20 <property name="label">New</property>
21 </object>
22 </child>
23 <child>
24 <object class="GtkButton" id="btno">
25 <property name="label">Open</property>
26 </object>
27 </child>
28 <child>
29 <object class="GtkLabel" id="dmy2">
30 <property name="hexpand">TRUE</property>
31 </object>
32 </child>
33 <child>
34 <object class="GtkButton" id="btns">
35 <property name="label">Save</property>
36 </object>
37 </child>
38 <child>
39 <object class="GtkButton" id="btnc">
40 <property name="label">Close</property>
41 </object>
42 </child>
43 <child>
44 <object class="GtkLabel" id="dmy3">
45 <property name="width-chars">10</property>
46 </object>
47 </child>
48 </object>
49 </child>
50 <child>
51 <object class="GtkNotebook" id="nb">
52 <property name="scrollable">TRUE</property>
53 <property name="hexpand">TRUE</property>
54 <property name="vexpand">TRUE</property>
55 </object>
56 </child>
57 </object>
58 </child>
59 </object>
60 </interface>
61
tfe.h
1 #include <gtk/gtk.h>
2
3 #include "../tfetextview/tfetextview.h"
4 #include "tfenotebook.h"
tfeapplication.c
1 #include "tfe.h"
2
3 static void
4 open_cb (GtkNotebook *nb) {
5 notebook_page_open (nb);
6 }
7
8 static void
9 new_cb (GtkNotebook *nb) {
10 notebook_page_new (nb);
11 }
12
13 static void
14 save_cb (GtkNotebook *nb) {
15 notebook_page_save (nb);
16 }
17
18 static void
19 close_cb (GtkNotebook *nb) {
20 notebook_page_close (GTK_NOTEBOOK (nb));
21 }
22
23 static void
24 app_activate (GApplication *application) {
25 GtkApplication *app = GTK_APPLICATION (application);
26 GtkWidget *win = GTK_WIDGET (gtk_application_get_active_window (app));
27 GtkWidget *boxv = gtk_window_get_child (GTK_WINDOW (win));
28 GtkNotebook *nb = GTK_NOTEBOOK (gtk_widget_get_last_child (boxv));
29
30 notebook_page_new (nb);
31 gtk_widget_show (GTK_WIDGET (win));
32 }
33
34 static void
35 app_open (GApplication *application, GFile ** files, gint n_files, const gchar *hint) {
36 GtkApplication *app = GTK_APPLICATION (application);
37 GtkWidget *win = GTK_WIDGET (gtk_application_get_active_window (app));
38 GtkWidget *boxv = gtk_window_get_child (GTK_WINDOW (win));
39 GtkNotebook *nb = GTK_NOTEBOOK (gtk_widget_get_last_child (boxv));
40 int i;
41
42 for (i = 0; i < n_files; i++)
43 notebook_page_new_with_file (nb, files[i]);
44 if (gtk_notebook_get_n_pages (nb) == 0)
45 notebook_page_new (nb);
46 gtk_widget_show (win);
47 }
48
49 static void
50 app_startup (GApplication *application) {
51 GtkApplication *app = GTK_APPLICATION (application);
52 GtkBuilder *build;
53 GtkApplicationWindow *win;
54 GtkNotebook *nb;
55 GtkButton *btno;
56 GtkButton *btnn;
57 GtkButton *btns;
58 GtkButton *btnc;
59
60 build = gtk_builder_new_from_resource ("/com/github/ToshioCP/tfe/tfe.ui");
61 win = GTK_APPLICATION_WINDOW (gtk_builder_get_object (build, "win"));
62 nb = GTK_NOTEBOOK (gtk_builder_get_object (build, "nb"));
63 gtk_window_set_application (GTK_WINDOW (win), app);
64 btno = GTK_BUTTON (gtk_builder_get_object (build, "btno"));
65 btnn = GTK_BUTTON (gtk_builder_get_object (build, "btnn"));
66 btns = GTK_BUTTON (gtk_builder_get_object (build, "btns"));
67 btnc = GTK_BUTTON (gtk_builder_get_object (build, "btnc"));
68 g_signal_connect_swapped (btno, "clicked", G_CALLBACK (open_cb), nb);
69 g_signal_connect_swapped (btnn, "clicked", G_CALLBACK (new_cb), nb);
70 g_signal_connect_swapped (btns, "clicked", G_CALLBACK (save_cb), nb);
71 g_signal_connect_swapped (btnc, "clicked", G_CALLBACK (close_cb), nb);
72 g_object_unref(build);
73
74 GdkDisplay *display;
75
76 display = gtk_widget_get_display (GTK_WIDGET (win));
77 GtkCssProvider *provider = gtk_css_provider_new ();
78 gtk_css_provider_load_from_data (provider, "textview {padding: 10px; font-family: monospace; font-size: 12pt;}", -1);
79 gtk_style_context_add_provider_for_display (display, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
80 }
81
82 #define APPLICATION_ID "com.github.ToshioCP.tfe"
83
84 int
85 main (int argc, char **argv) {
86 GtkApplication *app;
87 int stat;
88
89 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_HANDLES_OPEN);
90
91 g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
92 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
93 g_signal_connect (app, "open", G_CALLBACK (app_open), NULL);
94
95 stat =g_application_run (G_APPLICATION (app), argc, argv);
96 g_object_unref (app);
97 return stat;
98 }
99
tfenotebook.h
1 void
2 notebook_page_save(GtkNotebook *nb);
3
4 void
5 notebook_page_close (GtkNotebook *nb);
6
7 void
8 notebook_page_open (GtkNotebook *nb);
9
10 void
11 notebook_page_new_with_file (GtkNotebook *nb, GFile *file);
12
13 void
14 notebook_page_new (GtkNotebook *nb);
15
tfenotebook.c
1 #include "tfe.h"
2
3 /* The returned string should be freed with g_free() when no longer needed. */
4 static gchar*
5 get_untitled () {
6 static int c = -1;
7 if (++c == 0)
8 return g_strdup_printf("Untitled");
9 else
10 return g_strdup_printf ("Untitled%u", c);
11 }
12
13 static TfeTextView *
14 get_current_textview (GtkNotebook *nb) {
15 int i;
16 GtkWidget *scr;
17 GtkWidget *tv;
18
19 i = gtk_notebook_get_current_page (nb);
20 scr = gtk_notebook_get_nth_page (nb, i);
21 tv = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (scr));
22 return TFE_TEXT_VIEW (tv);
23 }
24
25 static void
26 file_changed_cb (TfeTextView *tv, GtkNotebook *nb) {
27 GtkWidget *scr;
28 GtkWidget *label;
29 GFile *file;
30 char *filename;
31
32 file = tfe_text_view_get_file (tv);
33 scr = gtk_widget_get_parent (GTK_WIDGET (tv));
34 if (G_IS_FILE (file)) {
35 filename = g_file_get_basename (file);
36 g_object_unref (file);
37 } else
38 filename = get_untitled ();
39 label = gtk_label_new (filename);
40 g_free (filename);
41 gtk_notebook_set_tab_label (nb, scr, label);
42 }
43
44 void
45 notebook_page_save (GtkNotebook *nb) {
46 g_return_if_fail(GTK_IS_NOTEBOOK (nb));
47
48 TfeTextView *tv;
49
50 tv = get_current_textview (nb);
51 tfe_text_view_save (TFE_TEXT_VIEW (tv));
52 }
53
54 void
55 notebook_page_close (GtkNotebook *nb) {
56 g_return_if_fail(GTK_IS_NOTEBOOK (nb));
57
58 GtkWidget *win;
59 int i;
60
61 if (gtk_notebook_get_n_pages (nb) == 1) {
62 win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
63 gtk_window_destroy(GTK_WINDOW (win));
64 } else {
65 i = gtk_notebook_get_current_page (nb);
66 gtk_notebook_remove_page (GTK_NOTEBOOK (nb), i);
67 }
68 }
69
70 static void
71 notebook_page_build (GtkNotebook *nb, GtkWidget *tv, char *filename) {
72 GtkWidget *scr = gtk_scrolled_window_new ();
73 GtkNotebookPage *nbp;
74 GtkWidget *lab;
75 int i;
76
77 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
78 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
79 lab = gtk_label_new (filename);
80 i = gtk_notebook_append_page (nb, scr, lab);
81 nbp = gtk_notebook_get_page (nb, scr);
82 g_object_set (nbp, "tab-expand", TRUE, NULL);
83 gtk_notebook_set_current_page (nb, i);
84 g_signal_connect (GTK_TEXT_VIEW (tv), "change-file", G_CALLBACK (file_changed_cb), nb);
85 }
86
87 static void
88 open_response (TfeTextView *tv, int response, GtkNotebook *nb) {
89 GFile *file;
90 char *filename;
91
92 if (response != TFE_OPEN_RESPONSE_SUCCESS || ! G_IS_FILE (file = tfe_text_view_get_file (tv))) {
93 g_object_ref_sink (tv);
94 g_object_unref (tv);
95 }else {
96 filename = g_file_get_basename (file);
97 g_object_unref (file);
98 notebook_page_build (nb, GTK_WIDGET (tv), filename);
99 }
100 }
101
102 void
103 notebook_page_open (GtkNotebook *nb) {
104 g_return_if_fail(GTK_IS_NOTEBOOK (nb));
105
106 GtkWidget *tv;
107
108 if ((tv = tfe_text_view_new ()) == NULL)
109 return;
110 g_signal_connect (TFE_TEXT_VIEW (tv), "open-response", G_CALLBACK (open_response), nb);
111 tfe_text_view_open (TFE_TEXT_VIEW (tv), GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW)));
112 }
113
114 void
115 notebook_page_new_with_file (GtkNotebook *nb, GFile *file) {
116 g_return_if_fail(GTK_IS_NOTEBOOK (nb));
117 g_return_if_fail(G_IS_FILE (file));
118
119 GtkWidget *tv;
120 char *filename;
121
122 if ((tv = tfe_text_view_new_with_file (file)) == NULL)
123 return; /* read error */
124 filename = g_file_get_basename (file);
125 notebook_page_build (nb, tv, filename);
126 }
127
128 void
129 notebook_page_new (GtkNotebook *nb) {
130 g_return_if_fail(GTK_IS_NOTEBOOK (nb));
131
132 GtkWidget *tv;
133 char *filename;
134
135 if ((tv = tfe_text_view_new ()) == NULL)
136 return;
137 filename = get_untitled ();
138 notebook_page_build (nb, tv, filename);
139 }
140
tfetextview.h
1 #ifndef __TFE_TEXT_VIEW_H__
2 #define __TFE_TEXT_VIEW_H__
3
4 #include <gtk/gtk.h>
5
6 #define TFE_TYPE_TEXT_VIEW tfe_text_view_get_type ()
7 G_DECLARE_FINAL_TYPE (TfeTextView, tfe_text_view, TFE, TEXT_VIEW, GtkTextView)
8
9 /* "open-response" signal response */
10 enum TfeTextViewOpenResponseType
11 {
12 TFE_OPEN_RESPONSE_SUCCESS,
13 TFE_OPEN_RESPONSE_CANCEL,
14 TFE_OPEN_RESPONSE_ERROR
15 };
16
17 GFile *
18 tfe_text_view_get_file (TfeTextView *tv);
19
20 void
21 tfe_text_view_open (TfeTextView *tv, GtkWindow *win);
22
23 void
24 tfe_text_view_save (TfeTextView *tv);
25
26 void
27 tfe_text_view_saveas (TfeTextView *tv);
28
29 GtkWidget *
30 tfe_text_view_new_with_file (GFile *file);
31
32 GtkWidget *
33 tfe_text_view_new (void);
34
35 #endif /* __TFE_TEXT_VIEW_H__ */
tfetextview.c
1 #include <string.h>
2 #include "tfetextview.h"
3
4 struct _TfeTextView {
5 GtkTextView parent;
6 GFile *file;
7 };
8
9 G_DEFINE_TYPE (TfeTextView, tfe_text_view, GTK_TYPE_TEXT_VIEW);
10
11 enum {
12 CHANGE_FILE,
13 OPEN_RESPONSE,
14 NUMBER_OF_SIGNALS
15 };
16
17 static guint tfe_text_view_signals[NUMBER_OF_SIGNALS];
18
19 static void
20 tfe_text_view_dispose (GObject *gobject) {
21 TfeTextView *tv = TFE_TEXT_VIEW (gobject);
22
23 if (G_IS_FILE (tv->file))
24 g_clear_object (&tv->file);
25
26 G_OBJECT_CLASS (tfe_text_view_parent_class)->dispose (gobject);
27 }
28
29 static void
30 tfe_text_view_init (TfeTextView *tv) {
31 tv->file = NULL;
32 }
33
34 static void
35 tfe_text_view_class_init (TfeTextViewClass *class) {
36 GObjectClass *object_class = G_OBJECT_CLASS (class);
37
38 object_class->dispose = tfe_text_view_dispose;
39 tfe_text_view_signals[CHANGE_FILE] = g_signal_new ("change-file",
40 G_TYPE_FROM_CLASS (class),
41 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
42 0 /* class offset */,
43 NULL /* accumulator */,
44 NULL /* accumulator data */,
45 NULL /* C marshaller */,
46 G_TYPE_NONE /* return_type */,
47 0 /* n_params */
48 );
49 tfe_text_view_signals[OPEN_RESPONSE] = g_signal_new ("open-response",
50 G_TYPE_FROM_CLASS (class),
51 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
52 0 /* class offset */,
53 NULL /* accumulator */,
54 NULL /* accumulator data */,
55 NULL /* C marshaller */,
56 G_TYPE_NONE /* return_type */,
57 1 /* n_params */,
58 G_TYPE_INT
59 );
60 }
61
62 GFile *
63 tfe_text_view_get_file (TfeTextView *tv) {
64 g_return_val_if_fail (TFE_IS_TEXT_VIEW (tv), NULL);
65
66 if (G_IS_FILE (tv->file))
67 return g_file_dup (tv->file);
68 else
69 return NULL;
70 }
71
72 static gboolean
73 save_file (GFile *file, GtkTextBuffer *tb, GtkWindow *win) {
74 GtkTextIter start_iter;
75 GtkTextIter end_iter;
76 gchar *contents;
77 gboolean stat;
78 GtkWidget *message_dialog;
79 GError *err = NULL;
80
81 gtk_text_buffer_get_bounds (tb, &start_iter, &end_iter);
82 contents = gtk_text_buffer_get_text (tb, &start_iter, &end_iter, FALSE);
83 if (g_file_replace_contents (file, contents, strlen (contents), NULL, TRUE, G_FILE_CREATE_NONE, NULL, NULL, &err)) {
84 gtk_text_buffer_set_modified (tb, FALSE);
85 stat = TRUE;
86 } else {
87 message_dialog = gtk_message_dialog_new (win, GTK_DIALOG_MODAL,
88 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
89 "%s.\n", err->message);
90 g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
91 gtk_widget_show (message_dialog);
92 g_error_free (err);
93 stat = FALSE;
94 }
95 g_free (contents);
96 return stat;
97 }
98
99 static void
100 saveas_dialog_response (GtkWidget *dialog, gint response, TfeTextView *tv) {
101 GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
102 GFile *file;
103 GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (tv), GTK_TYPE_WINDOW);
104
105 if (response == GTK_RESPONSE_ACCEPT) {
106 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
107 if (! G_IS_FILE (file))
108 g_warning ("TfeTextView: gtk_file_chooser_get_file returns non GFile.\n");
109 else if (save_file(file, tb, GTK_WINDOW (win))) {
110 if (G_IS_FILE (tv->file))
111 g_object_unref (tv->file);
112 tv->file = file;
113 g_signal_emit (tv, tfe_text_view_signals[CHANGE_FILE], 0);
114 } else
115 g_object_unref (file);
116 }
117 gtk_window_destroy (GTK_WINDOW (dialog));
118 }
119
120 void
121 tfe_text_view_save (TfeTextView *tv) {
122 g_return_if_fail (TFE_IS_TEXT_VIEW (tv));
123
124 GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
125 GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (tv), GTK_TYPE_WINDOW);
126
127 if (! gtk_text_buffer_get_modified (tb))
128 return; /* no need to save it */
129 else if (tv->file == NULL)
130 tfe_text_view_saveas (tv);
131 else if (! G_IS_FILE (tv->file))
132 g_error ("TfeTextView: The pointer tv->file isn't NULL nor GFile.\n");
133 else
134 save_file (tv->file, tb, GTK_WINDOW (win));
135 }
136
137 void
138 tfe_text_view_saveas (TfeTextView *tv) {
139 g_return_if_fail (TFE_IS_TEXT_VIEW (tv));
140
141 GtkWidget *dialog;
142 GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (tv), GTK_TYPE_WINDOW);
143
144 dialog = gtk_file_chooser_dialog_new ("Save file", GTK_WINDOW (win), GTK_FILE_CHOOSER_ACTION_SAVE,
145 "Cancel", GTK_RESPONSE_CANCEL,
146 "Save", GTK_RESPONSE_ACCEPT,
147 NULL);
148 g_signal_connect (dialog, "response", G_CALLBACK (saveas_dialog_response), tv);
149 gtk_widget_show (dialog);
150 }
151
152 GtkWidget *
153 tfe_text_view_new_with_file (GFile *file) {
154 g_return_val_if_fail (G_IS_FILE (file), NULL);
155
156 GtkWidget *tv;
157 GtkTextBuffer *tb;
158 char *contents;
159 gsize length;
160
161 if (! g_file_load_contents (file, NULL, &contents, &length, NULL, NULL)) /* read error */
162 return NULL;
163
164 if ((tv = tfe_text_view_new()) != NULL) {
165 tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
166 gtk_text_buffer_set_text (tb, contents, length);
167 TFE_TEXT_VIEW (tv)->file = g_file_dup (file);
168 gtk_text_buffer_set_modified (tb, FALSE);
169 }
170 g_free (contents);
171 return tv;
172 }
173
174 static void
175 open_dialog_response(GtkWidget *dialog, gint response, TfeTextView *tv) {
176 GtkTextBuffer *tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
177 GFile *file;
178 char *contents;
179 gsize length;
180 GtkWidget *message_dialog;
181 GError *err = NULL;
182
183 if (response != GTK_RESPONSE_ACCEPT)
184 g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], 0, TFE_OPEN_RESPONSE_CANCEL);
185 else if (! G_IS_FILE (file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)))) {
186 g_warning ("TfeTextView: gtk_file_chooser_get_file returns non GFile.\n");
187 g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], 0, TFE_OPEN_RESPONSE_ERROR);
188 } else if (! g_file_load_contents (file, NULL, &contents, &length, NULL, &err)) { /* read error */
189 g_object_unref (file);
190 message_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog), GTK_DIALOG_MODAL,
191 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
192 "%s.\n", err->message);
193 g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
194 gtk_widget_show (message_dialog);
195 g_error_free (err);
196 g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], 0, TFE_OPEN_RESPONSE_ERROR);
197 } else {
198 gtk_text_buffer_set_text (tb, contents, length);
199 g_free (contents);
200 if (G_IS_FILE (tv->file))
201 g_object_unref (tv->file);
202 tv->file = file;
203 gtk_text_buffer_set_modified (tb, FALSE);
204 g_signal_emit (tv, tfe_text_view_signals[OPEN_RESPONSE], 0, TFE_OPEN_RESPONSE_SUCCESS);
205 g_signal_emit (tv, tfe_text_view_signals[CHANGE_FILE], 0);
206 }
207 gtk_window_destroy (GTK_WINDOW (dialog));
208 }
209
210 void
211 tfe_text_view_open (TfeTextView *tv, GtkWindow *win) {
212 g_return_if_fail (TFE_IS_TEXT_VIEW (tv));
213 g_return_if_fail (GTK_IS_WINDOW (win));
214
215 GtkWidget *dialog;
216
217 dialog = gtk_file_chooser_dialog_new ("Open file", win, GTK_FILE_CHOOSER_ACTION_OPEN,
218 "Cancel", GTK_RESPONSE_CANCEL,
219 "Open", GTK_RESPONSE_ACCEPT,
220 NULL);
221 g_signal_connect (dialog, "response", G_CALLBACK (open_dialog_response), tv);
222 gtk_widget_show (dialog);
223 }
224
225 GtkWidget *
226 tfe_text_view_new (void) {
227 return GTK_WIDGET (g_object_new (TFE_TYPE_TEXT_VIEW, NULL));
228 }
229
Total number of lines, words and characters
$ LANG=C wc tfe5/meson.build tfe5/tfeapplication.c tfe5/tfe.gresource.xml tfe5/tfe.h tfe5/tfenotebook.c tfe5/tfenotebook.h tfetextview/tfetextview.c tfetextview/tfetextview.h tfe5/tfe.ui
10 17 294 tfe5/meson.build
99 304 3205 tfe5/tfeapplication.c
6 9 153 tfe5/tfe.gresource.xml
4 6 87 tfe5/tfe.h
140 378 3601 tfe5/tfenotebook.c
15 21 241 tfe5/tfenotebook.h
229 671 8017 tfetextview/tfetextview.c
35 60 701 tfetextview/tfetextview.h
61 100 2073 tfe5/tfe.ui
599 1566 18372 total
Up: Readme.md, Prev: Section 15, Next: Section 17