mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-29 20:34:16 +01:00
Modify section 19 and 20.
This commit is contained in:
parent
92401c6a51
commit
20b4a16175
39 changed files with 323 additions and 273 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -20,6 +20,7 @@ src/tfe5/hello.txt
|
||||||
src/tfe6/_build
|
src/tfe6/_build
|
||||||
src/tfe7/_build
|
src/tfe7/_build
|
||||||
src/menu/a.out
|
src/menu/a.out
|
||||||
|
src/menu3/_build
|
||||||
src/color/_build
|
src/color/_build
|
||||||
src/turtle/_build
|
src/turtle/_build
|
||||||
src/temp
|
src/temp
|
||||||
|
|
|
@ -9,7 +9,7 @@ The table of contents are shown at the end of this abstract.
|
||||||
- Section 24 to 27 describes list model and list view (GtkListView, GtkGridView and GtkColumnView).
|
- Section 24 to 27 describes list model and list view (GtkListView, GtkGridView and GtkColumnView).
|
||||||
It also describes GtkExpression.
|
It also describes GtkExpression.
|
||||||
|
|
||||||
Please refer to [Gtk API reference](https://developer.gnome.org/gtk4/stable/index.html)
|
Please refer to [Gtk reference manual](https://developer.gnome.org/gtk4/stable/index.html)
|
||||||
and [Gnome Developer Center](https://developer.gnome.org/) for further topics.
|
and [Gnome Developer Center](https://developer.gnome.org/) for further topics.
|
||||||
|
|
||||||
This tutorial is under development and unstable.
|
This tutorial is under development and unstable.
|
||||||
|
|
|
@ -91,7 +91,7 @@ Signals are registered in the class initialization function.
|
||||||
The signal "change-file" has no default handler (object method handler).
|
The signal "change-file" has no default handler (object method handler).
|
||||||
You usually don't need to set a default handler.
|
You usually don't need to set a default handler.
|
||||||
If you need it, use `g_signal_new_class_handler` function.
|
If you need it, use `g_signal_new_class_handler` function.
|
||||||
See [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-new-class-handler) for further information.
|
See [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-new-class-handler) for further information.
|
||||||
- The return value of `g_signal_new` is the signal id.
|
- The return value of `g_signal_new` is the signal id.
|
||||||
The type of signal id is guint, which is the same as unsigned int.
|
The type of signal id is guint, which is the same as unsigned int.
|
||||||
It is used in the function `g_signal_emit`.
|
It is used in the function `g_signal_emit`.
|
||||||
|
@ -101,7 +101,7 @@ This signal has a parameter.
|
||||||
"open-response" signal has one parameter.
|
"open-response" signal has one parameter.
|
||||||
- 25: The type of the parameter.
|
- 25: The type of the parameter.
|
||||||
`G_TYPE_INT` is a type of integer.
|
`G_TYPE_INT` is a type of integer.
|
||||||
Such fundamental types are described in [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Type-Information.html).
|
Such fundamental types are described in [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Type-Information.html).
|
||||||
|
|
||||||
The handlers are declared as follows.
|
The handlers are declared as follows.
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ Each function is defined as follows.
|
||||||
Just returns the value from the function `g_object_new` but casts it to the pointer to GtkWidget.
|
Just returns the value from the function `g_object_new` but casts it to the pointer to GtkWidget.
|
||||||
Initialization is done in `tfe_text_view_init` which is called in the process of `g_object_new` function.
|
Initialization is done in `tfe_text_view_init` which is called in the process of `g_object_new` function.
|
||||||
- 1-21: `tfe_text_view_new_with_file` function.
|
- 1-21: `tfe_text_view_new_with_file` function.
|
||||||
- 3: `g_return_val_if_fail` is described in [Glib API reference](https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-return-val-if-fail).
|
- 3: `g_return_val_if_fail` is described in [Glib reference manual](https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-return-val-if-fail).
|
||||||
It tests whether the argument `file` is a pointer to GFile.
|
It tests whether the argument `file` is a pointer to GFile.
|
||||||
If it's true, then the program goes on to the next line.
|
If it's true, then the program goes on to the next line.
|
||||||
If it's false, then it returns NULL (the second argument) immediately.
|
If it's false, then it returns NULL (the second argument) immediately.
|
||||||
|
@ -438,7 +438,7 @@ The important thing is to duplicate `tv->file`.
|
||||||
Otherwise, if the caller frees the GFile object, `tv->file` is no more guaranteed to point the GFile.
|
Otherwise, if the caller frees the GFile object, `tv->file` is no more guaranteed to point the GFile.
|
||||||
Another reason to use `g_file_dup` is that GFile isn't thread-safe.
|
Another reason to use `g_file_dup` is that GFile isn't thread-safe.
|
||||||
If you use GFile in the different thread, the duplication is necessary.
|
If you use GFile in the different thread, the duplication is necessary.
|
||||||
See [Gio API reference](https://developer.gnome.org/gio/stable/GFile.html#g-file-dup).
|
See [Gio reference manual](https://developer.gnome.org/gio/stable/GFile.html#g-file-dup).
|
||||||
|
|
||||||
## The API document and source file of tfetextview.c
|
## The API document and source file of tfetextview.c
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ On the other hand, when an instance of GObject (not GInitiallyUnowned) is create
|
||||||
And the instance has a normal reference count instead of floating reference.
|
And the instance has a normal reference count instead of floating reference.
|
||||||
|
|
||||||
If you use `g_object_unref` to an instance that has a floating reference, you need to convert the floating reference to a normal reference in advance.
|
If you use `g_object_unref` to an instance that has a floating reference, you need to convert the floating reference to a normal reference in advance.
|
||||||
See [GObject API reference manual](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#gobject-The-Base-Object-Type.description) for further information.
|
See [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#gobject-The-Base-Object-Type.description) for further information.
|
||||||
|
|
||||||
## notebook\_page\_close
|
## notebook\_page\_close
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ textview {color: yellow; ...}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Class, ID and some other things can be applied to the selector like Web CSS.
|
Class, ID and some other things can be applied to the selector like Web CSS.
|
||||||
Refer [Gtk4 API reference](https://developer.gnome.org/gtk4/stable/theming.html) for further information.
|
Refer [Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/theming.html) for further information.
|
||||||
|
|
||||||
In line 30, the CSS is a string.
|
In line 30, the CSS is a string.
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ Therefore, `act_quit` has a name "quit" and no parameter.
|
||||||
- 17: Adds the action to GtkApplication `app`.
|
- 17: Adds the action to GtkApplication `app`.
|
||||||
GtkApplication implements an interface GActionMap and GActionGroup.
|
GtkApplication implements an interface GActionMap and GActionGroup.
|
||||||
GtkApplication (GActionMap) can have a group of actions and the actions are added with the function `g_action_map_add_action`.
|
GtkApplication (GActionMap) can have a group of actions and the actions are added with the function `g_action_map_add_action`.
|
||||||
This function is described in [GMenuModel section in GIO API reference](https://developer.gnome.org/gio/stable/GActionMap.html#g-action-map-add-action).
|
This function is described in [GMenuModel section in GIO reference manual](https://developer.gnome.org/gio/stable/GActionMap.html#g-action-map-add-action).
|
||||||
- 18: Connects "activate" signal of the action and the handler `quit_activated`.
|
- 18: Connects "activate" signal of the action and the handler `quit_activated`.
|
||||||
- 20-23: Creates GMenu and GMenuItem instances.
|
- 20-23: Creates GMenu and GMenuItem instances.
|
||||||
`menubar` and `menu` are GMenu.
|
`menubar` and `menu` are GMenu.
|
||||||
|
|
38
gfm/sec19.md
38
gfm/sec19.md
|
@ -216,7 +216,7 @@ g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries,
|
||||||
The code above does:
|
The code above does:
|
||||||
|
|
||||||
- Builds the "quit" action
|
- Builds the "quit" action
|
||||||
- Connects the action and the "activate" signal handler `quit_activate`
|
- Connects the action and the "activate" signal handler `quit_activated`
|
||||||
- Adds the action to the action map `app`.
|
- Adds the action to the action map `app`.
|
||||||
|
|
||||||
The same goes for the other actions.
|
The same goes for the other actions.
|
||||||
|
@ -234,7 +234,7 @@ The code above does:
|
||||||
- Builds a "fullscreen" action and "color" action.
|
- Builds a "fullscreen" action and "color" action.
|
||||||
- Connects the "fullscreen" action and the "change-state" signal handler `fullscreen_changed`
|
- Connects the "fullscreen" action and the "change-state" signal handler `fullscreen_changed`
|
||||||
- Its initial state is set to FALSE.
|
- Its initial state is set to FALSE.
|
||||||
- Connects the "color" action and the "activate" signal handler `color_activate`
|
- Connects the "color" action and the "activate" signal handler `color_activated`
|
||||||
- Its parameter type is string and the initial value is "red".
|
- Its parameter type is string and the initial value is "red".
|
||||||
- Adds the actions to the action map `win`.
|
- Adds the actions to the action map `win`.
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ The C source code of `menu3` and `meson.build` is as follows.
|
||||||
52 }
|
52 }
|
||||||
53
|
53
|
||||||
54 static void
|
54 static void
|
||||||
55 on_activate (GApplication *app, gpointer user_data) {
|
55 app_activate (GApplication *app, gpointer user_data) {
|
||||||
56 GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
|
56 GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
|
||||||
57
|
57
|
||||||
58 const GActionEntry win_entries[] = {
|
58 const GActionEntry win_entries[] = {
|
||||||
|
@ -322,7 +322,7 @@ The C source code of `menu3` and `meson.build` is as follows.
|
||||||
77 }
|
77 }
|
||||||
78
|
78
|
||||||
79 static void
|
79 static void
|
||||||
80 on_startup (GApplication *app, gpointer user_data) {
|
80 app_startup (GApplication *app, gpointer user_data) {
|
||||||
81 GtkBuilder *builder = gtk_builder_new_from_resource ("/com/github/ToshioCP/menu3/menu3.ui");
|
81 GtkBuilder *builder = gtk_builder_new_from_resource ("/com/github/ToshioCP/menu3/menu3.ui");
|
||||||
82 GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));
|
82 GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));
|
||||||
83
|
83
|
||||||
|
@ -335,20 +335,22 @@ The C source code of `menu3` and `meson.build` is as follows.
|
||||||
90 g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app);
|
90 g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app);
|
||||||
91 }
|
91 }
|
||||||
92
|
92
|
||||||
93 int
|
93 #define APPLICATION_ID "com.github.ToshioCP.menu3"
|
||||||
94 main (int argc, char **argv) {
|
94
|
||||||
95 GtkApplication *app;
|
95 int
|
||||||
96 int stat;
|
96 main (int argc, char **argv) {
|
||||||
97
|
97 GtkApplication *app;
|
||||||
98 app = gtk_application_new ("com.github.ToshioCP.menu3", G_APPLICATION_FLAGS_NONE);
|
98 int stat;
|
||||||
99 g_signal_connect (app, "startup", G_CALLBACK (on_startup), NULL);
|
99
|
||||||
100 g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
|
100 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
|
||||||
101
|
101 g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
|
||||||
102 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
102 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||||
103 g_object_unref (app);
|
103
|
||||||
104 return stat;
|
104 stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||||
105 }
|
105 g_object_unref (app);
|
||||||
106
|
106 return stat;
|
||||||
|
107 }
|
||||||
|
108
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
meson.build
|
meson.build
|
||||||
|
|
|
@ -53,7 +53,7 @@ I installed Gtk4 under the directory `$HOME/local`.
|
||||||
This is a private user area.
|
This is a private user area.
|
||||||
|
|
||||||
If you want to install it in the system area, `/opt/gtk4` is one of good choices.
|
If you want to install it in the system area, `/opt/gtk4` is one of good choices.
|
||||||
[Gtk4 API Reference](https://developer.gnome.org/gtk4/stable/gtk-building.html) gives an installation example to `/opt/gtk4`.
|
[Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/gtk-building.html) gives an installation example to `/opt/gtk4`.
|
||||||
|
|
||||||
Don't install it to `/usr/local` which is the default.
|
Don't install it to `/usr/local` which is the default.
|
||||||
It is used by Ubuntu applications, which are not build on Gtk4.
|
It is used by Ubuntu applications, which are not build on Gtk4.
|
||||||
|
|
282
gfm/sec20.md
282
gfm/sec20.md
|
@ -3,7 +3,7 @@ Up: [Readme.md](../Readme.md), Prev: [Section 19](sec19.md), Next: [Section 21]
|
||||||
# GtkMenuButton, accelerators, font, pango and gsettings
|
# GtkMenuButton, accelerators, font, pango and gsettings
|
||||||
|
|
||||||
Traditional menu structure is fine.
|
Traditional menu structure is fine.
|
||||||
However, Buttons or menu items we often use are not so many.
|
However, buttons or menu items we often use are not so many.
|
||||||
Some mightn't be clicked at all.
|
Some mightn't be clicked at all.
|
||||||
Therefore, it's a good idea to put some frequently used buttons on the toolbar and put the rest of the less frequently used operations into the menu.
|
Therefore, it's a good idea to put some frequently used buttons on the toolbar and put the rest of the less frequently used operations into the menu.
|
||||||
Such menu are often connected to GtkMenuButton.
|
Such menu are often connected to GtkMenuButton.
|
||||||
|
@ -89,11 +89,11 @@ Menus are described in `menu.ui` file.
|
||||||
|
|
||||||
There are four items, "New", "Saveas", "Preference" and "Quit".
|
There are four items, "New", "Saveas", "Preference" and "Quit".
|
||||||
|
|
||||||
- New menu creates a new empty page.
|
- "New" menu creates a new empty page.
|
||||||
- Saveas menu saves the current page as a new filename.
|
- "Saveas" menu saves the current page as a new filename.
|
||||||
- Preference menu sets preference items.
|
- "Preference" menu sets preference items.
|
||||||
This version of `tfe` has only font preference.
|
This version of `tfe` has only font preference.
|
||||||
- Quit menu quits the application.
|
- "Quit" menu quits the application.
|
||||||
|
|
||||||
These four menus are not used so often.
|
These four menus are not used so often.
|
||||||
That's why they are put to the menu behind the menu button.
|
That's why they are put to the menu behind the menu button.
|
||||||
|
@ -183,7 +183,7 @@ You can define more than one accelerator keys and the list must ends with NULL (
|
||||||
If you want to do so, the array length needs to be three or more.
|
If you want to do so, the array length needs to be three or more.
|
||||||
The parser recognizes "\<control\>o", "\<Shift\>\<Alt\>F2", "\<Ctrl\>minus" and so on.
|
The parser recognizes "\<control\>o", "\<Shift\>\<Alt\>F2", "\<Ctrl\>minus" and so on.
|
||||||
If you want to use symbol key like "\<Ctrl\>-", use "\<Ctrl\>minus" instead.
|
If you want to use symbol key like "\<Ctrl\>-", use "\<Ctrl\>minus" instead.
|
||||||
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the gtk4 source code.
|
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the Gtk4 source code.
|
||||||
|
|
||||||
## Saveas handler
|
## Saveas handler
|
||||||
|
|
||||||
|
@ -221,9 +221,10 @@ In `tfeapplication.c`, saveas handler just call `notebook_page_saveas`.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
1 static void
|
1 static void
|
||||||
2 saveas_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
2 saveas_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
3 notebook_page_saveas (GTK_NOTEBOOK (nb));
|
3 GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
4 }
|
4 notebook_page_saveas (nb);
|
||||||
|
5 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
## Preference and alert dialog
|
## Preference and alert dialog
|
||||||
|
@ -266,16 +267,17 @@ Preference dialog xml definition is added to `tfe.ui`.
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- Preference dialog is an independent dialog.
|
- Preference dialog is an independent dialog.
|
||||||
It is not a descendant widget of the top GtkApplicationwindow `win`.
|
It is not a descendant widget of the top-level GtkApplicationwindow `win`.
|
||||||
Therefore, There's no child tag of the dialog object.
|
Therefore, There's no child tag that surrounds the dialog object.
|
||||||
- There are four properties of the dialog specified.
|
- There are four properties of the dialog.
|
||||||
GtkDialog is a child object (not child widget) of GtkWindow, so it inherits all the properties from GtkWindow.
|
GtkDialog is a child object (not child widget) of GtkWindow, so it inherits all the properties from GtkWindow.
|
||||||
Title, resizable, modal and transient-for properties are inherited from GtkWindow.
|
Title, resizable, modal and transient-for properties are inherited from GtkWindow.
|
||||||
Transient-for specifies a temporary parent window, which the dialog's location is based on.
|
Transient-for specifies a temporary parent window, which the dialog's location is based on.
|
||||||
- internal-child attribute is used in the child tag above.
|
- internal-child attribute is used in the child tag above.
|
||||||
GtkDialog has a GtkBox child widget.
|
GtkDialog has a GtkBox child widget.
|
||||||
Its id is "content_area" in `gtkdialog.ui`, which is the ui file of GtkDialog in gtk4 source files.
|
Its id is "content_area" in `gtkdialog.ui`, which is the ui file of GtkDialog.
|
||||||
This box is provided to users to add content widgets in it.
|
(It is in the Gtk4 source files.)
|
||||||
|
This box is provided for users to add content widgets in it.
|
||||||
The tag `<child internal-child="content_area">` is put at the top of the contents.
|
The tag `<child internal-child="content_area">` is put at the top of the contents.
|
||||||
Then you need to specify an object tag and define its class as GtkBox and its id as content_area.
|
Then you need to specify an object tag and define its class as GtkBox and its id as content_area.
|
||||||
This object is defined in `gtkdialog.ui` but you need to define it again in the child tag.
|
This object is defined in `gtkdialog.ui` but you need to define it again in the child tag.
|
||||||
|
@ -365,7 +367,7 @@ tfe_startup (GApplication *application) {
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
The function `tfe_application_quit` destroys top level windows and quits the application.
|
The function `tfe_application_quit` destroys top-level windows and quits the application.
|
||||||
It first disconnects the handlers from the signal "close-request".
|
It first disconnects the handlers from the signal "close-request".
|
||||||
|
|
||||||
### Alert dialog
|
### Alert dialog
|
||||||
|
@ -447,8 +449,8 @@ An alert message will be inserted by the program later.
|
||||||
There are two child tags which have "action" type.
|
There are two child tags which have "action" type.
|
||||||
They are button objects located in the action area.
|
They are button objects located in the action area.
|
||||||
Action-widgets tag describes the actions of the buttons.
|
Action-widgets tag describes the actions of the buttons.
|
||||||
Btn\_cancel button emits response signal with cancel response (GTK_RESPONSE_CANCEL) if it is clicked on.
|
`btn_cancel` button emits response signal with cancel response (`GTK_RESPONSE_CANCEL`) if it is clicked on.
|
||||||
Btn\_accept button emits response signal with accept response (GTK_RESPONSE_ACCEPT) if it is clicked on.
|
`btn_accept` button emits response signal with accept response (`GTK_RESPONSE_ACCEPT`) if it is clicked on.
|
||||||
The response signal is connected to `alert_response_cb` handler.
|
The response signal is connected to `alert_response_cb` handler.
|
||||||
|
|
||||||
The alert dialog keeps alive while the application lives.
|
The alert dialog keeps alive while the application lives.
|
||||||
|
@ -478,8 +480,9 @@ close_cb (GtkNotebook *nb) {
|
||||||
... ...
|
... ...
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
close_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
close_cb (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
close_cb (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
... ...
|
... ...
|
||||||
|
@ -499,15 +502,16 @@ alert_response_cb (GtkDialog *alert, int response_id, gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
quit_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
quit_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
|
GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
|
||||||
|
|
||||||
is_quit = true;
|
is_quit = true;
|
||||||
if (has_saved_all (GTK_NOTEBOOK (nb)))
|
if (has_saved_all (nb))
|
||||||
tfe_application_quit (GTK_WINDOW (win));
|
tfe_application_quit (GTK_WINDOW (win));
|
||||||
else {
|
else {
|
||||||
gtk_label_set_text (lb_alert, "Contents aren't saved yet.\nAre you sure to quit?");
|
gtk_label_set_text (lb_alert, "Contents aren't saved yet.\nAre you sure to quit?");
|
||||||
gtk_button_set_label (close_btn_close, "Quit");
|
gtk_button_set_label (btn_accept, "Quit");
|
||||||
gtk_widget_show (GTK_WIDGET (alert));
|
gtk_widget_show (GTK_WIDGET (alert));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,20 +539,24 @@ When user clicks on the close button, `close_cb` handler is invoked.
|
||||||
The handler sets `is_quit` to false.
|
The handler sets `is_quit` to false.
|
||||||
The function `has_saved` returns true if the current page has been saved.
|
The function `has_saved` returns true if the current page has been saved.
|
||||||
If it is true, it calls `notebook_page_close` to close the current page.
|
If it is true, it calls `notebook_page_close` to close the current page.
|
||||||
Otherwise, it sets the text in the label and button, then shows the alert dialog.
|
Otherwise, it sets the message of the dialog and the label of the button, then shows the alert dialog.
|
||||||
|
|
||||||
The response signal of the dialog is connected to the handler `alert_response_cb`.
|
The response signal of the dialog is connected to the handler `alert_response_cb`.
|
||||||
It hides the dialog first.
|
It hides the dialog first.
|
||||||
Then check the response\_id.
|
Then checks the `response_id`.
|
||||||
If it is `GTK_RESPONSE_ACCEPT`, which means user clicked on the close button, then closes the current page.
|
If it is `GTK_RESPONSE_ACCEPT`, which means user clicked on the close button, then it closes the current page.
|
||||||
|
Otherwise it does nothing.
|
||||||
|
|
||||||
When user press "Ctrl-q" or clicked on the quit menu, then `quit_activated` handler is invoked.
|
When user press "Ctrl-q" or clicked on the quit menu, then `quit_activated` handler is invoked.
|
||||||
The handler sets `is_quit` to true.
|
The handler sets `is_quit` to true.
|
||||||
The function `has_saved_all` returns true if all the pages have been saved.
|
The function `has_saved_all` returns true if all the pages have been saved.
|
||||||
If it is true, it calls `tfe_application_quit` to quit the application.
|
If it is true, it calls `tfe_application_quit` to quit the application.
|
||||||
Otherwise, it sets the text in the label and button, then shows the alert dialog.
|
Otherwise, it sets the message of the dialog and the label of the button, then shows the alert dialog.
|
||||||
|
|
||||||
Now `alert_response_cb` works similar but it calls `tfe_application_quit`instead of `notebook_page_close`.
|
If the user clicked on the buttons on the alert dialog, `alert_resoponse_cb` is invoked.
|
||||||
|
It hides the dialog and checks the `response_id`.
|
||||||
|
If it is `GTK_RESPONSE_ACCEPT`, which means user clicked on the quit button, then it calls `tfe_application_quit` to quit the application.
|
||||||
|
Otherwise it does nothing.
|
||||||
|
|
||||||
The static variables `alert`, `lb_alert` and `btn_accept` are set in the startup handler.
|
The static variables `alert`, `lb_alert` and `btn_accept` are set in the startup handler.
|
||||||
And the signal "close-request" and `dialog_close_cb` handler are connected.
|
And the signal "close-request" and `dialog_close_cb` handler are connected.
|
||||||
|
@ -592,10 +600,12 @@ And the signal "close-request" and `dialog_close_cb` handler are connected.
|
||||||
|
|
||||||
- 1-14: `has_saved` function.
|
- 1-14: `has_saved` function.
|
||||||
- 10: The function `gtk_text_buffer_get_modified` returns true if the content of the buffer has been modified since the modified flag had set false.
|
- 10: The function `gtk_text_buffer_get_modified` returns true if the content of the buffer has been modified since the modified flag had set false.
|
||||||
The flag is set to false when the buffer is generated.
|
The flag is set to false when:
|
||||||
It is reset to false when it is replaced with a new contents from a file or it is saved to a file.
|
- the buffer is created.
|
||||||
|
- the contents of the buffer is replaced
|
||||||
|
- the contents of the buffer is saved to a file.
|
||||||
- 11-13: This function returns true if the contents of the current page has been saved and no modification has been made.
|
- 11-13: This function returns true if the contents of the current page has been saved and no modification has been made.
|
||||||
If it returns false, then the user tries to close the current page without saving the modified contents.
|
It returns false, if the current page has been modified and hasn't been saved.
|
||||||
- 16-33: `has_saved_all` function.
|
- 16-33: `has_saved_all` function.
|
||||||
This function is similar to `has_saved` function.
|
This function is similar to `has_saved` function.
|
||||||
It returns true if all the pages have been saved.
|
It returns true if all the pages have been saved.
|
||||||
|
@ -655,10 +665,11 @@ When a page is built, connect "change-file" and "modified-changed" signals to `f
|
||||||
34 filename = gtk_notebook_get_tab_label_text (GTK_NOTEBOOK (nb), scr);
|
34 filename = gtk_notebook_get_tab_label_text (GTK_NOTEBOOK (nb), scr);
|
||||||
35 text = g_strdup_printf ("*%s", filename);
|
35 text = g_strdup_printf ("*%s", filename);
|
||||||
36 label = gtk_label_new (text);
|
36 label = gtk_label_new (text);
|
||||||
37 gtk_notebook_set_tab_label (GTK_NOTEBOOK (nb), scr, label);
|
37 g_free (text);
|
||||||
38 } else
|
38 gtk_notebook_set_tab_label (GTK_NOTEBOOK (nb), scr, label);
|
||||||
39 file_changed_cb (tv);
|
39 } else
|
||||||
40 }
|
40 file_changed_cb (tv);
|
||||||
|
41 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- 1-20: `file_changed_cb` handler.
|
- 1-20: `file_changed_cb` handler.
|
||||||
|
@ -667,12 +678,12 @@ That is, there's no page corresponds to `tv`.
|
||||||
Then, it isn't necessary to change the name of the tab because no tab exists.
|
Then, it isn't necessary to change the name of the tab because no tab exists.
|
||||||
- 13-15: If `file` is GFile, then it gets the filename and unrefs `file`.
|
- 13-15: If `file` is GFile, then it gets the filename and unrefs `file`.
|
||||||
- 16-17: Otherwise, `file` is probably NULL and it assigns "Untitled" related name to `filename`
|
- 16-17: Otherwise, `file` is probably NULL and it assigns "Untitled" related name to `filename`
|
||||||
- 18-19: Generates GtkLabel with `filename` and sets the tab of the page with the GtkLabel.
|
- 18-19: Creates GtkLabel with `filename` and sets the tab of the page with the GtkLabel.
|
||||||
- 22-40: `modified_changed_cb` handler.
|
- 22-41: `modified_changed_cb` handler.
|
||||||
- 31-32: If `tv` isn't a descendant of `nb`, then nothing needs to be done.
|
- 31-32: If `tv` isn't a descendant of `nb`, then nothing needs to be done.
|
||||||
- 33-35: If the content is modified, then it gets the text of the tab and adds asterisk at the beginning of the text.
|
- 33-35: If the content is modified, then it gets the text of the tab and adds asterisk at the beginning of the text.
|
||||||
- 36-37: Sets the tab with the asterisk prepended text.
|
- 36-38: Sets the tab with the asterisk prepended text.
|
||||||
- 38-39: Otherwise the modified bit is off.
|
- 39-40: Otherwise the modified bit is off.
|
||||||
It is because content is saved.
|
It is because content is saved.
|
||||||
It calls `file_changed_cb` and resets the filename, that means it leaves out the asterisk.
|
It calls `file_changed_cb` and resets the filename, that means it leaves out the asterisk.
|
||||||
|
|
||||||
|
@ -735,7 +746,7 @@ A new file `css.c` is made for functions related to CSS.
|
||||||
1 #include "tfe.h"
|
1 #include "tfe.h"
|
||||||
2
|
2
|
||||||
3 void
|
3 void
|
||||||
4 set_css_for_display (GtkWindow *win, char *css) {
|
4 set_css_for_display (GtkWindow *win, const char *css) {
|
||||||
5 GdkDisplay *display;
|
5 GdkDisplay *display;
|
||||||
6
|
6
|
||||||
7 display = gtk_widget_get_display (GTK_WIDGET (win));
|
7 display = gtk_widget_get_display (GTK_WIDGET (win));
|
||||||
|
@ -751,78 +762,79 @@ A new file `css.c` is made for functions related to CSS.
|
||||||
17 textview_css = g_strdup_printf ("textview {padding: 10px; font-family: \"%s\"; font-style: %s; font-weight: %s; font-size: %dpt;}",
|
17 textview_css = g_strdup_printf ("textview {padding: 10px; font-family: \"%s\"; font-style: %s; font-weight: %s; font-size: %dpt;}",
|
||||||
18 fontfamily, fontstyle, fontweight, fontsize);
|
18 fontfamily, fontstyle, fontweight, fontsize);
|
||||||
19 set_css_for_display (win, textview_css);
|
19 set_css_for_display (win, textview_css);
|
||||||
20 }
|
20 g_free (textview_css);
|
||||||
21
|
21 }
|
||||||
22 void
|
22
|
||||||
23 set_font_for_display_with_pango_font_desc (GtkWindow *win, PangoFontDescription *pango_font_desc) {
|
23 void
|
||||||
24 int pango_style;
|
24 set_font_for_display_with_pango_font_desc (GtkWindow *win, PangoFontDescription *pango_font_desc) {
|
||||||
25 int pango_weight;
|
25 PangoStyle pango_style;
|
||||||
26 const char *family;
|
26 PangoWeight pango_weight;
|
||||||
27 const char *style;
|
27 const char *family;
|
||||||
28 const char *weight;
|
28 const char *style;
|
||||||
29 int fontsize;
|
29 const char *weight;
|
||||||
30
|
30 int fontsize;
|
||||||
31 family = pango_font_description_get_family (pango_font_desc);
|
31
|
||||||
32 pango_style = pango_font_description_get_style (pango_font_desc);
|
32 family = pango_font_description_get_family (pango_font_desc);
|
||||||
33 switch (pango_style) {
|
33 pango_style = pango_font_description_get_style (pango_font_desc);
|
||||||
34 case PANGO_STYLE_NORMAL:
|
34 switch (pango_style) {
|
||||||
35 style = "normal";
|
35 case PANGO_STYLE_NORMAL:
|
||||||
36 break;
|
36 style = "normal";
|
||||||
37 case PANGO_STYLE_ITALIC:
|
37 break;
|
||||||
38 style = "italic";
|
38 case PANGO_STYLE_ITALIC:
|
||||||
39 break;
|
39 style = "italic";
|
||||||
40 case PANGO_STYLE_OBLIQUE:
|
40 break;
|
||||||
41 style = "oblique";
|
41 case PANGO_STYLE_OBLIQUE:
|
||||||
42 break;
|
42 style = "oblique";
|
||||||
43 default:
|
43 break;
|
||||||
44 style = "normal";
|
44 default:
|
||||||
45 break;
|
45 style = "normal";
|
||||||
46 }
|
46 break;
|
||||||
47 pango_weight = pango_font_description_get_weight (pango_font_desc);
|
47 }
|
||||||
48 switch (pango_weight) {
|
48 pango_weight = pango_font_description_get_weight (pango_font_desc);
|
||||||
49 case PANGO_WEIGHT_THIN:
|
49 switch (pango_weight) {
|
||||||
50 weight = "100";
|
50 case PANGO_WEIGHT_THIN:
|
||||||
51 break;
|
51 weight = "100";
|
||||||
52 case PANGO_WEIGHT_ULTRALIGHT:
|
52 break;
|
||||||
53 weight = "200";
|
53 case PANGO_WEIGHT_ULTRALIGHT:
|
||||||
54 break;
|
54 weight = "200";
|
||||||
55 case PANGO_WEIGHT_LIGHT:
|
55 break;
|
||||||
56 weight = "300";
|
56 case PANGO_WEIGHT_LIGHT:
|
||||||
57 break;
|
57 weight = "300";
|
||||||
58 case PANGO_WEIGHT_SEMILIGHT:
|
58 break;
|
||||||
59 weight = "350";
|
59 case PANGO_WEIGHT_SEMILIGHT:
|
||||||
60 break;
|
60 weight = "350";
|
||||||
61 case PANGO_WEIGHT_BOOK:
|
61 break;
|
||||||
62 weight = "380";
|
62 case PANGO_WEIGHT_BOOK:
|
||||||
63 break;
|
63 weight = "380";
|
||||||
64 case PANGO_WEIGHT_NORMAL:
|
64 break;
|
||||||
65 weight = "400"; /* or "normal" */
|
65 case PANGO_WEIGHT_NORMAL:
|
||||||
66 break;
|
66 weight = "400"; /* or "normal" */
|
||||||
67 case PANGO_WEIGHT_MEDIUM:
|
67 break;
|
||||||
68 weight = "500";
|
68 case PANGO_WEIGHT_MEDIUM:
|
||||||
69 break;
|
69 weight = "500";
|
||||||
70 case PANGO_WEIGHT_SEMIBOLD:
|
70 break;
|
||||||
71 weight = "600";
|
71 case PANGO_WEIGHT_SEMIBOLD:
|
||||||
72 break;
|
72 weight = "600";
|
||||||
73 case PANGO_WEIGHT_BOLD:
|
73 break;
|
||||||
74 weight = "700"; /* or "bold" */
|
74 case PANGO_WEIGHT_BOLD:
|
||||||
75 break;
|
75 weight = "700"; /* or "bold" */
|
||||||
76 case PANGO_WEIGHT_ULTRABOLD:
|
76 break;
|
||||||
77 weight = "800";
|
77 case PANGO_WEIGHT_ULTRABOLD:
|
||||||
78 break;
|
78 weight = "800";
|
||||||
79 case PANGO_WEIGHT_HEAVY:
|
79 break;
|
||||||
80 weight = "900";
|
80 case PANGO_WEIGHT_HEAVY:
|
||||||
81 break;
|
81 weight = "900";
|
||||||
82 case PANGO_WEIGHT_ULTRAHEAVY:
|
82 break;
|
||||||
83 weight = "900"; /* In PangoWeight definition, the weight is 1000. But CSS allows the weight below 900. */
|
83 case PANGO_WEIGHT_ULTRAHEAVY:
|
||||||
84 break;
|
84 weight = "900"; /* In PangoWeight definition, the weight is 1000. But CSS allows the weight below 900. */
|
||||||
85 default:
|
85 break;
|
||||||
86 weight = "normal";
|
86 default:
|
||||||
87 break;
|
87 weight = "normal";
|
||||||
88 }
|
88 break;
|
||||||
89 fontsize = pango_font_description_get_size (pango_font_desc) / PANGO_SCALE;
|
89 }
|
||||||
90 set_font_for_display (win, family, style, weight, fontsize);
|
90 fontsize = pango_font_description_get_size (pango_font_desc) / PANGO_SCALE;
|
||||||
91 }
|
91 set_font_for_display (win, family, style, weight, fontsize);
|
||||||
|
92 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- 3-11: `set_css_for_display`.
|
- 3-11: `set_css_for_display`.
|
||||||
|
@ -841,22 +853,24 @@ Bold is 700.
|
||||||
- font-size specifies the size of a font.
|
- font-size specifies the size of a font.
|
||||||
Small, medium, large and 12pt are font-size.
|
Small, medium, large and 12pt are font-size.
|
||||||
- 17: Makes CSS text.
|
- 17: Makes CSS text.
|
||||||
The function `g_strdup_printf` generates a new string with printf-like formatting.
|
The function `g_strdup_printf` creates a new string with printf-like formatting.
|
||||||
- 22-91: `set_font_for_display_with_pango_font_desc`.
|
- 23-92: `set_font_for_display_with_pango_font_desc`.
|
||||||
This function takes out font-family, font-style, font-weight and font-size from the PangoFontDescription object and calls `set_font`for_display`.
|
This function takes out font-family, font-style, font-weight and font-size from the PangoFontDescription object and calls `set_font`for_display`.
|
||||||
- 31: Gets the font-family of `pango_font_desc`.
|
- 32: Gets the font-family of `pango_font_desc`.
|
||||||
- 32-46: Gets the font-style of `pango_font_desc`.
|
- 33-47: Gets the font-style of `pango_font_desc`.
|
||||||
The functions `pango_font_description_get_style` returns an enumerated value.
|
The functions `pango_font_description_get_style` returns an enumerated value.
|
||||||
- 47-88: Gets the font-weight of `pango_font_desc`.
|
- 48-89: Gets the font-weight of `pango_font_desc`.
|
||||||
The function `pango_font_description_get_weight` returns an enumerated value.
|
The function `pango_font_description_get_weight` returns an enumerated value.
|
||||||
They corresponds to the numbers from 100 to 900.
|
They corresponds to the numbers from 100 to 900.
|
||||||
- 89: Gets the font-size of `pango_font_desc`.
|
- 90: Gets the font-size of `pango_font_desc`.
|
||||||
The function `pango_font_description_get_size` returns the size of a font.
|
The function `pango_font_description_get_size` returns the size of a font.
|
||||||
The unit of this size is (1/PANGO\_SCALE)pt.
|
The unit of this size is (1/PANGO\_SCALE)pt.
|
||||||
If the font size is 10pt, the function returns 10*PANGO\_SCALE.
|
If the font size is 10pt, the function returns 10*PANGO\_SCALE.
|
||||||
PANGO\_SCALE is defined as 1024.
|
PANGO\_SCALE is defined as 1024.
|
||||||
Therefore, 10*PANGO\_SCALE is 10240.
|
Therefore, 10*PANGO\_SCALE is 10240.
|
||||||
- 90: calls `set_font_for_display` to set CSS for the GdkDisplay.
|
- 91: calls `set_font_for_display` to set CSS for the GdkDisplay.
|
||||||
|
|
||||||
|
For further information, see [Pango reference manual](https://developer.gnome.org/pango/1.46/).
|
||||||
|
|
||||||
## GSettings
|
## GSettings
|
||||||
|
|
||||||
|
@ -920,12 +934,13 @@ It is [GVariant format string](https://developer.gnome.org/glib/stable/gvariant-
|
||||||
Other common types are:
|
Other common types are:
|
||||||
- "b": gboolean
|
- "b": gboolean
|
||||||
- "i": gint32.
|
- "i": gint32.
|
||||||
- "d": double
|
- "d": double.
|
||||||
Further information is in the website `GVariant format string` above.
|
|
||||||
|
Further information is in [Glib reference manual](https://developer.gnome.org/glib/stable/gvariant-format-strings.html).
|
||||||
|
|
||||||
### gsettings
|
### gsettings
|
||||||
|
|
||||||
First, let's try `gsetting` application.
|
First, let's try `gsettings` application.
|
||||||
It is a configuration tool for GSettings.
|
It is a configuration tool for GSettings.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
@ -1005,7 +1020,7 @@ Then, change the mode to advanced and quit.
|
||||||
|
|
||||||
![gnome-calculator advanced mode](../image/gnome_calculator_advanced.png)
|
![gnome-calculator advanced mode](../image/gnome_calculator_advanced.png)
|
||||||
|
|
||||||
Run gsettongs and check whether the value of `button-mode` changes.
|
Run gsettings and check whether the value of `button-mode` changes.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ gsettings list-recursively org.gnome.calculator
|
$ gsettings list-recursively org.gnome.calculator
|
||||||
|
@ -1018,13 +1033,13 @@ org.gnome.calculator button-mode 'advanced'
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Now we know that Gnome Calculator used gsettings and it sets `button-mode` key to "advanced" which is the current mode.
|
Now we know that Gnome Calculator used gsettings and it has set `button-mode` key to "advanced".
|
||||||
The value remains even the calculator quits.
|
The value remains even the calculator quits.
|
||||||
So when the calculator is run again, it will appear as an advanced mode calculator.
|
So when the calculator is run again, it will appear as an advanced mode calculator.
|
||||||
|
|
||||||
### glib-compile-schemas
|
### glib-compile-schemas
|
||||||
|
|
||||||
GSettings schemas are specified with XML format.
|
GSettings schemas are specified with an XML format.
|
||||||
The XML schema files must have the filename extension `.gschema.xml`.
|
The XML schema files must have the filename extension `.gschema.xml`.
|
||||||
The following is the XML schema file for the application `tfe`.
|
The following is the XML schema file for the application `tfe`.
|
||||||
|
|
||||||
|
@ -1059,7 +1074,7 @@ They are optional, but it is recommended to add them in the XML file.
|
||||||
The XML file is compiled by glib-compile-schemas.
|
The XML file is compiled by glib-compile-schemas.
|
||||||
When compiling, `glib-compile-schemas` compiles all the XML files which have ".gschema.xml" file extension in the directory given as an argument.
|
When compiling, `glib-compile-schemas` 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 `gschemas.compiled`.
|
It converts the XML file into a binary file `gschemas.compiled`.
|
||||||
Suppose the XML file above is under `tfe6`directory.
|
Suppose the XML file above is under `tfe6` directory.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ glib-compile-schemas tfe6
|
$ glib-compile-schemas tfe6
|
||||||
|
@ -1076,7 +1091,7 @@ This is because GSettings object searches `GSETTINGS_SCHEMA_DIR` for `gschemas.c
|
||||||
|
|
||||||
GSettings object looks for this file by the following process.
|
GSettings object looks for this file by the following process.
|
||||||
|
|
||||||
- It searches `glib-2.0/schemas` subdirectories of all the directories specified in the environment cariable `XDG_DATA_DIRS`.
|
- It searches `glib-2.0/schemas` subdirectories of all the directories specified in the environment variable `XDG_DATA_DIRS`.
|
||||||
Most common directory is `/usr/share/glib-2.0/schemas`.
|
Most common directory is `/usr/share/glib-2.0/schemas`.
|
||||||
- If `GSETTINGS_SCHEMA_DIR` environment variable is defined, it searches all the directories specified in the variable.
|
- If `GSETTINGS_SCHEMA_DIR` environment variable is defined, it searches all the directories specified in the variable.
|
||||||
`GSETTINGS_SCHEMA_DIR` can specify multiple directories delimited by colon (:).
|
`GSETTINGS_SCHEMA_DIR` can specify multiple directories delimited by colon (:).
|
||||||
|
@ -1085,7 +1100,7 @@ In the directories above, all the `.gschema.xml` files are stored.
|
||||||
Therefore, when you install your application, follow the instruction below to install your schemas.
|
Therefore, when you install your application, follow the instruction below to install your schemas.
|
||||||
|
|
||||||
1. Make `.gschema.xml` file.
|
1. Make `.gschema.xml` file.
|
||||||
2. Copy it to one of the directories above. For example, `/usr/share/glib-2.0/schemas`.
|
2. Copy it to one of the directories above. For example, `/usr/local/share/glib-2.0/schemas`.
|
||||||
3. Run `glib-compile-schemas` on the directory above.
|
3. Run `glib-compile-schemas` on the directory above.
|
||||||
|
|
||||||
### Meson.build
|
### Meson.build
|
||||||
|
@ -1146,18 +1161,21 @@ Then the two values will be always the same.
|
||||||
If one value changes then the other will automatically change.
|
If one value changes then the other will automatically change.
|
||||||
|
|
||||||
You need to make an effort to understand GSettings concept, but coding is very simple.
|
You need to make an effort to understand GSettings concept, but coding is very simple.
|
||||||
Just generate a GSettings object and bind it to a property of an object.
|
Just create a GSettings object and bind it to a property of an object.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed gtk4 under the instruction in Section 2.
|
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed Gtk4 from the source (See Section 2).
|
||||||
Then you need to put `--prefix=$HOME/local` option to meson like this.
|
Then you need to put `--prefix=$HOME/local` option to meson like this.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ meson --prefix=$HOME/local _build
|
$ meson --prefix=$HOME/local _build
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Modify `meson.build` abd add install option and set it true in executable function.
|
If you've installed Gtk4 from the distribution package, `--prefix` option isn't necessary.
|
||||||
|
You just install `tfe` to the default bin directory like `/usr/local/bin`.
|
||||||
|
|
||||||
|
Modify `meson.build` and add install option and set it true in executable function.
|
||||||
|
|
||||||
~~~meson
|
~~~meson
|
||||||
executable('tfe', sourcefiles, resources, dependencies: gtkdep, export_dynamic: true, install: true)
|
executable('tfe', sourcefiles, resources, dependencies: gtkdep, export_dynamic: true, install: true)
|
||||||
|
@ -1182,10 +1200,10 @@ install_data('com.github.ToshioCP.tfe.gschema.xml', install_dir: schema_dir)
|
||||||
The default value of the option 'prefix' is "/usr/local", but it is "\$HOME/local" because we have run meson with prefix option.
|
The default value of the option 'prefix' is "/usr/local", but it is "\$HOME/local" because we have run meson with prefix option.
|
||||||
The default value of the option 'datadir' is "share".
|
The default value of the option 'datadir' is "share".
|
||||||
The operator '/' connects the strings with '/' separator.
|
The operator '/' connects the strings with '/' separator.
|
||||||
So, `$HOME/local/share/glib-2.0/schemas` is assigned to the varable `schema_dir`.
|
So, `$HOME/local/share/glib-2.0/schemas` is assigned to the variable `schema_dir`.
|
||||||
- install_data: This function installs the data to the install directory.
|
- install_data: This function installs the data to the install directory.
|
||||||
|
|
||||||
Meson can runs a post compile script.
|
Meson can run a post compile script.
|
||||||
|
|
||||||
~~~meson
|
~~~meson
|
||||||
meson.add_install_script('glib-compile-schemas', schema_dir)
|
meson.add_install_script('glib-compile-schemas', schema_dir)
|
||||||
|
|
|
@ -3,7 +3,7 @@ Up: [Readme.md](../Readme.md), Prev: [Section 24](sec24.md), Next: [Section 26]
|
||||||
# GtkListView
|
# GtkListView
|
||||||
|
|
||||||
Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
||||||
The new feature is described in the sections "GListModel support" and "List-based widgets" at the top of [the third chapter of the API reference](https://developer.gnome.org/gtk4/stable/gtkobjects.html).
|
The new feature is described in the sections "GListModel support" and "List-based widgets" at the top of [the third chapter of Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/gtkobjects.html).
|
||||||
|
|
||||||
Gtk4 has other means to implement lists.
|
Gtk4 has other means to implement lists.
|
||||||
They are GtkListBox and GtkTreeView which are took over from Gtk3.
|
They are GtkListBox and GtkTreeView which are took over from Gtk3.
|
||||||
|
@ -59,7 +59,7 @@ There are functions to add items to the list or remove items from the list.
|
||||||
- `gtk_string_list_remove` removes an item from the list
|
- `gtk_string_list_remove` removes an item from the list
|
||||||
- `gtk_string_list_get_string` gets a string in the list
|
- `gtk_string_list_get_string` gets a string in the list
|
||||||
|
|
||||||
See [API document](https://developer.gnome.org/gtk4/stable/GtkStringList.html) for the further information.
|
See [Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/GtkStringList.html) for the further information.
|
||||||
|
|
||||||
I'll explain the other list objects later.
|
I'll explain the other list objects later.
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ Therefore, "gchararray" is "an array of char type", which is the same as string
|
||||||
It is used to get the type of GValue object.
|
It is used to get the type of GValue object.
|
||||||
GValue is a generic value and it can contain various type of values.
|
GValue is a generic value and it can contain various type of values.
|
||||||
For example, the type can be gboolean, gchar (char), gint (int), gfloat (float), gdouble (double), gchararray (char *) and so on.
|
For example, the type can be gboolean, gchar (char), gint (int), gfloat (float), gdouble (double), gchararray (char *) and so on.
|
||||||
For the further information, refer to GFileAttribute and GFileInfo section in [GIO API reference](https://developer.gnome.org/gio/stable/).
|
For the further information, refer to GFileAttribute and GFileInfo section in [GIO reference manual](https://developer.gnome.org/gio/stable/).
|
||||||
- closure tag has type attribute and function attribute.
|
- closure tag has type attribute and function attribute.
|
||||||
Function attribute specifies a function name and type attribute specifies the type of the return value of the function.
|
Function attribute specifies a function name and type attribute specifies the type of the return value of the function.
|
||||||
The contents of closure tag (it is between \<closure...\> and\</closure\>) is parameters of the function.
|
The contents of closure tag (it is between \<closure...\> and\</closure\>) is parameters of the function.
|
||||||
|
|
|
@ -278,7 +278,7 @@ So, the change of the text in `entry` reflects "label" in `label2` immediately.
|
||||||
|
|
||||||
Closure expression calls closure when it is evaluated.
|
Closure expression calls closure when it is evaluated.
|
||||||
A closure is a generic representation of a callback (a pointer to a function).
|
A closure is a generic representation of a callback (a pointer to a function).
|
||||||
For information about closure, see [GObject API reference](https://developer.gnome.org/gobject/stable/chapter-signal.html#closure).
|
For information about closure, see [GObject reference manual](https://developer.gnome.org/gobject/stable/chapter-signal.html#closure).
|
||||||
A closure expression is created with `gtk_cclosure_expression_new` function.
|
A closure expression is created with `gtk_cclosure_expression_new` function.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
|
|
|
@ -139,12 +139,12 @@ The function `g_signal_connect` has four arguments.
|
||||||
3. A handler function (also called callback), which needs to be casted by `G_CALLBACK`.
|
3. A handler function (also called callback), which needs to be casted by `G_CALLBACK`.
|
||||||
4. Data to pass to the handler. If no data is necessary, NULL should be given.
|
4. Data to pass to the handler. If no data is necessary, NULL should be given.
|
||||||
|
|
||||||
You can find the description of each signal in API reference.
|
You can find the description of each signal in the API reference manual.
|
||||||
For example, "activate" signal is in GApplication section in [GIO API reference](https://developer.gnome.org/gio/stable/GApplication.html#GApplication-activate).
|
For example, "activate" signal is in GApplication section in [GIO reference manual](https://developer.gnome.org/gio/stable/GApplication.html#GApplication-activate).
|
||||||
The handler function is described in it.
|
The handler function is described in it.
|
||||||
|
|
||||||
In addition, `g_signal_connect` is described in [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
In addition, `g_signal_connect` is described in [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
||||||
API reference is very important.
|
API reference manual is very important.
|
||||||
You should see and understand it to write Gtk applications.
|
You should see and understand it to write Gtk applications.
|
||||||
They are located in ['GNOME Developer Center'](https://developer.gnome.org/).
|
They are located in ['GNOME Developer Center'](https://developer.gnome.org/).
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ The change is:
|
||||||
- The fourth argument of `g_signal_connect` is changed from `NULL` to `win`.
|
- The fourth argument of `g_signal_connect` is changed from `NULL` to `win`.
|
||||||
|
|
||||||
Most important is the fourth argument of `g_signal_connect`.
|
Most important is the fourth argument of `g_signal_connect`.
|
||||||
It is described as "data to pass to handler" in the definition of `g_signal_connect` in [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
It is described as "data to pass to handler" in the definition of `g_signal_connect` in [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
||||||
Therefore, `win` which is a pointer to GtkApplicationWindow is passed to the handler as a second parameter `user_data`.
|
Therefore, `win` which is a pointer to GtkApplicationWindow is passed to the handler as a second parameter `user_data`.
|
||||||
Then, the handler cast it to a pointer to GtkWindow and call `gtk_window_destroy` to destroy the top-level window.
|
Then, the handler cast it to a pointer to GtkWindow and call `gtk_window_destroy` to destroy the top-level window.
|
||||||
Then, the application quits.
|
Then, the application quits.
|
||||||
|
|
|
@ -191,7 +191,7 @@ The string literal "Hello" has 6 bytes because the string has '\0' at the end it
|
||||||
`s` is assigned the top address of the memory.
|
`s` is assigned the top address of the memory.
|
||||||
`g_free` returns the memory to the heap area.
|
`g_free` returns the memory to the heap area.
|
||||||
|
|
||||||
`g_strdup` is described in [GLib API reference](https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-strdup).
|
`g_strdup` is described in [GLib reference manual](https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-strdup).
|
||||||
The following is extracted from the reference.
|
The following is extracted from the reference.
|
||||||
|
|
||||||
> The returned string should be freed with `g_free()` when no longer needed.
|
> The returned string should be freed with `g_free()` when no longer needed.
|
||||||
|
|
|
@ -18,7 +18,7 @@ When the program starts, we give a filename as an argument.
|
||||||
Then it opens the file and inserts its contents into the GtkTextBuffer.
|
Then it opens the file and inserts its contents into the GtkTextBuffer.
|
||||||
|
|
||||||
At the beginning of the implementation, we need to know how GtkApplication (or GApplication) recognizes arguments.
|
At the beginning of the implementation, we need to know how GtkApplication (or GApplication) recognizes arguments.
|
||||||
It is described in the [GIO API reference](https://developer.gnome.org/gio/stable/GApplication.html#GApplication.description).
|
It is described in the [GIO reference manual](https://developer.gnome.org/gio/stable/GApplication.html#GApplication.description).
|
||||||
|
|
||||||
When GtkApplication is created, a flag (its type is GApplicationFlags) is given as an argument.
|
When GtkApplication is created, a flag (its type is GApplicationFlags) is given as an argument.
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ GtkApplication *
|
||||||
gtk_application_new (const gchar *application_id, GApplicationFlags flags);
|
gtk_application_new (const gchar *application_id, GApplicationFlags flags);
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
This flag is described in the [GApplication section](https://developer.gnome.org/gio/stable/GApplication.html#GApplicationFlags) in GIO API reference.
|
This flag is described in the [GApplication section](https://developer.gnome.org/gio/stable/GApplication.html#GApplicationFlags) in GIO reference manual.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
GApplicationFlags' Members
|
GApplicationFlags' Members
|
||||||
|
@ -334,7 +334,7 @@ Therefore, the structure is like this:
|
||||||
If it is set to TRUE then the tab expands horizontally as long as possible.
|
If it is set to TRUE then the tab expands horizontally as long as possible.
|
||||||
If it is FALSE, then the width of the tab is determined by the size of the label.
|
If it is FALSE, then the width of the tab is determined by the size of the label.
|
||||||
`g_object_set` is a general function to set properties in any objects.
|
`g_object_set` is a general function to set properties in any objects.
|
||||||
See [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#g-object-set).
|
See [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#g-object-set).
|
||||||
- 49-51: If it fails to read the file, "No such file" message is outputted.
|
- 49-51: If it fails to read the file, "No such file" message is outputted.
|
||||||
Frees `filename`.
|
Frees `filename`.
|
||||||
- 52-53: If `filename` is NULL, "No valid file is given" message is outputted.
|
- 52-53: If `filename` is NULL, "No valid file is given" message is outputted.
|
||||||
|
|
|
@ -97,7 +97,7 @@ tfe_text_view_new (void) {
|
||||||
|
|
||||||
If you are curious about the background theory of this program, It's very good for you.
|
If you are curious about the background theory of this program, It's very good for you.
|
||||||
Because knowing the theory is very important for you to program GTK applications.
|
Because knowing the theory is very important for you to program GTK applications.
|
||||||
Look at [GObject API reference](https://developer.gnome.org/gobject/stable/).
|
Look at [GObject reference manual](https://developer.gnome.org/gobject/stable/).
|
||||||
All you need is described in it.
|
All you need is described in it.
|
||||||
Or, refer to [GObject tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
Or, refer to [GObject tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
||||||
However, it's a tough journey especially for beginners.
|
However, it's a tough journey especially for beginners.
|
||||||
|
|
|
@ -7,7 +7,7 @@ The table of contents are shown at the end of this abstract.
|
||||||
- Section 24 to 27 describes list model and list view (GtkListView, GtkGridView and GtkColumnView).
|
- Section 24 to 27 describes list model and list view (GtkListView, GtkGridView and GtkColumnView).
|
||||||
It also describes GtkExpression.
|
It also describes GtkExpression.
|
||||||
|
|
||||||
Please refer to [Gtk API reference](https://developer.gnome.org/gtk4/stable/index.html)
|
Please refer to [Gtk reference manual](https://developer.gnome.org/gtk4/stable/index.html)
|
||||||
and [Gnome Developer Center](https://developer.gnome.org/) for further topics.
|
and [Gnome Developer Center](https://developer.gnome.org/) for further topics.
|
||||||
|
|
||||||
This tutorial is under development and unstable.
|
This tutorial is under development and unstable.
|
||||||
|
|
|
@ -90,12 +90,14 @@ app_activate (GApplication *app, gpointer user_data) {
|
||||||
gtk_window_present (GTK_WINDOW (win));
|
gtk_window_present (GTK_WINDOW (win));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define APPLICATION_ID "com.github.ToshioCP.menu2"
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv) {
|
main (int argc, char **argv) {
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
app = gtk_application_new ("com.github.ToshioCP.menu2", G_APPLICATION_FLAGS_NONE);
|
app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
|
||||||
g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||||
|
|
||||||
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||||
|
|
|
@ -92,12 +92,14 @@ app_activate (GApplication *app, gpointer user_data) {
|
||||||
gtk_window_present (GTK_WINDOW (win));
|
gtk_window_present (GTK_WINDOW (win));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define APPLICATION_ID "com.github.ToshioCP.menu2"
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv) {
|
main (int argc, char **argv) {
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
app = gtk_application_new ("com.github.ToshioCP.menu2", G_APPLICATION_FLAGS_NONE);
|
app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
|
||||||
g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||||
|
|
||||||
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||||
|
|
|
@ -52,7 +52,7 @@ quit_activated (GSimpleAction *action, GVariant *parameter, gpointer app)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_activate (GApplication *app, gpointer user_data) {
|
app_activate (GApplication *app, gpointer user_data) {
|
||||||
GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
|
GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
|
||||||
|
|
||||||
const GActionEntry win_entries[] = {
|
const GActionEntry win_entries[] = {
|
||||||
|
@ -77,7 +77,7 @@ on_activate (GApplication *app, gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_startup (GApplication *app, gpointer user_data) {
|
app_startup (GApplication *app, gpointer user_data) {
|
||||||
GtkBuilder *builder = gtk_builder_new_from_resource ("/com/github/ToshioCP/menu3/menu3.ui");
|
GtkBuilder *builder = gtk_builder_new_from_resource ("/com/github/ToshioCP/menu3/menu3.ui");
|
||||||
GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));
|
GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));
|
||||||
|
|
||||||
|
@ -90,14 +90,16 @@ on_startup (GApplication *app, gpointer user_data) {
|
||||||
g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app);
|
g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define APPLICATION_ID "com.github.ToshioCP.menu3"
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv) {
|
main (int argc, char **argv) {
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
app = gtk_application_new ("com.github.ToshioCP.menu3", G_APPLICATION_FLAGS_NONE);
|
app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
|
||||||
g_signal_connect (app, "startup", G_CALLBACK (on_startup), NULL);
|
g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
|
||||||
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
|
g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
|
||||||
|
|
||||||
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
stat =g_application_run (G_APPLICATION (app), argc, argv);
|
||||||
g_object_unref (app);
|
g_object_unref (app);
|
||||||
|
|
|
@ -63,7 +63,7 @@ tfetextview/tfetextview.c tfe_text_view_class_init
|
||||||
The signal "change-file" has no default handler (object method handler).
|
The signal "change-file" has no default handler (object method handler).
|
||||||
You usually don't need to set a default handler.
|
You usually don't need to set a default handler.
|
||||||
If you need it, use `g_signal_new_class_handler` function.
|
If you need it, use `g_signal_new_class_handler` function.
|
||||||
See [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-new-class-handler) for further information.
|
See [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-new-class-handler) for further information.
|
||||||
- The return value of `g_signal_new` is the signal id.
|
- The return value of `g_signal_new` is the signal id.
|
||||||
The type of signal id is guint, which is the same as unsigned int.
|
The type of signal id is guint, which is the same as unsigned int.
|
||||||
It is used in the function `g_signal_emit`.
|
It is used in the function `g_signal_emit`.
|
||||||
|
@ -73,7 +73,7 @@ This signal has a parameter.
|
||||||
"open-response" signal has one parameter.
|
"open-response" signal has one parameter.
|
||||||
- 25: The type of the parameter.
|
- 25: The type of the parameter.
|
||||||
`G_TYPE_INT` is a type of integer.
|
`G_TYPE_INT` is a type of integer.
|
||||||
Such fundamental types are described in [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Type-Information.html).
|
Such fundamental types are described in [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Type-Information.html).
|
||||||
|
|
||||||
The handlers are declared as follows.
|
The handlers are declared as follows.
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ tfetextview/tfetextview.c tfe_text_view_new_with_file tfe_text_view_new
|
||||||
Just returns the value from the function `g_object_new` but casts it to the pointer to GtkWidget.
|
Just returns the value from the function `g_object_new` but casts it to the pointer to GtkWidget.
|
||||||
Initialization is done in `tfe_text_view_init` which is called in the process of `g_object_new` function.
|
Initialization is done in `tfe_text_view_init` which is called in the process of `g_object_new` function.
|
||||||
- 1-21: `tfe_text_view_new_with_file` function.
|
- 1-21: `tfe_text_view_new_with_file` function.
|
||||||
- 3: `g_return_val_if_fail` is described in [Glib API reference](https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-return-val-if-fail).
|
- 3: `g_return_val_if_fail` is described in [Glib reference manual](https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#g-return-val-if-fail).
|
||||||
It tests whether the argument `file` is a pointer to GFile.
|
It tests whether the argument `file` is a pointer to GFile.
|
||||||
If it's true, then the program goes on to the next line.
|
If it's true, then the program goes on to the next line.
|
||||||
If it's false, then it returns NULL (the second argument) immediately.
|
If it's false, then it returns NULL (the second argument) immediately.
|
||||||
|
@ -239,7 +239,7 @@ The important thing is to duplicate `tv->file`.
|
||||||
Otherwise, if the caller frees the GFile object, `tv->file` is no more guaranteed to point the GFile.
|
Otherwise, if the caller frees the GFile object, `tv->file` is no more guaranteed to point the GFile.
|
||||||
Another reason to use `g_file_dup` is that GFile isn't thread-safe.
|
Another reason to use `g_file_dup` is that GFile isn't thread-safe.
|
||||||
If you use GFile in the different thread, the duplication is necessary.
|
If you use GFile in the different thread, the duplication is necessary.
|
||||||
See [Gio API reference](https://developer.gnome.org/gio/stable/GFile.html#g-file-dup).
|
See [Gio reference manual](https://developer.gnome.org/gio/stable/GFile.html#g-file-dup).
|
||||||
|
|
||||||
## The API document and source file of tfetextview.c
|
## The API document and source file of tfetextview.c
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ On the other hand, when an instance of GObject (not GInitiallyUnowned) is create
|
||||||
And the instance has a normal reference count instead of floating reference.
|
And the instance has a normal reference count instead of floating reference.
|
||||||
|
|
||||||
If you use `g_object_unref` to an instance that has a floating reference, you need to convert the floating reference to a normal reference in advance.
|
If you use `g_object_unref` to an instance that has a floating reference, you need to convert the floating reference to a normal reference in advance.
|
||||||
See [GObject API reference manual](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#gobject-The-Base-Object-Type.description) for further information.
|
See [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#gobject-The-Base-Object-Type.description) for further information.
|
||||||
|
|
||||||
## notebook\_page\_close
|
## notebook\_page\_close
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ textview {color: yellow; ...}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Class, ID and some other things can be applied to the selector like Web CSS.
|
Class, ID and some other things can be applied to the selector like Web CSS.
|
||||||
Refer [Gtk4 API reference](https://developer.gnome.org/gtk4/stable/theming.html) for further information.
|
Refer [Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/theming.html) for further information.
|
||||||
|
|
||||||
In line 30, the CSS is a string.
|
In line 30, the CSS is a string.
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ Therefore, `act_quit` has a name "quit" and no parameter.
|
||||||
- 17: Adds the action to GtkApplication `app`.
|
- 17: Adds the action to GtkApplication `app`.
|
||||||
GtkApplication implements an interface GActionMap and GActionGroup.
|
GtkApplication implements an interface GActionMap and GActionGroup.
|
||||||
GtkApplication (GActionMap) can have a group of actions and the actions are added with the function `g_action_map_add_action`.
|
GtkApplication (GActionMap) can have a group of actions and the actions are added with the function `g_action_map_add_action`.
|
||||||
This function is described in [GMenuModel section in GIO API reference](https://developer.gnome.org/gio/stable/GActionMap.html#g-action-map-add-action).
|
This function is described in [GMenuModel section in GIO reference manual](https://developer.gnome.org/gio/stable/GActionMap.html#g-action-map-add-action).
|
||||||
- 18: Connects "activate" signal of the action and the handler `quit_activated`.
|
- 18: Connects "activate" signal of the action and the handler `quit_activated`.
|
||||||
- 20-23: Creates GMenu and GMenuItem instances.
|
- 20-23: Creates GMenu and GMenuItem instances.
|
||||||
`menubar` and `menu` are GMenu.
|
`menubar` and `menu` are GMenu.
|
||||||
|
|
|
@ -138,7 +138,7 @@ g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries,
|
||||||
The code above does:
|
The code above does:
|
||||||
|
|
||||||
- Builds the "quit" action
|
- Builds the "quit" action
|
||||||
- Connects the action and the "activate" signal handler `quit_activate`
|
- Connects the action and the "activate" signal handler `quit_activated`
|
||||||
- Adds the action to the action map `app`.
|
- Adds the action to the action map `app`.
|
||||||
|
|
||||||
The same goes for the other actions.
|
The same goes for the other actions.
|
||||||
|
@ -156,7 +156,7 @@ The code above does:
|
||||||
- Builds a "fullscreen" action and "color" action.
|
- Builds a "fullscreen" action and "color" action.
|
||||||
- Connects the "fullscreen" action and the "change-state" signal handler `fullscreen_changed`
|
- Connects the "fullscreen" action and the "change-state" signal handler `fullscreen_changed`
|
||||||
- Its initial state is set to FALSE.
|
- Its initial state is set to FALSE.
|
||||||
- Connects the "color" action and the "activate" signal handler `color_activate`
|
- Connects the "color" action and the "activate" signal handler `color_activated`
|
||||||
- Its parameter type is string and the initial value is "red".
|
- Its parameter type is string and the initial value is "red".
|
||||||
- Adds the actions to the action map `win`.
|
- Adds the actions to the action map `win`.
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ I installed Gtk4 under the directory `$HOME/local`.
|
||||||
This is a private user area.
|
This is a private user area.
|
||||||
|
|
||||||
If you want to install it in the system area, `/opt/gtk4` is one of good choices.
|
If you want to install it in the system area, `/opt/gtk4` is one of good choices.
|
||||||
[Gtk4 API Reference](https://developer.gnome.org/gtk4/stable/gtk-building.html) gives an installation example to `/opt/gtk4`.
|
[Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/gtk-building.html) gives an installation example to `/opt/gtk4`.
|
||||||
|
|
||||||
Don't install it to `/usr/local` which is the default.
|
Don't install it to `/usr/local` which is the default.
|
||||||
It is used by Ubuntu applications, which are not build on Gtk4.
|
It is used by Ubuntu applications, which are not build on Gtk4.
|
||||||
|
|
119
src/sec20.src.md
119
src/sec20.src.md
|
@ -1,7 +1,7 @@
|
||||||
# GtkMenuButton, accelerators, font, pango and gsettings
|
# GtkMenuButton, accelerators, font, pango and gsettings
|
||||||
|
|
||||||
Traditional menu structure is fine.
|
Traditional menu structure is fine.
|
||||||
However, Buttons or menu items we often use are not so many.
|
However, buttons or menu items we often use are not so many.
|
||||||
Some mightn't be clicked at all.
|
Some mightn't be clicked at all.
|
||||||
Therefore, it's a good idea to put some frequently used buttons on the toolbar and put the rest of the less frequently used operations into the menu.
|
Therefore, it's a good idea to put some frequently used buttons on the toolbar and put the rest of the less frequently used operations into the menu.
|
||||||
Such menu are often connected to GtkMenuButton.
|
Such menu are often connected to GtkMenuButton.
|
||||||
|
@ -61,11 +61,11 @@ tfe6/menu.ui
|
||||||
|
|
||||||
There are four items, "New", "Saveas", "Preference" and "Quit".
|
There are four items, "New", "Saveas", "Preference" and "Quit".
|
||||||
|
|
||||||
- New menu creates a new empty page.
|
- "New" menu creates a new empty page.
|
||||||
- Saveas menu saves the current page as a new filename.
|
- "Saveas" menu saves the current page as a new filename.
|
||||||
- Preference menu sets preference items.
|
- "Preference" menu sets preference items.
|
||||||
This version of `tfe` has only font preference.
|
This version of `tfe` has only font preference.
|
||||||
- Quit menu quits the application.
|
- "Quit" menu quits the application.
|
||||||
|
|
||||||
These four menus are not used so often.
|
These four menus are not used so often.
|
||||||
That's why they are put to the menu behind the menu button.
|
That's why they are put to the menu behind the menu button.
|
||||||
|
@ -155,7 +155,7 @@ You can define more than one accelerator keys and the list must ends with NULL (
|
||||||
If you want to do so, the array length needs to be three or more.
|
If you want to do so, the array length needs to be three or more.
|
||||||
The parser recognizes "\<control\>o", "\<Shift\>\<Alt\>F2", "\<Ctrl\>minus" and so on.
|
The parser recognizes "\<control\>o", "\<Shift\>\<Alt\>F2", "\<Ctrl\>minus" and so on.
|
||||||
If you want to use symbol key like "\<Ctrl\>-", use "\<Ctrl\>minus" instead.
|
If you want to use symbol key like "\<Ctrl\>-", use "\<Ctrl\>minus" instead.
|
||||||
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the gtk4 source code.
|
Such relation between lower case and symbol (its character code) is specified in [`gdkkeysyms.h`](https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/gdkkeysyms.h) in the Gtk4 source code.
|
||||||
|
|
||||||
## Saveas handler
|
## Saveas handler
|
||||||
|
|
||||||
|
@ -215,16 +215,17 @@ Preference dialog xml definition is added to `tfe.ui`.
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- Preference dialog is an independent dialog.
|
- Preference dialog is an independent dialog.
|
||||||
It is not a descendant widget of the top GtkApplicationwindow `win`.
|
It is not a descendant widget of the top-level GtkApplicationwindow `win`.
|
||||||
Therefore, There's no child tag of the dialog object.
|
Therefore, There's no child tag that surrounds the dialog object.
|
||||||
- There are four properties of the dialog specified.
|
- There are four properties of the dialog.
|
||||||
GtkDialog is a child object (not child widget) of GtkWindow, so it inherits all the properties from GtkWindow.
|
GtkDialog is a child object (not child widget) of GtkWindow, so it inherits all the properties from GtkWindow.
|
||||||
Title, resizable, modal and transient-for properties are inherited from GtkWindow.
|
Title, resizable, modal and transient-for properties are inherited from GtkWindow.
|
||||||
Transient-for specifies a temporary parent window, which the dialog's location is based on.
|
Transient-for specifies a temporary parent window, which the dialog's location is based on.
|
||||||
- internal-child attribute is used in the child tag above.
|
- internal-child attribute is used in the child tag above.
|
||||||
GtkDialog has a GtkBox child widget.
|
GtkDialog has a GtkBox child widget.
|
||||||
Its id is "content_area" in `gtkdialog.ui`, which is the ui file of GtkDialog in gtk4 source files.
|
Its id is "content_area" in `gtkdialog.ui`, which is the ui file of GtkDialog.
|
||||||
This box is provided to users to add content widgets in it.
|
(It is in the Gtk4 source files.)
|
||||||
|
This box is provided for users to add content widgets in it.
|
||||||
The tag `<child internal-child="content_area">` is put at the top of the contents.
|
The tag `<child internal-child="content_area">` is put at the top of the contents.
|
||||||
Then you need to specify an object tag and define its class as GtkBox and its id as content_area.
|
Then you need to specify an object tag and define its class as GtkBox and its id as content_area.
|
||||||
This object is defined in `gtkdialog.ui` but you need to define it again in the child tag.
|
This object is defined in `gtkdialog.ui` but you need to define it again in the child tag.
|
||||||
|
@ -314,7 +315,7 @@ tfe_startup (GApplication *application) {
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
The function `tfe_application_quit` destroys top level windows and quits the application.
|
The function `tfe_application_quit` destroys top-level windows and quits the application.
|
||||||
It first disconnects the handlers from the signal "close-request".
|
It first disconnects the handlers from the signal "close-request".
|
||||||
|
|
||||||
### Alert dialog
|
### Alert dialog
|
||||||
|
@ -396,8 +397,8 @@ An alert message will be inserted by the program later.
|
||||||
There are two child tags which have "action" type.
|
There are two child tags which have "action" type.
|
||||||
They are button objects located in the action area.
|
They are button objects located in the action area.
|
||||||
Action-widgets tag describes the actions of the buttons.
|
Action-widgets tag describes the actions of the buttons.
|
||||||
Btn\_cancel button emits response signal with cancel response (GTK_RESPONSE_CANCEL) if it is clicked on.
|
`btn_cancel` button emits response signal with cancel response (`GTK_RESPONSE_CANCEL`) if it is clicked on.
|
||||||
Btn\_accept button emits response signal with accept response (GTK_RESPONSE_ACCEPT) if it is clicked on.
|
`btn_accept` button emits response signal with accept response (`GTK_RESPONSE_ACCEPT`) if it is clicked on.
|
||||||
The response signal is connected to `alert_response_cb` handler.
|
The response signal is connected to `alert_response_cb` handler.
|
||||||
|
|
||||||
The alert dialog keeps alive while the application lives.
|
The alert dialog keeps alive while the application lives.
|
||||||
|
@ -427,8 +428,9 @@ close_cb (GtkNotebook *nb) {
|
||||||
... ...
|
... ...
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
close_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
close_cb (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
close_cb (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
... ...
|
... ...
|
||||||
|
@ -448,15 +450,16 @@ alert_response_cb (GtkDialog *alert, int response_id, gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
quit_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
quit_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
|
GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
|
||||||
|
|
||||||
is_quit = true;
|
is_quit = true;
|
||||||
if (has_saved_all (GTK_NOTEBOOK (nb)))
|
if (has_saved_all (nb))
|
||||||
tfe_application_quit (GTK_WINDOW (win));
|
tfe_application_quit (GTK_WINDOW (win));
|
||||||
else {
|
else {
|
||||||
gtk_label_set_text (lb_alert, "Contents aren't saved yet.\nAre you sure to quit?");
|
gtk_label_set_text (lb_alert, "Contents aren't saved yet.\nAre you sure to quit?");
|
||||||
gtk_button_set_label (close_btn_close, "Quit");
|
gtk_button_set_label (btn_accept, "Quit");
|
||||||
gtk_widget_show (GTK_WIDGET (alert));
|
gtk_widget_show (GTK_WIDGET (alert));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,20 +487,24 @@ When user clicks on the close button, `close_cb` handler is invoked.
|
||||||
The handler sets `is_quit` to false.
|
The handler sets `is_quit` to false.
|
||||||
The function `has_saved` returns true if the current page has been saved.
|
The function `has_saved` returns true if the current page has been saved.
|
||||||
If it is true, it calls `notebook_page_close` to close the current page.
|
If it is true, it calls `notebook_page_close` to close the current page.
|
||||||
Otherwise, it sets the text in the label and button, then shows the alert dialog.
|
Otherwise, it sets the message of the dialog and the label of the button, then shows the alert dialog.
|
||||||
|
|
||||||
The response signal of the dialog is connected to the handler `alert_response_cb`.
|
The response signal of the dialog is connected to the handler `alert_response_cb`.
|
||||||
It hides the dialog first.
|
It hides the dialog first.
|
||||||
Then check the response\_id.
|
Then checks the `response_id`.
|
||||||
If it is `GTK_RESPONSE_ACCEPT`, which means user clicked on the close button, then closes the current page.
|
If it is `GTK_RESPONSE_ACCEPT`, which means user clicked on the close button, then it closes the current page.
|
||||||
|
Otherwise it does nothing.
|
||||||
|
|
||||||
When user press "Ctrl-q" or clicked on the quit menu, then `quit_activated` handler is invoked.
|
When user press "Ctrl-q" or clicked on the quit menu, then `quit_activated` handler is invoked.
|
||||||
The handler sets `is_quit` to true.
|
The handler sets `is_quit` to true.
|
||||||
The function `has_saved_all` returns true if all the pages have been saved.
|
The function `has_saved_all` returns true if all the pages have been saved.
|
||||||
If it is true, it calls `tfe_application_quit` to quit the application.
|
If it is true, it calls `tfe_application_quit` to quit the application.
|
||||||
Otherwise, it sets the text in the label and button, then shows the alert dialog.
|
Otherwise, it sets the message of the dialog and the label of the button, then shows the alert dialog.
|
||||||
|
|
||||||
Now `alert_response_cb` works similar but it calls `tfe_application_quit`instead of `notebook_page_close`.
|
If the user clicked on the buttons on the alert dialog, `alert_resoponse_cb` is invoked.
|
||||||
|
It hides the dialog and checks the `response_id`.
|
||||||
|
If it is `GTK_RESPONSE_ACCEPT`, which means user clicked on the quit button, then it calls `tfe_application_quit` to quit the application.
|
||||||
|
Otherwise it does nothing.
|
||||||
|
|
||||||
The static variables `alert`, `lb_alert` and `btn_accept` are set in the startup handler.
|
The static variables `alert`, `lb_alert` and `btn_accept` are set in the startup handler.
|
||||||
And the signal "close-request" and `dialog_close_cb` handler are connected.
|
And the signal "close-request" and `dialog_close_cb` handler are connected.
|
||||||
|
@ -508,10 +515,12 @@ tfe6/tfenotebook.c has_saved has_saved_all
|
||||||
|
|
||||||
- 1-14: `has_saved` function.
|
- 1-14: `has_saved` function.
|
||||||
- 10: The function `gtk_text_buffer_get_modified` returns true if the content of the buffer has been modified since the modified flag had set false.
|
- 10: The function `gtk_text_buffer_get_modified` returns true if the content of the buffer has been modified since the modified flag had set false.
|
||||||
The flag is set to false when the buffer is generated.
|
The flag is set to false when:
|
||||||
It is reset to false when it is replaced with a new contents from a file or it is saved to a file.
|
- the buffer is created.
|
||||||
|
- the contents of the buffer is replaced
|
||||||
|
- the contents of the buffer is saved to a file.
|
||||||
- 11-13: This function returns true if the contents of the current page has been saved and no modification has been made.
|
- 11-13: This function returns true if the contents of the current page has been saved and no modification has been made.
|
||||||
If it returns false, then the user tries to close the current page without saving the modified contents.
|
It returns false, if the current page has been modified and hasn't been saved.
|
||||||
- 16-33: `has_saved_all` function.
|
- 16-33: `has_saved_all` function.
|
||||||
This function is similar to `has_saved` function.
|
This function is similar to `has_saved` function.
|
||||||
It returns true if all the pages have been saved.
|
It returns true if all the pages have been saved.
|
||||||
|
@ -544,12 +553,12 @@ That is, there's no page corresponds to `tv`.
|
||||||
Then, it isn't necessary to change the name of the tab because no tab exists.
|
Then, it isn't necessary to change the name of the tab because no tab exists.
|
||||||
- 13-15: If `file` is GFile, then it gets the filename and unrefs `file`.
|
- 13-15: If `file` is GFile, then it gets the filename and unrefs `file`.
|
||||||
- 16-17: Otherwise, `file` is probably NULL and it assigns "Untitled" related name to `filename`
|
- 16-17: Otherwise, `file` is probably NULL and it assigns "Untitled" related name to `filename`
|
||||||
- 18-19: Generates GtkLabel with `filename` and sets the tab of the page with the GtkLabel.
|
- 18-19: Creates GtkLabel with `filename` and sets the tab of the page with the GtkLabel.
|
||||||
- 22-40: `modified_changed_cb` handler.
|
- 22-41: `modified_changed_cb` handler.
|
||||||
- 31-32: If `tv` isn't a descendant of `nb`, then nothing needs to be done.
|
- 31-32: If `tv` isn't a descendant of `nb`, then nothing needs to be done.
|
||||||
- 33-35: If the content is modified, then it gets the text of the tab and adds asterisk at the beginning of the text.
|
- 33-35: If the content is modified, then it gets the text of the tab and adds asterisk at the beginning of the text.
|
||||||
- 36-37: Sets the tab with the asterisk prepended text.
|
- 36-38: Sets the tab with the asterisk prepended text.
|
||||||
- 38-39: Otherwise the modified bit is off.
|
- 39-40: Otherwise the modified bit is off.
|
||||||
It is because content is saved.
|
It is because content is saved.
|
||||||
It calls `file_changed_cb` and resets the filename, that means it leaves out the asterisk.
|
It calls `file_changed_cb` and resets the filename, that means it leaves out the asterisk.
|
||||||
|
|
||||||
|
@ -628,22 +637,24 @@ Bold is 700.
|
||||||
- font-size specifies the size of a font.
|
- font-size specifies the size of a font.
|
||||||
Small, medium, large and 12pt are font-size.
|
Small, medium, large and 12pt are font-size.
|
||||||
- 17: Makes CSS text.
|
- 17: Makes CSS text.
|
||||||
The function `g_strdup_printf` generates a new string with printf-like formatting.
|
The function `g_strdup_printf` creates a new string with printf-like formatting.
|
||||||
- 22-91: `set_font_for_display_with_pango_font_desc`.
|
- 23-92: `set_font_for_display_with_pango_font_desc`.
|
||||||
This function takes out font-family, font-style, font-weight and font-size from the PangoFontDescription object and calls `set_font`for_display`.
|
This function takes out font-family, font-style, font-weight and font-size from the PangoFontDescription object and calls `set_font`for_display`.
|
||||||
- 31: Gets the font-family of `pango_font_desc`.
|
- 32: Gets the font-family of `pango_font_desc`.
|
||||||
- 32-46: Gets the font-style of `pango_font_desc`.
|
- 33-47: Gets the font-style of `pango_font_desc`.
|
||||||
The functions `pango_font_description_get_style` returns an enumerated value.
|
The functions `pango_font_description_get_style` returns an enumerated value.
|
||||||
- 47-88: Gets the font-weight of `pango_font_desc`.
|
- 48-89: Gets the font-weight of `pango_font_desc`.
|
||||||
The function `pango_font_description_get_weight` returns an enumerated value.
|
The function `pango_font_description_get_weight` returns an enumerated value.
|
||||||
They corresponds to the numbers from 100 to 900.
|
They corresponds to the numbers from 100 to 900.
|
||||||
- 89: Gets the font-size of `pango_font_desc`.
|
- 90: Gets the font-size of `pango_font_desc`.
|
||||||
The function `pango_font_description_get_size` returns the size of a font.
|
The function `pango_font_description_get_size` returns the size of a font.
|
||||||
The unit of this size is (1/PANGO\_SCALE)pt.
|
The unit of this size is (1/PANGO\_SCALE)pt.
|
||||||
If the font size is 10pt, the function returns 10*PANGO\_SCALE.
|
If the font size is 10pt, the function returns 10*PANGO\_SCALE.
|
||||||
PANGO\_SCALE is defined as 1024.
|
PANGO\_SCALE is defined as 1024.
|
||||||
Therefore, 10*PANGO\_SCALE is 10240.
|
Therefore, 10*PANGO\_SCALE is 10240.
|
||||||
- 90: calls `set_font_for_display` to set CSS for the GdkDisplay.
|
- 91: calls `set_font_for_display` to set CSS for the GdkDisplay.
|
||||||
|
|
||||||
|
For further information, see [Pango reference manual](https://developer.gnome.org/pango/1.46/).
|
||||||
|
|
||||||
## GSettings
|
## GSettings
|
||||||
|
|
||||||
|
@ -698,12 +709,13 @@ It is [GVariant format string](https://developer.gnome.org/glib/stable/gvariant-
|
||||||
Other common types are:
|
Other common types are:
|
||||||
- "b": gboolean
|
- "b": gboolean
|
||||||
- "i": gint32.
|
- "i": gint32.
|
||||||
- "d": double
|
- "d": double.
|
||||||
Further information is in the website `GVariant format string` above.
|
|
||||||
|
Further information is in [Glib reference manual](https://developer.gnome.org/glib/stable/gvariant-format-strings.html).
|
||||||
|
|
||||||
### gsettings
|
### gsettings
|
||||||
|
|
||||||
First, let's try `gsetting` application.
|
First, let's try `gsettings` application.
|
||||||
It is a configuration tool for GSettings.
|
It is a configuration tool for GSettings.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
@ -783,7 +795,7 @@ Then, change the mode to advanced and quit.
|
||||||
|
|
||||||
![gnome-calculator advanced mode](../image/gnome_calculator_advanced.png){width=10.74cm height=7.14cm}
|
![gnome-calculator advanced mode](../image/gnome_calculator_advanced.png){width=10.74cm height=7.14cm}
|
||||||
|
|
||||||
Run gsettongs and check whether the value of `button-mode` changes.
|
Run gsettings and check whether the value of `button-mode` changes.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ gsettings list-recursively org.gnome.calculator
|
$ gsettings list-recursively org.gnome.calculator
|
||||||
|
@ -796,13 +808,13 @@ org.gnome.calculator button-mode 'advanced'
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Now we know that Gnome Calculator used gsettings and it sets `button-mode` key to "advanced" which is the current mode.
|
Now we know that Gnome Calculator used gsettings and it has set `button-mode` key to "advanced".
|
||||||
The value remains even the calculator quits.
|
The value remains even the calculator quits.
|
||||||
So when the calculator is run again, it will appear as an advanced mode calculator.
|
So when the calculator is run again, it will appear as an advanced mode calculator.
|
||||||
|
|
||||||
### glib-compile-schemas
|
### glib-compile-schemas
|
||||||
|
|
||||||
GSettings schemas are specified with XML format.
|
GSettings schemas are specified with an XML format.
|
||||||
The XML schema files must have the filename extension `.gschema.xml`.
|
The XML schema files must have the filename extension `.gschema.xml`.
|
||||||
The following is the XML schema file for the application `tfe`.
|
The following is the XML schema file for the application `tfe`.
|
||||||
|
|
||||||
|
@ -828,7 +840,7 @@ They are optional, but it is recommended to add them in the XML file.
|
||||||
The XML file is compiled by glib-compile-schemas.
|
The XML file is compiled by glib-compile-schemas.
|
||||||
When compiling, `glib-compile-schemas` compiles all the XML files which have ".gschema.xml" file extension in the directory given as an argument.
|
When compiling, `glib-compile-schemas` 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 `gschemas.compiled`.
|
It converts the XML file into a binary file `gschemas.compiled`.
|
||||||
Suppose the XML file above is under `tfe6`directory.
|
Suppose the XML file above is under `tfe6` directory.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ glib-compile-schemas tfe6
|
$ glib-compile-schemas tfe6
|
||||||
|
@ -845,7 +857,7 @@ This is because GSettings object searches `GSETTINGS_SCHEMA_DIR` for `gschemas.c
|
||||||
|
|
||||||
GSettings object looks for this file by the following process.
|
GSettings object looks for this file by the following process.
|
||||||
|
|
||||||
- It searches `glib-2.0/schemas` subdirectories of all the directories specified in the environment cariable `XDG_DATA_DIRS`.
|
- It searches `glib-2.0/schemas` subdirectories of all the directories specified in the environment variable `XDG_DATA_DIRS`.
|
||||||
Most common directory is `/usr/share/glib-2.0/schemas`.
|
Most common directory is `/usr/share/glib-2.0/schemas`.
|
||||||
- If `GSETTINGS_SCHEMA_DIR` environment variable is defined, it searches all the directories specified in the variable.
|
- If `GSETTINGS_SCHEMA_DIR` environment variable is defined, it searches all the directories specified in the variable.
|
||||||
`GSETTINGS_SCHEMA_DIR` can specify multiple directories delimited by colon (:).
|
`GSETTINGS_SCHEMA_DIR` can specify multiple directories delimited by colon (:).
|
||||||
|
@ -854,7 +866,7 @@ In the directories above, all the `.gschema.xml` files are stored.
|
||||||
Therefore, when you install your application, follow the instruction below to install your schemas.
|
Therefore, when you install your application, follow the instruction below to install your schemas.
|
||||||
|
|
||||||
1. Make `.gschema.xml` file.
|
1. Make `.gschema.xml` file.
|
||||||
2. Copy it to one of the directories above. For example, `/usr/share/glib-2.0/schemas`.
|
2. Copy it to one of the directories above. For example, `/usr/local/share/glib-2.0/schemas`.
|
||||||
3. Run `glib-compile-schemas` on the directory above.
|
3. Run `glib-compile-schemas` on the directory above.
|
||||||
|
|
||||||
### Meson.build
|
### Meson.build
|
||||||
|
@ -919,18 +931,21 @@ Then the two values will be always the same.
|
||||||
If one value changes then the other will automatically change.
|
If one value changes then the other will automatically change.
|
||||||
|
|
||||||
You need to make an effort to understand GSettings concept, but coding is very simple.
|
You need to make an effort to understand GSettings concept, but coding is very simple.
|
||||||
Just generate a GSettings object and bind it to a property of an object.
|
Just create a GSettings object and bind it to a property of an object.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed gtk4 under the instruction in Section 2.
|
It is a good idea to install your application in `$HOME/local/bin` directory if you have installed Gtk4 from the source (See Section 2).
|
||||||
Then you need to put `--prefix=$HOME/local` option to meson like this.
|
Then you need to put `--prefix=$HOME/local` option to meson like this.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
$ meson --prefix=$HOME/local _build
|
$ meson --prefix=$HOME/local _build
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Modify `meson.build` abd add install option and set it true in executable function.
|
If you've installed Gtk4 from the distribution package, `--prefix` option isn't necessary.
|
||||||
|
You just install `tfe` to the default bin directory like `/usr/local/bin`.
|
||||||
|
|
||||||
|
Modify `meson.build` and add install option and set it true in executable function.
|
||||||
|
|
||||||
@@@if gfm
|
@@@if gfm
|
||||||
~~~meson
|
~~~meson
|
||||||
|
@ -963,10 +978,10 @@ install_data('com.github.ToshioCP.tfe.gschema.xml', install_dir: schema_dir)
|
||||||
The default value of the option 'prefix' is "/usr/local", but it is "\$HOME/local" because we have run meson with prefix option.
|
The default value of the option 'prefix' is "/usr/local", but it is "\$HOME/local" because we have run meson with prefix option.
|
||||||
The default value of the option 'datadir' is "share".
|
The default value of the option 'datadir' is "share".
|
||||||
The operator '/' connects the strings with '/' separator.
|
The operator '/' connects the strings with '/' separator.
|
||||||
So, `$HOME/local/share/glib-2.0/schemas` is assigned to the varable `schema_dir`.
|
So, `$HOME/local/share/glib-2.0/schemas` is assigned to the variable `schema_dir`.
|
||||||
- install_data: This function installs the data to the install directory.
|
- install_data: This function installs the data to the install directory.
|
||||||
|
|
||||||
Meson can runs a post compile script.
|
Meson can run a post compile script.
|
||||||
|
|
||||||
@@@if gfm
|
@@@if gfm
|
||||||
~~~meson
|
~~~meson
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# GtkListView
|
# GtkListView
|
||||||
|
|
||||||
Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
Gtk4 has added new list objects GtkListView, GtkGridView and GtkColumnView.
|
||||||
The new feature is described in the sections "GListModel support" and "List-based widgets" at the top of [the third chapter of the API reference](https://developer.gnome.org/gtk4/stable/gtkobjects.html).
|
The new feature is described in the sections "GListModel support" and "List-based widgets" at the top of [the third chapter of Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/gtkobjects.html).
|
||||||
|
|
||||||
Gtk4 has other means to implement lists.
|
Gtk4 has other means to implement lists.
|
||||||
They are GtkListBox and GtkTreeView which are took over from Gtk3.
|
They are GtkListBox and GtkTreeView which are took over from Gtk3.
|
||||||
|
@ -65,7 +65,7 @@ There are functions to add items to the list or remove items from the list.
|
||||||
- `gtk_string_list_remove` removes an item from the list
|
- `gtk_string_list_remove` removes an item from the list
|
||||||
- `gtk_string_list_get_string` gets a string in the list
|
- `gtk_string_list_get_string` gets a string in the list
|
||||||
|
|
||||||
See [API document](https://developer.gnome.org/gtk4/stable/GtkStringList.html) for the further information.
|
See [Gtk4 reference manual](https://developer.gnome.org/gtk4/stable/GtkStringList.html) for the further information.
|
||||||
|
|
||||||
I'll explain the other list objects later.
|
I'll explain the other list objects later.
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ Therefore, "gchararray" is "an array of char type", which is the same as string
|
||||||
It is used to get the type of GValue object.
|
It is used to get the type of GValue object.
|
||||||
GValue is a generic value and it can contain various type of values.
|
GValue is a generic value and it can contain various type of values.
|
||||||
For example, the type can be gboolean, gchar (char), gint (int), gfloat (float), gdouble (double), gchararray (char *) and so on.
|
For example, the type can be gboolean, gchar (char), gint (int), gfloat (float), gdouble (double), gchararray (char *) and so on.
|
||||||
For the further information, refer to GFileAttribute and GFileInfo section in [GIO API reference](https://developer.gnome.org/gio/stable/).
|
For the further information, refer to GFileAttribute and GFileInfo section in [GIO reference manual](https://developer.gnome.org/gio/stable/).
|
||||||
- closure tag has type attribute and function attribute.
|
- closure tag has type attribute and function attribute.
|
||||||
Function attribute specifies a function name and type attribute specifies the type of the return value of the function.
|
Function attribute specifies a function name and type attribute specifies the type of the return value of the function.
|
||||||
The contents of closure tag (it is between \<closure...\> and\</closure\>) is parameters of the function.
|
The contents of closure tag (it is between \<closure...\> and\</closure\>) is parameters of the function.
|
||||||
|
|
|
@ -136,7 +136,7 @@ So, the change of the text in `entry` reflects "label" in `label2` immediately.
|
||||||
|
|
||||||
Closure expression calls closure when it is evaluated.
|
Closure expression calls closure when it is evaluated.
|
||||||
A closure is a generic representation of a callback (a pointer to a function).
|
A closure is a generic representation of a callback (a pointer to a function).
|
||||||
For information about closure, see [GObject API reference](https://developer.gnome.org/gobject/stable/chapter-signal.html#closure).
|
For information about closure, see [GObject reference manual](https://developer.gnome.org/gobject/stable/chapter-signal.html#closure).
|
||||||
A closure expression is created with `gtk_cclosure_expression_new` function.
|
A closure expression is created with `gtk_cclosure_expression_new` function.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
|
|
|
@ -107,12 +107,12 @@ The function `g_signal_connect` has four arguments.
|
||||||
3. A handler function (also called callback), which needs to be casted by `G_CALLBACK`.
|
3. A handler function (also called callback), which needs to be casted by `G_CALLBACK`.
|
||||||
4. Data to pass to the handler. If no data is necessary, NULL should be given.
|
4. Data to pass to the handler. If no data is necessary, NULL should be given.
|
||||||
|
|
||||||
You can find the description of each signal in API reference.
|
You can find the description of each signal in the API reference manual.
|
||||||
For example, "activate" signal is in GApplication section in [GIO API reference](https://developer.gnome.org/gio/stable/GApplication.html#GApplication-activate).
|
For example, "activate" signal is in GApplication section in [GIO reference manual](https://developer.gnome.org/gio/stable/GApplication.html#GApplication-activate).
|
||||||
The handler function is described in it.
|
The handler function is described in it.
|
||||||
|
|
||||||
In addition, `g_signal_connect` is described in [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
In addition, `g_signal_connect` is described in [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
||||||
API reference is very important.
|
API reference manual is very important.
|
||||||
You should see and understand it to write Gtk applications.
|
You should see and understand it to write Gtk applications.
|
||||||
They are located in ['GNOME Developer Center'](https://developer.gnome.org/).
|
They are located in ['GNOME Developer Center'](https://developer.gnome.org/).
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ The change is:
|
||||||
- The fourth argument of `g_signal_connect` is changed from `NULL` to `win`.
|
- The fourth argument of `g_signal_connect` is changed from `NULL` to `win`.
|
||||||
|
|
||||||
Most important is the fourth argument of `g_signal_connect`.
|
Most important is the fourth argument of `g_signal_connect`.
|
||||||
It is described as "data to pass to handler" in the definition of `g_signal_connect` in [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
It is described as "data to pass to handler" in the definition of `g_signal_connect` in [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).
|
||||||
Therefore, `win` which is a pointer to GtkApplicationWindow is passed to the handler as a second parameter `user_data`.
|
Therefore, `win` which is a pointer to GtkApplicationWindow is passed to the handler as a second parameter `user_data`.
|
||||||
Then, the handler cast it to a pointer to GtkWindow and call `gtk_window_destroy` to destroy the top-level window.
|
Then, the handler cast it to a pointer to GtkWindow and call `gtk_window_destroy` to destroy the top-level window.
|
||||||
Then, the application quits.
|
Then, the application quits.
|
||||||
|
|
|
@ -189,7 +189,7 @@ The string literal "Hello" has 6 bytes because the string has '\0' at the end it
|
||||||
`s` is assigned the top address of the memory.
|
`s` is assigned the top address of the memory.
|
||||||
`g_free` returns the memory to the heap area.
|
`g_free` returns the memory to the heap area.
|
||||||
|
|
||||||
`g_strdup` is described in [GLib API reference](https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-strdup).
|
`g_strdup` is described in [GLib reference manual](https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-strdup).
|
||||||
The following is extracted from the reference.
|
The following is extracted from the reference.
|
||||||
|
|
||||||
> The returned string should be freed with `g_free()` when no longer needed.
|
> The returned string should be freed with `g_free()` when no longer needed.
|
||||||
|
|
|
@ -16,7 +16,7 @@ When the program starts, we give a filename as an argument.
|
||||||
Then it opens the file and inserts its contents into the GtkTextBuffer.
|
Then it opens the file and inserts its contents into the GtkTextBuffer.
|
||||||
|
|
||||||
At the beginning of the implementation, we need to know how GtkApplication (or GApplication) recognizes arguments.
|
At the beginning of the implementation, we need to know how GtkApplication (or GApplication) recognizes arguments.
|
||||||
It is described in the [GIO API reference](https://developer.gnome.org/gio/stable/GApplication.html#GApplication.description).
|
It is described in the [GIO reference manual](https://developer.gnome.org/gio/stable/GApplication.html#GApplication.description).
|
||||||
|
|
||||||
When GtkApplication is created, a flag (its type is GApplicationFlags) is given as an argument.
|
When GtkApplication is created, a flag (its type is GApplicationFlags) is given as an argument.
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ GtkApplication *
|
||||||
gtk_application_new (const gchar *application_id, GApplicationFlags flags);
|
gtk_application_new (const gchar *application_id, GApplicationFlags flags);
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
This flag is described in the [GApplication section](https://developer.gnome.org/gio/stable/GApplication.html#GApplicationFlags) in GIO API reference.
|
This flag is described in the [GApplication section](https://developer.gnome.org/gio/stable/GApplication.html#GApplicationFlags) in GIO reference manual.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
GApplicationFlags' Members
|
GApplicationFlags' Members
|
||||||
|
@ -202,7 +202,7 @@ Therefore, the structure is like this:
|
||||||
If it is set to TRUE then the tab expands horizontally as long as possible.
|
If it is set to TRUE then the tab expands horizontally as long as possible.
|
||||||
If it is FALSE, then the width of the tab is determined by the size of the label.
|
If it is FALSE, then the width of the tab is determined by the size of the label.
|
||||||
`g_object_set` is a general function to set properties in any objects.
|
`g_object_set` is a general function to set properties in any objects.
|
||||||
See [GObject API reference](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#g-object-set).
|
See [GObject reference manual](https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#g-object-set).
|
||||||
- 49-51: If it fails to read the file, "No such file" message is outputted.
|
- 49-51: If it fails to read the file, "No such file" message is outputted.
|
||||||
Frees `filename`.
|
Frees `filename`.
|
||||||
- 52-53: If `filename` is NULL, "No valid file is given" message is outputted.
|
- 52-53: If `filename` is NULL, "No valid file is given" message is outputted.
|
||||||
|
|
|
@ -95,7 +95,7 @@ tfe_text_view_new (void) {
|
||||||
|
|
||||||
If you are curious about the background theory of this program, It's very good for you.
|
If you are curious about the background theory of this program, It's very good for you.
|
||||||
Because knowing the theory is very important for you to program GTK applications.
|
Because knowing the theory is very important for you to program GTK applications.
|
||||||
Look at [GObject API reference](https://developer.gnome.org/gobject/stable/).
|
Look at [GObject reference manual](https://developer.gnome.org/gobject/stable/).
|
||||||
All you need is described in it.
|
All you need is described in it.
|
||||||
Or, refer to [GObject tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
Or, refer to [GObject tutorial](https://github.com/ToshioCP/Gobject-tutorial).
|
||||||
However, it's a tough journey especially for beginners.
|
However, it's a tough journey especially for beginners.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "tfe.h"
|
#include "tfe.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
set_css_for_display (GtkWindow *win, char *css) {
|
set_css_for_display (GtkWindow *win, const char *css) {
|
||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
|
|
||||||
display = gtk_widget_get_display (GTK_WIDGET (win));
|
display = gtk_widget_get_display (GTK_WIDGET (win));
|
||||||
|
@ -17,12 +17,13 @@ set_font_for_display (GtkWindow *win, const char *fontfamily, const char *fontst
|
||||||
textview_css = g_strdup_printf ("textview {padding: 10px; font-family: \"%s\"; font-style: %s; font-weight: %s; font-size: %dpt;}",
|
textview_css = g_strdup_printf ("textview {padding: 10px; font-family: \"%s\"; font-style: %s; font-weight: %s; font-size: %dpt;}",
|
||||||
fontfamily, fontstyle, fontweight, fontsize);
|
fontfamily, fontstyle, fontweight, fontsize);
|
||||||
set_css_for_display (win, textview_css);
|
set_css_for_display (win, textview_css);
|
||||||
|
g_free (textview_css);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_font_for_display_with_pango_font_desc (GtkWindow *win, PangoFontDescription *pango_font_desc) {
|
set_font_for_display_with_pango_font_desc (GtkWindow *win, PangoFontDescription *pango_font_desc) {
|
||||||
int pango_style;
|
PangoStyle pango_style;
|
||||||
int pango_weight;
|
PangoWeight pango_weight;
|
||||||
const char *family;
|
const char *family;
|
||||||
const char *style;
|
const char *style;
|
||||||
const char *weight;
|
const char *weight;
|
||||||
|
|
|
@ -36,28 +36,33 @@ close_cb (GtkNotebook *nb) {
|
||||||
|
|
||||||
/* ----- menu or accelerator => action => handlers ----- */
|
/* ----- menu or accelerator => action => handlers ----- */
|
||||||
static void
|
static void
|
||||||
open_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
open_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
open_cb (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
open_cb (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
save_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
save_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
save_cb (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
save_cb (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
close_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
close_cb (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
close_cb (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
new_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
new_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
notebook_page_new (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
notebook_page_new (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
saveas_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
saveas_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
notebook_page_saveas (GTK_NOTEBOOK (nb));
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
|
notebook_page_saveas (nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -76,7 +81,7 @@ font_set_cb (GtkFontButton *fontbtn, gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pref_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
pref_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
gtk_widget_show (GTK_WIDGET (pref));
|
gtk_widget_show (GTK_WIDGET (pref));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,11 +100,12 @@ alert_response_cb (GtkDialog *alert, int response_id, gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
quit_activated (GSimpleAction *action, GVariant *parameter, gpointer nb) {
|
quit_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||||
|
GtkNotebook *nb = GTK_NOTEBOOK (user_data);
|
||||||
GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
|
GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (nb), GTK_TYPE_WINDOW);
|
||||||
|
|
||||||
is_quit = true;
|
is_quit = true;
|
||||||
if (has_saved_all (GTK_NOTEBOOK (nb)))
|
if (has_saved_all (nb))
|
||||||
tfe_application_quit (GTK_WINDOW (win));
|
tfe_application_quit (GTK_WINDOW (win));
|
||||||
else {
|
else {
|
||||||
gtk_label_set_text (lb_alert, "Contents aren't saved yet.\nAre you sure to quit?");
|
gtk_label_set_text (lb_alert, "Contents aren't saved yet.\nAre you sure to quit?");
|
||||||
|
|
|
@ -58,6 +58,7 @@ modified_changed_cb (GtkTextBuffer *tb, gpointer user_data) {
|
||||||
filename = gtk_notebook_get_tab_label_text (GTK_NOTEBOOK (nb), scr);
|
filename = gtk_notebook_get_tab_label_text (GTK_NOTEBOOK (nb), scr);
|
||||||
text = g_strdup_printf ("*%s", filename);
|
text = g_strdup_printf ("*%s", filename);
|
||||||
label = gtk_label_new (text);
|
label = gtk_label_new (text);
|
||||||
|
g_free (text);
|
||||||
gtk_notebook_set_tab_label (GTK_NOTEBOOK (nb), scr, label);
|
gtk_notebook_set_tab_label (GTK_NOTEBOOK (nb), scr, label);
|
||||||
} else
|
} else
|
||||||
file_changed_cb (tv);
|
file_changed_cb (tv);
|
||||||
|
|
Loading…
Add table
Reference in a new issue