IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

GTK+ par l'exemple


précédentsommairesuivant

VIII. Sauvegarder les modifications

VIII-A. Aperçu

Image non disponible
Cliquez pour agrandir

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 :

main.c
Sélectionnez
  {
    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 :

callback.c
Sélectionnez
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 :

callback.c
Sélectionnez
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 :

callback.c
Sélectionnez
        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 :

callback.c
Sélectionnez
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.

VIII-D. Code source


précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006-2008 Nicolas Joseph. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.