All pastes #388967 Raw Edit

Untitled

public text v1 · immutable
·published 2007-03-10 12:54 UTC
rendered paste body
#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')