VIII. Sauvegarder les modifications▲
VIII-A. Aperçu▲
VIII-B. Enregistrer▲
Avant de pouvoir sauvegarder un document, il faut qu'il soit modifié. Comment savoir que le contenu du fichier a été modifié ? Grâce au signal changed du GtkTextBuffer que nous interceptons grâce à la fonction cb_modifie :
{
GtkTextBuffer *
p_text_buffer =
NULL
;
p_text_buffer =
gtk_text_view_get_buffer (
GTK_TEXT_VIEW (
p_text_view));
g_signal_connect (
G_OBJECT (
p_text_buffer), "
changed
"
, G_CALLBACK (
cb_modifie), NULL
);
}
Cette dernière modifie simplement le champ sauve du document :
void
cb_modifie (
GtkWidget *
p_widget, gpointer user_data)
{
if
(
docs.actif)
{
docs.actif->
sauve =
FALSE;
}
}
Pour la sauvegarde, il faut distinguer deux cas : soit il s'agit de la première sauvegarde du fichier, il faut alors demander le nom du fichier à l'utilisateur (cela ressemble fortement à l'ouverture d'un fichier), soit le fichier est déjà présent sur le disque, il suffit de remplacer son contenu par celui du GtkTextViewer. Nous avons convenu qu'un fichier qui n'était pas encore enregistré avait sa propriété chemin à NULL.
Bien sûr cela n'a lieu que si un fichier est ouvert et qu'il a été modifié depuis sa dernière sauvegarde :
void
cb_save (
GtkWidget *
p_widget, gpointer user_data)
{
if
(
docs.actif)
{
if
(!
docs.actif->
sauve)
{
/* Le fichier n'a pas encore ete enregistre */
if
(!
docs.actif->
chemin)
{
GtkWidget *
p_dialog =
NULL
;
p_dialog =
gtk_file_chooser_dialog_new (
"
Sauvegarder le fichier
"
, NULL
,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL
);
if
(
gtk_dialog_run (
GTK_DIALOG (
p_dialog)) ==
GTK_RESPONSE_ACCEPT)
{
docs.actif->
chemin =
gtk_file_chooser_get_filename (
GTK_FILE_CHOOSER (
p_dialog));
}
gtk_widget_destroy (
p_dialog);
}
/* Soit le fichier a deja ete enregistre, soit l'utilisateur vient de nous
fournir son nouvel emplacement, on peut donc l'enregistrer */
if
(
docs.actif->
chemin)
{
/* ... */
}
}
}
else
{
print_warning (
"
Aucun document ouvert
"
);
}
}
Il nous reste plus qu'à récupérer le contenu du GtkTextViewer et le copier dans le fichier chemin sans oublier de reconvertir le texte dans le codage local :
FILE *
fichier =
NULL
;
fichier =
fopen (
docs.actif->
chemin, "
w
"
);
if
(
fichier)
{
gchar *
contents =
NULL
;
gchar *
locale =
NULL
;
GtkTextIter start;
GtkTextIter end;
GtkTextBuffer *
p_text_buffer =
NULL
;
p_text_buffer =
gtk_text_view_get_buffer (
docs.actif->
p_text_view);
gtk_text_buffer_get_bounds (
p_text_buffer, &
start, &
end);
contents =
gtk_text_buffer_get_text (
p_text_buffer, &
start, &
end, FALSE);
locale =
g_locale_from_utf8 (
contents, -
1
, NULL
, NULL
, NULL
);
g_free (
contents), contents =
NULL
;
fprintf (
fichier, "
%s
"
, locale);
g_free (
locale), locale =
NULL
;
fclose (
fichier), fichier =
NULL
;
docs.actif->
sauve =
TRUE;
}
else
{
print_warning (
"
Impossible de sauvegarder le fichier %s
"
, docs.actif->
chemin);
}
Le dernier paramètre de la fonction gtk_text_buffer_get_text est mis à FALSE, car nous ne voulons pas enregistrer les caractères invisibles présents dans le GtkTextBuffer. Ces caractères servent à mettre en forme le texte (taille, couleur…), nous pourrions créer un nouveau format de fichier pour enregistrer la mise en forme.
VIII-C. Enregistrer sous▲
Pour enregistrer notre document sous un autre nom, il suffit de faire croire à cb_save que le document n'a pas encore était enregistré, tout simplement en changeant chemin à NULL et sauve à FALSE :
void
cb_saveas (
GtkWidget *
p_widget, gpointer user_data)
{
if
(
docs.actif)
{
document_t tmp =
*
docs.actif;
docs.actif->
chemin =
NULL
;
docs.actif->
sauve =
FALSE;
cb_save (
p_widget, user_data);
if
(!
docs.actif->
sauve)
{
(*
docs.actif) =
tmp;
}
}
else
{
print_warning (
"
Aucun document ouvert
"
);
}
}
Il ne faut pas oublier que l'utilisateur peut annuler l'enregistrement, de ce fait, nous sauvegardons l'état du document et si la sauvegarde n'a pas eu lieu, on le restaure.