GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Sat Oct 25, 2014 4:18 am

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: get number of elements in GtkWidget array
PostPosted: Mon Nov 07, 2011 3:45 pm 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
Hello everyone. I have a function
void func(GtkWidget *widgetarray[])
i want to determine the number of elements in array
Code:
int i=0;
while(GTK_IS_WIDGET(widgetarray[i]) == TRUE)
i++;


Code:
int i=0;
while(widgetarray[i])
i++;

i get segmentation fault core dumped error for both above.

Code:
size_t size = (sizeof widgetarray )/(sizeof widgetarray[0])

but i get size in negative decimals.

Can anyone help me to find number of elements in array.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Tue Nov 08, 2011 10:32 am 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
i have also tried
Code:
size = G_N_ELEMENTS(widgetarray);

but i always get size = 1.
Solve it pls.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Tue Nov 08, 2011 10:59 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 764
Location: UK
You are making a large number of mistakes and assumptions about the array.

The use of "sizeof()" or the macro G_N_ELEMENTS() will only work if the array is fully defined at compile time.
Code:
    GtkWidgets *widgetarray[10];
    size_t size = G_N_ELEMENTS(widgetarray);
    size_t alt_size = (sizeof (widgetarray) / sizeof ((widgetarray)[0]))


size and alt_size will then be 10;

So passing an array of unknown size to a function will not work using the above methods.

You also do not specify what you are passing to the function, as you could be passing a bad value which then causes your segmentation fault. You also do not say if the array is NULL terminated or terminated in some other way.

E.

_________________
E.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Tue Nov 08, 2011 3:52 pm 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
So, here is the full code.
Code:

static gboolean delete_event(GtkWidget *window,GdkEvent *event)
{
    int i=0,j = -1;

   
    for (i = 0; i<10;i++)
    {
        filenotsavedarray[i] = -1;
        }
   
    for (i = 0; i <gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); i++)
    {
        GtkTextBuffer *buffer;
        GtkTextIter start_iter, end_iter;
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtinput[i]));
        gtk_text_buffer_get_start_iter(buffer, &start_iter);
        gtk_text_buffer_get_end_iter(buffer, &end_iter);
        char *text;
        text = gtk_text_buffer_get_text(buffer,&start_iter,&end_iter,FALSE);
        if (function_filechanged(filepathsarray[i],text) == TRUE)
        {
            if (j==-1)
            {
                j=0;
                }
            filenotsavedarray[j] = i;
            j++;
            }
        g_free(text);
        }
   
    if (j != -1)
    {
        GtkWidget *dialog,*label,*cmdclosewithoutsave,*cmdcancel,*cmdsave;
        filecheckbuttonsarray_size = i;
        GtkWidget *filecheckbuttonsarray[i];
       
        dialog = gtk_dialog_new();
       
        label = gtk_label_new("Following files are not saved. Please select the files you want to save before closing.");
        cmdclosewithoutsave = gtk_button_new_with_mnemonic("_Close without saving");
        cmdsave = gtk_button_new_with_mnemonic("_Save");
        cmdcancel = gtk_button_new_with_mnemonic("_Cancel");
       
        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),label,FALSE,FALSE,0);
        for (i =0; i <j; i++)
        {
            filecheckbuttonsarray[i] = gtk_check_button_new_with_label(gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(notebook),scrollwin[filenotsavedarray[i]]));
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filecheckbuttonsarray[i]),TRUE);
            gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),filecheckbuttonsarray[i],FALSE,FALSE,0);
            }
        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),cmdclosewithoutsave);
        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),cmdcancel);
        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),cmdsave);
        g_signal_connect(G_OBJECT(cmdclosewithoutsave),"clicked",G_CALLBACK(exit_activated),dialog);
        g_signal_connect(G_OBJECT(cmdsave),"clicked",G_CALLBACK(exitdialog_cmdsave_clicked),filecheckbuttonsarray);
        gtk_window_set_modal(GTK_WINDOW(dialog),FALSE);
        gtk_widget_show_all(dialog);
        gtk_dialog_run(GTK_DIALOG(dialog));       
        return TRUE;
        }
    else
    {
        return FALSE;
        }       
    }
static void destroy(GtkWidget *window)
{
   gtk_main_quit();
    }

void exitdialog_cmdsave_clicked(GtkWidget *widget, GtkWidget *widgetarray[])
{
    int i = 0;
    gssize length = -1;
    while (i<filecheckbuttonsarray_size)
    {
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgetarray[i])) == TRUE)
        {
            if (strcmp(filepathsarray[filenotsavedarray[i]],"") !=0)
            {
                GtkTextIter start_iter, end_iter;
                GtkTextBuffer *buffer;
                buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtinput[filenotsavedarray[i]]));
                gtk_text_buffer_get_end_iter(buffer,&end_iter);
                gtk_text_buffer_get_start_iter(buffer,&start_iter);
                g_file_set_contents(filepathsarray[filenotsavedarray[i]],gtk_text_buffer_get_text(buffer,&start_iter,&end_iter,FALSE),length,NULL);
                }
            else
            {
                gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),filenotsavedarray[i]);
                saveas_activated(widget,window);
                }
            }
        else
        {
            break;
            }
         i++;
        }
    gtk_widget_destroy(window);    /*This function doesn't run */
    }


Actually, I am developing a Text Editor and I am modifying the delete_event, so that it will first check and will then display the files which are unsaved. These file names are displayed in check boxes. The array filecheckbuttonsarray is passed to the callback function of cmdsave.
filecheckbuttonsarray_size is declared globally.

So here I am facing two errors, first one is getting number of elements in widgetarray. Actually, I don't want to declare the filecheckbuttonsarray_size globally, I don't want to use it. So, please tell me another good way of getting number of elements.

Second is that I am not able to close the window after all files are saved. In function void exitdialog_cmdsave_clicked(GtkWidget *widget, GtkWidget *widgetarray[]), we have gtk_main_quit() at the end of the function, but that's not running, I mean I'm not able to close the window.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Thu Nov 10, 2011 12:31 am 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
You still haven't shown how you set up the widget array or answered the question of whether it is zero terminated.
An easy (though not potentially as efficient) solution to your problem is to use glib's pointer array data type http://developer.gnome.org/glib/2.28/glib-Pointer-Arrays.html to store pointers to your widgets as they are being created. Getting the length is easy as it is stored in the structure as yourgptrarray->len. It also potentially makes for cleaner memory management of your widgets.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Thu Nov 10, 2011 11:27 am 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
the array is created in delete_event.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Fri Nov 11, 2011 4:49 am 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
Again you still have not shown how this array is set up and if it is zero terminated.
delete_event is received from one widget (often the top level window) not an array of widgets.


Top
 Profile  
 
 Post subject: Re: get number of elements in GtkWidget array
PostPosted: Fri Nov 11, 2011 7:50 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 764
Location: UK
Hi, sorry for the delay in replying, I do have a real life as well. I have rewritten your code, but not tested it.

The first thing I did was to changed the way you created and used the dialog window. I first removed all the depreciated uses of the internal variables of the object GtkDialog and replaced them with the relevant functions. I also did not use signals, but used the return value from gtk_dialog_run() to control what should be done next having first assigned a return value for each button with the function gtk_dialog_new_with_buttons().

Next I looked at the way you are accessing arrays. In your original form there is no way of knowing how long your array is as you have not stored a length variable or NULL terminated your array.

I have used the Glib library of data structures to help here in particular GArray and GPtrArray. These have functions to make memory management of arrays easy. as they expand as you add entries to them. Paul in a previous posting has suggested that you use this method.

Please take your time looking over the current documentation for GtkDialog, GArray and GPtrArray, and avoid the use of depreciated code. Note that what is depreciated in GTK+ 2 has now been removed in GTK+ 3.

Code:
static gboolean delete_event(GtkWidget *window, GdkEvent *event)
{
    int i;
    int j = -1;
    GArray * filenotsavedarray = g_array_new(FALSE, FALSE, sizeof(int));

/* Search for files that have been changed, and fill an array.
* note that this could be very slow, say if files are over a
* network, or on a device that has now been un-mounted.
* Would advise the use of a boolean variable to keep track of
* when a document has been changed.
*/
    for (i = 0; i < gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); ++i)
    {
        char *text;
        GtkTextBuffer *buffer;
        GtkTextIter start_iter, end_iter;

        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtinput[i]));
        gtk_text_buffer_get_start_iter(buffer, &start_iter);
        gtk_text_buffer_get_end_iter(buffer, &end_iter);

        text = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
        if (function_filechanged(filepathsarray[i], text) == TRUE)
        {
            g_array_append_val(filenotsavedarray, i);
        }
        g_free(text);
    }

    if (filenotsavedarray->len != 0)
    {
        GtkWidget *dialog, *label, *content_area;
        GPtrArray *filecheckbuttonsarray = g_ptr_array_sized_(filenotsavedarray->len);
        int status;

/* Create a dialog window with some buttons and a title for the window */
        dialog = gtk_dialog_new_with_buttons("Exit and save documents",
            GTK_WINDOW(window), GTK_DIALOG_MODAL,
            "Close without saving", GTK_RESPONSE_REJECT,
            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
            GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
            NULL);

/* Add a label to the contents area of the dialog box */
        content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
        label = gtk_label_new("Following files are not saved. Please select the files you want to save before closing.");
        gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, FALSE, 0);

/* Add Check Button for each unsaved file to the dialog window
* contents area and to an array
*/
        for (i = 0; i < filenotsavedarray->len; ++i)
        {
            GtkWidget *cb;
            int val = g_array_index(filenotsavedarray, int, i);
            cb = gtk_check_button_new_with_label(gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(notebook), scrollwin[val]));
            g_ptr_array_add(filecheckbuttonsarray, (gpointer) cb);
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb), TRUE);
            gtk_box_pack_start(GTK_BOX(content_area), cb, FALSE, FALSE, 0);
        }

/* Show the dialog window and get the returned status */
        gtk_widget_show_all(dialog);
        status = gtk_dialog_run(GTK_DIALOG(dialog));
        gtk_widget_destroy(dialog);

        switch (status) {
/* Saved button clicked */
        case GTK_RESPONSE_ACCEPT:
            exitdialog_cmdsave(window, filecheckbuttonsarray, filenotsavedarray);
/* Close without saving - button clicked */
        case GTK_RESPONSE_REJECT:
            g_ptr_array_free(filecheckbuttonsarray, TRUE);
            g_array_free(filenotsavedarray, TRUE);
            return FALSE; /* Carry on and delete the window */
/* Cancel button clicked */
        case GTK_RESPONSE_CANCEL:
/* Anything else ??? */
        default:
            g_ptr_array_free(filecheckbuttonsarray, TRUE);
            g_array_free(filenotsavedarray, TRUE);
            return TRUE; /* Cancel the window delete signal */
        }
    }

    g_array_free(filenotsavedarray, TRUE);

    return FALSE;
}

static void destroy(GtkWidget *window)
{
    gtk_main_quit();
}

/* Work through the arrays and save the files. */

void exitdialog_cmdsave(GtkWidget *widget, GPtrArray *widgetarray, GArray *filenotsavedarray)
{
    int i;

    for (i = 0; i < filenotsavedarray->len; ++i)
    {
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(widgetarray, i))) == TRUE)
        {
            int idx = g_array_index(filenotsavedarray, int, i);
            if (strcmp(filepathsarray[idx], "") != 0)
            {
                GtkTextIter start_iter, end_iter;
                GtkTextBuffer *buffer;

                buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtinput[idx]));
                gtk_text_buffer_get_end_iter(buffer, &end_iter);
                gtk_text_buffer_get_start_iter(buffer, &start_iter);
                g_file_set_contents(filepathsarray[idx], gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE), -1, NULL);
            }
            else
            {
                gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), idx);
                saveas_activated(widget, window);
            }
        }
    }
}


E.

_________________
E.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group