Etnablog.altervista.org :)

Visitatore: 1313294
Welcome ospite
Menu di accessibilità:
Dimensione carattere:

Home > Programmazione C > Ruotatore automatico di tutte le foto in una cartella...con GUI GTK!
Contenuto della pagina:
20 Luglio 2007

Ruotatore automatico di tutte le foto in una cartella...con GUI GTK!

Il mio primo VERO programma in C :) 

Questo è il mio primo vero programma in C.

In sostanza si tratta di un programma che vi permette di scegliere, con una comoda interfaccia in GTK, una cartella del vostro PC, e di applicare, sulla cartella scelta, il comando di autorotazione delle foto di cui vi ho parlato la scorsa volta.

Sembra funzionare bene.

Il programma COMPILATO e anche i SORGENTI COMPLETI sono scaricabili da qui:

http://etnablog.altervista.org/m isc/script-c/gira_tutte_le_foto_con_gui. tar.gz

Vi ricordo che perchè il programma possa funzionare, è necessario installare da Synaptic il comando "jhead".

In realtà, quel codice è per me un buon esercizio e riferimento su come:
- Creare una interfaccia con GLADE e GTK da cui scegliere una CARTELLA e NON un FILE.
- Eseguire da una GUI un comando per SHELL.
- Concatenare stringhe e farne un "escape" degli apici (caratteri "pericolosi"..).
- Usare gprintf e la sua gprintf.h
- Superare un errore di tipo "incompatible pointer type".
- Tenere conto della codifica UTF-8 delle GTK.
- eliminare gnome.h in favore invece di gtk/gtk.h . Non so bene perchè ma preferisco non usarlo..

Se avete qualche consiglio su come migliorarlo...
Eccovi il codice principale. Lo scrivo qui per tante ragioni, tra cui il fatto che così sarà indicizzato, oltre che dai motori di ricerca, anche dal motore di ricerca interno al sito:


/* Created by Anjuta version 1.2.4a */
/*	This file will not be overwritten */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gtk/gtk.h>
#include <stdlib.h>
#include <glade/glade.h>
#include <glib/gprintf.h>
/*
    NELLA GUIDA DI RIFERIMENTO DELLE GLIB SI LEGGE:
	"Note that the functions g_printf(), g_fprintf(), g_sprintf(), g_snprintf(), g_vprintf(), g_vfprintf(), g_vsprintf() 
	and g_vsnprintf() are declared in the header gprintf.h which is not included in glib.h 
	(otherwise using glib.h would drag in stdio.h), so you'll have to explicitly include <glib/gprintf.h> 
	in order to use the GLib printf() functions.
*/

//gchar selezione[]= "";
gchar* selezione = NULL; 
/* 
   INVECE DI METTERE gchar* selezione = NULL; 
   PRIMA AVEVO USATO: gchar* selezione = g_strdup("a string"); 
   NE OTTENEVO UN ERRORE IN COMPILAZIONE: Il C non ammette di inizializzare variabili con una funzione
*/


void
on_button1_clicked (GtkButton *button, gpointer user_data)
{
	/* 
	     Avevo scritto:
	     GtkWidget *window1;
	     window1 = gtk_widget_get_toplevel(button);
	     compilando mi dava un warning: passing argument 1 of 'gtk_widget_toplevel' from incompatible pointer type.
	     Questo perchè ho passato un GtkButton* invece di un GtkWidget*. 
	     Ho risolto il problema facendo un "casting" con GTK_WIDGET.
	*/
	
	GtkWidget *window1 = gtk_widget_get_toplevel(GTK_WIDGET (button));
	
	gchar *filename;
	
	GtkWidget *dialog;

   dialog = gtk_file_chooser_dialog_new ("Open File",
				      GTK_WINDOW (window1),
				      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
				      NULL);
  /* 
      Anzichè scrivere GTK_WINDOW(window1) prima c'era scritto solo "window1", e beccavo un warning in compilazione tipo "incompatible pointer type"..
	  Ho risolto facendo il casting con GTK_WINDOW.
	  Se vedi nella guida di riferimento delle gtk vedi che la sintassi di gtk_file_chooser_dialog_new è:
	  GtkWidget* gtk_file_chooser_dialog_new (const gchar *title, GtkWindow *parent, GtkFileChooserAction action,const gchar *first_button_text, ...);
	  
	  Passando solo window1 passavo un GtkWidget e NON la "parent window".
  */
     


   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
     {

		  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); 

		 /*
		      AVREI POTUTO USARE:
		      filename = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); 

		      gtk_file_chooser_get_uri OTTIENE IL FILE PER "URI". Gli spazi vengono sostituiti, ad esempio, da "%20".
		      Ottenere il valore per URI sarebbe utile per un fatto di sicurezza, nel caso avrei dovuto passare il file a fopen (ad esempio).
		      Nel nostro caso invece, il file lo passerò a g_spawn_sync (vedi piu avanti)
		 */
		 
		 selezione = g_strdup(filename);
		  /*
		      PER SETTARE "SELEZIONE" PRIMA AVEVO USATO strcpy(selezione, "pippoasdfasdf");
		      POI MI AVEVANO CONSIGLIATO INVECE DI USARE:
		 	  sprintf(selezione, "%s", filename); 
		      ALL'INIZIO DEL PROGRAMMA PERO' "selezione" era inizializzata così: gchar selezione[]= "";
		      QUINDI NON AVEVO UN PUNTATORE COME ADESSO

		      SINTASSI: int sprintf(char *str, const char *format, ...);
		      La funzione sprintf() differisce dalla funzione printf()  in quanto i caratteri vengono scritti nell'area puntata da str.
		 
		      AVREI POTUTO USARE, AL POSTO DI SPRINTF, ANCHE IL COMANDO:
		      strcpy(selezione, filename);
		      STRCPY FUNZIONA COSI':
		      SINTASSI: ptr = strcpy( s1, s2 );
		      La funzione strcpy() copia la stringa s1 sull'area puntata da s2 la quale deve essere sufficientemente ampia ad accogliere tutti i caratteri di s1 compreso il terminatore '&#65533;'.
		 
		 */
       g_printf("DIRECTORY SELEZIONATA: %s n", selezione);
     }
   else filename = "";
	  
 
   gtk_widget_destroy (dialog);
	
	/*  Ho preferito ricercare la GtkLabel a partire da window1, per esigenze di "esperimento", 
	*   ma avrei potuto direttamente scrivere:
	*   GladeXML *self = glade_get_widget_tree(GTK_WIDGET(button));
    */
    GladeXML *self = glade_get_widget_tree(GTK_WIDGET(window1));
	GtkWidget *label = glade_xml_get_widget (self, "etichetta");
   
   filename = g_filename_display_name (filename);
      /*
   			Voglio stampare a video il file ottenuto. 
            Le GUI GTK, in generale, usano la codifica UTF-8 ma l'encoding dell'utente potrebbe non essere UTF-8, e così 
            anche i nomi dei suoi file potrebbero non essere UTF-8.
            Quindi bisogna assicurarsi di convertire il nome del file ottenuto in UTF-8 per essere certi di mostrarlo a video correttamente.
            Usiamo allora il comando g_filename_display_name che ha questa sintassi:
            gchar*      g_filename_display_name         (const gchar *filename);
     */

	gtk_label_set_text (GTK_LABEL(label), filename);
   
 
}

void
on_button_ruota_clicked (GtkButton *button, gpointer user_data)
{
	
	/* 
	     IL COMANDO CHE PASSERO' ALLA SHELL E': 
	
		 find 'percorso/cartella' -type f -iname '*.jpg' -print0 | xargs -0 jhead -autorot
	
	     -print0: i singoli file restituiti da find verranno passati ad xargs in modo che vengano correttamente interpretati nonostante vi siano spazi vuoti o apici in mezzo.
         Print0 separa i singoli file da un carattere speciale detto "NULL", in modo che xargs non faccia confusione tra spazi bianchi nei nomi dei file e la separazione dei file stessi.
         Se find trova troppi file si corre il rischio che la stringa sia troppo lunga ed ecceda il limite di caratteri ammesso nella riga di comando.
         Per questo motivo usiamo xargs che se la sbrigherà lui a fare in modo che questo non succeda. Inoltre, tramite il parametro -0, diciamo ad xargs che riconosca i singoli file perchè separati da un carattere "NULL". Per questo prima abbiamo usato -print0!
   */
	
	gchar* selezione_escape = g_shell_quote (selezione);
    gchar* comando = g_strconcat("find ", selezione_escape," -type f -iname '*.jpg' -print0 | xargs -0 jhead -autorot", NULL);
	g_printf("COMANDO ESEGUITO: %s nn", comando);

	
	system(comando);	
	/*
	     Il comando system esegue su shell un comando. Piu o meno allo stesso scopo possono servire anche i comandi
	     g_spawn_sync e g_spawn_command_line_sync. Non sono riuscito ad implementarli con successo.
	 */

}

int main (int argc, char *argv[])
{
	GtkWidget *window1, *button1, *button_ruota;
	GladeXML *xml;
	
	if (selezione == "" || selezione == NULL) g_printf("SELEZIONE ATTUALE: NESSUNAn");
	else g_printf("SELEZIONE ATTUALE: %s n", selezione);
	
	
    // PACKAGE è definito in config.h
	//gnome_init (PACKAGE, VERSION, argc, argv);
	gtk_init (&argc, &argv);
	//glade_gnome_init ();

	
	
	xml = glade_xml_new ("gira_tutte_le_foto_con_gui.glade", NULL, NULL);

	/* Ho ESCLUSO l'autoconnect, faccio le callback manualmente */
	// glade_xml_signal_autoconnect (xml);
	window1 = glade_xml_get_widget (xml, "window1");

	button1 = glade_xml_get_widget (xml, "button1");

	g_signal_connect (G_OBJECT (button1), "clicked",
                    G_CALLBACK (on_button1_clicked),
                    NULL);
	

	
	button_ruota = glade_xml_get_widget (xml, "button_ruota");

    g_signal_connect (G_OBJECT (button_ruota), "clicked",
                    G_CALLBACK (on_button_ruota_clicked),
                    selezione);

    g_signal_connect (G_OBJECT (window1), "delete_event",
                    G_CALLBACK (gtk_main_quit), NULL);
	
	 gtk_widget_show (window1);


	gtk_main ();
	
	return 0;
}

Descrizioni usate nelle foto: 
Postato da: Etnablog in Programmazione C alle 22:41

Permalink | Commenti(0)
Inserisci commento

Commenti:

Nessun commento. Vuoi essere il primo?
Solo gli utenti registrati possono lasciare commenti
*1 user online
Caricamento pagina: 0.02 s