Outils pour utilisateurs

Outils du site


issue223:gtk4

Ceci est une ancienne révision du document !


In the previous article a contact class which inherited from GObject was created and used to add some fictitious contacts to a GListStore so that they could be viewed using GtkColumnView. This article shows how to expand the application into a simple address book. This requires that a new contact can be created and a selected contact deleted. A contacts list needs to be maintained which can be automatically saved to disk and opened when the application is restarted. A screenshot of the application is shown below which has been developed using Ubuntu 24.04. Again fictitious individuals, Mr Jellyfish, Mr Puffin, Mrs Fossa and Mr Numbat named after Ubuntu releases will be used. The full source code for this project and can be downloaded using the web link: https://github.com/crispinprojects/fullcircle Open and view the files person-contact.h, person-contact.c and main.c file to follow the explanation below. The main.c file is updated from the last article.

Saving Contacts A way is needed to save contacts stored in the GListStore so that when the application is closed data has been saved to disk. In this example contact details will be saved to a .csv file. The extension “csv” stands for comma-separated value. With a .csv file each line in the file represents a contact record and the values (e.g. the name, email and phone fields) within each record are separated by commas. This format is easily viewed using a text editor or spreadsheet. However, in a data-intensive system a database would be used as these are more efficient. With a .csv file all the data has to be read in before it can be used but with a database a query can be made to read in a portion of the data that is required. The code for saving a GListStore of contacts to a .csv file is shown on the next page. GFile is an identifier for a file and is constructed using g_file_new_for_path() which takes one parameter, a string containing the path for the file to be opened. In this case a file called “contacts.csv” is saved to the current working directory. A data output stream is created for writing data directly to a file output stream. This is done using GDataOutputStream and GFileOutputStream. The code iterates over the store getting each item from the store, extracting the name, email and phone values using g_object_get() and then concatenates these to a single line of text separating each value with a comma. Each line is then saved using GDataOutputStream.

Creating New Contacts A new button called button_new_contact is created within the activate() function and then added to the window header. The g_signal_connect() function connects the button clicked signal to the callback called “callbk_new_contact” using the store as the gpointer parameter. GtkWidget *button_new_contact; button_new_contact = gtk_button_new_with_label(“New Contact”); g_signal_connect(button_new_contact, “clicked”, G_CALLBACK(callbk_new_contact), store); Within “callbk_new_contact” a dialog window is created and entry widgets are used for capturing the contact name, email and phone. Inspecting the code in the download shows that the positioning of widgets is handled with a box container. Widgets are appended to a box container which is a child of the dialog window. Pressing the “Add Contact” button invokes the callback called “callbk_add_new_contact”.

The function g_object_set_data() allows an association to be made between the “button_add” and the entry called “entry_name” using the key parameter named “entry-name-key” as shown below. g_object_set_data(G_OBJECT(button_add), “entry-name-key”,entry_name); This allows the GtkWidget pointer called entry_name to be obtained in the add new contact callback using the code line shown below. GtkWidget *entry_name = g_object_get_data(G_OBJECT(button), “entry-name-key”); The same approach is used to make associations between the “button_add” and the email and phone entries. A new contact is created using g_object_new(). Then g_object_set() is used to set the values for the person name, email address and phone details from the text retrieved from the entry widgets. The code snip below shows how this is done.

PersonContact *contact_new= g_object_new(PERSON_TYPE_CONTACT,0); g_object_set (contact_new, “name”, name, NULL); g_object_set (contact_new, “email”, email, NULL); g_object_set (contact_new, “phone”, phone_str, NULL); g_list_store_append(store,contact_new); save_contacts(store); The new contact is appended to the GListStore and the “save_contacts()” method is called to update the saved contacts. Opening Contacts When the application is closed the contacts remain saved in the “contacts.csv” file located in the working directory. When the application is restarted a method is needed within activate() to open the saved contacts and load them into a GListStore so that they can be displayed using the GtkColumnView widget. Inspecting the code in the download shows that this is done using the open_contacts() method which returns a pointer to a GListStore. The g_file_read() function is used with the GFile pointer to open the “contacts.csv” file for reading. The “contacts.csv” file is assumed to be located in the working directory. A GFileInputStream is used to read the contents of the file. A check is made to ensure that the file stream exists and, if not, NULL is returned.

A GListStore pointer called store is declared and g_list_store_new() is used to create a new GListStore with items of type G_TYPE_OBJECT which is the fundamental type for GObject. Then g_data_input_stream_new() is used to create a new data input stream for the file input stream. This allows g_data_input_stream_read_line() to be used to read a line from the data input stream. A while loop is used to read the data lines one by one from the “contacts.csv” file. The C string token function called strtok() is used to break each line string into pieces representing the name, email and phone fields. Each piece of data is separated by a comma and so a comma is used as the delimiter i.e. break character. With strtok() the first parameter is the string and the second is the delimiter and it returns a char pointer to the occurrence of each piece of data. There are three pieces of data which are the field’s name, email and phone and so strtok() is called three times for each line. Notice in subsequent strtok() calls the first parameter is a null pointer to ensure that the position after the end of the last token is used as the new starting location for scanning. See the strtok() documentation in the external links for more information.

Selection Everything can now be glued together to create a simple address book application to store contacts. A GtkSingleSelection *selection pointer can be created and used to select a single contact in the column_view so that it can be deleted. This is done by passing the selection pointer to a callback. An example is shown below for a button to delete a selected contact when clicked. button_delete_contact = gtk_button_new_with_label(“Delete Contact”); g_signal_connect(button_delete_contact, “clicked”, G_CALLBACK(callbk_delete_contact), selection); The selection pointer allows the index position “p” of a contact to be obtained as shown below. guint p = gtk_single_selection_get_selected((GtkSingleSelection*) selection); The index position can then be used to remove a contact from the GListStore using g_list_store_remove(). The save_contacts() method is called after a contact has been removed so that it is no longer saved in the “contacts.csv “ data file. The same selection approach can be used to expand the application so that a contact can be edited.

Use the Makefile in the download to build the application which produces an executable called “addressbook”. Hopefully these articles and code examples have provided enough information to get started with GTK4 programming in C. External Links GListStore https://docs.gtk.org/gio/class.ListStore.html strtok to split a string into tokens https://cplusplus.com/reference/cstring/strtok/

issue223/gtk4.1764576252.txt.gz · Dernière modification : 2025/12/01 09:04 de d52fr