#include <string.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
typedef struct state {
int started;
int stopped;
char path[256];
no no no :-) non usare *mai* un array a dimensione fissa per una stringa inserita dall'utente: rischi memory corruption e buffer overflow. Usa cahr *path e allocalo dinamicamente
GladeXML *main_window;
questo va bene, io personalemente di solito pero non tengo in memoria tutto l'oggetto GladeXML ma estraggo direttamente (nel tuo caso in main()) i puntatori alle widget che mi interessano e tengo quelli nella struct. In questo modo posso fare l'unref di GladeXML e non tenere in memoria tutto l'oggetto che parsifica l'xml.
} t_state;
t_state e' un po' troppo generico come nome, rischi problemi di conflitto (C non ha i namespace) inoltre la convenzione in gtk e' di usare CamelCase per i tipi
void on_start_clicked(GtkButton *button, gpointer user_data);
void on_browse_clicked(GtkButton *button, gpointer user_data);
void on_save_clicked(GtkButton *button, gpointer user_data);
void on_clear_clicked(GtkButton *button, gpointer user_data);
void on_help_clicked(GtkButton *button, gpointer user_data);
void t_state_set_started(int started);
void t_state_set_stopped(int stopped);
void t_state_set_path(t_state *data, char *path);
int t_state_get_started();
int t_state_get_stopped();
char *t_state_get_path();
GladeXML *t_state_get_glade_xml(t_state *data);
notazione di stile: io preferisco evitare i prototipi di tutte le funzioni all'inizio del file, sono inutili e significa solo che devi cambiare il codice in due posti... ordinando le funzioni in modo sensato li puoi evitare
void t_state_set_path(t_state *data, char *path)
{
strcpy(data->path, path);
}
come dicevo, alloca la stringa:
g_free (data->path);
data->path = g_strdup (path);
inoltre la funzione deve essere marcata static, dato che e' un metodo interno, privato a questo file.
GladeXML *t_state_get_glade_xml(t_state *data)
{
return data->main_window;
}
se non ti serve al di fuori di questo filem, questa getter e' eccessiva (e comunque dovrebber essere static).
All'interno del file, usare semplicemente data->main_window va bene.
Se invece ti servisse all'esterno di questo file, io non credo che esporre questa getter sia una buona idea: GladeXML e' un dettaglio implementativo privato a questo file... se ad esempio all'esterno avessero bisogno di accedere al bottone Clear, la getter dovrebbe essere
get_clear_button ()
{
GtkWidget *button = glade_xml_get_widget(data->main_window, "clear");
return button;
}
oppure se fai come ti consiglio e nello stato metti direttamente le widgets
{
return data->clear_button;
}
in questo modo dall'esterno non si ha accesso all'oggetto GladeXML
void on_browse_clicked(GtkButton *button, gpointer data)
{
GladeXML *main_window = t_state_get_glade_xml(data);
GtkWidget *window1 = glade_xml_get_widget(main_window, "window1");
GtkWidget *dialog = gtk_file_chooser_dialog_new("Seleziona directory...",
GTK_WINDOW(window1),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
^^^
usare gli spazi e' gratis ;-)
{
char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
t_state_set_path(data, filename);
GtkWidget *start = glade_xml_get_widget(main_window, "start");
GtkWidget *save = glade_xml_get_widget(main_window, "save");
GtkWidget *clear = glade_xml_get_widget(main_window, "clear");
gtk_widget_set_sensitive(start, TRUE);
gtk_widget_set_sensitive(save, TRUE);
gtk_widget_set_sensitive(clear, TRUE);
}
gtk_widget_destroy(dialog);
}
void on_clear_clicked(GtkButton *button, gpointer main_window)
{
GtkWidget *textview1 = glade_xml_get_widget(main_window, "textview1");
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview1));
gtk_text_buffer_set_text(buffer, "", -1);
}
int main(int argc, char *argv[])
{
GladeXML *main_window;
GtkWidget *widget;
static t_state data = {FALSE, FALSE, "\0", main_window};
io allocherei dinamicamente: g_new0 (t_state, 1)... non e' il caso qui, ma la struct puo diventare un po troppo grossa per essere messa sulla stack
gtk_init(&argc, &argv);
main_window = glade_xml_new("gdso.glade", NULL, NULL);
widget = glade_xml_get_widget(main_window, "window1");
g_signal_connect(G_OBJECT(widget), "delete_event",
G_CALLBACK(gtk_main_quit), NULL);
non c'e' bisogno di fare il cast G_OBJECT() in connect
widget = glade_xml_get_widget(main_window, "clear");
g_signal_connect(G_OBJECT(widget), "clicked",
G_CALLBACK(on_clear_clicked), main_window);
gtk_widget_set_sensitive(widget, FALSE);
widget = glade_xml_get_widget(main_window, "browse");
g_signal_connect(G_OBJECT(widget), "clicked",
G_CALLBACK(on_browse_clicked), &data);
gtk_main();
non e' molto importante qui visto che la app sta uscendo, ma visto che vieni dal java, ricordati che in C devi liberare la memoria allocata... quindi il free delle cose che ti ho indicato di allocare e l'unref di GladeXML.
return 0;
}
///////////////////////////////////////////////////////////////
cc -o gdso main.c `pkg-config --cflags --libs libglade-2.0`
main.c: In function 'main':
main.c:82: error: initializer element is not constant
main.c:82: error: (near initialization for 'data.main_window')