GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Tue Sep 30, 2014 10:22 am

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: [SOLVED] RE: File opening and reading
PostPosted: Wed Jan 02, 2013 7:37 pm 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Hi all,

I have been trying to use GTK-2+ for writting a graphical interface for my research related program. I followed through some of the tutorials for generating different types of widgets and its associated 'callback functions'. Still i have problem understanding some key issues, which are stated below.

1) In a conventional 'c' program the code is executed in a sequential fashion, but in gtk based c program, all the widget which are used and its associated callback acts independently and parallely.
2) I would like to know how to make them work in a sequential fashion.

Here is the thing i wanted to implement....

A main window, with a menubar. A menu item named 'file' was created and two sub menuitems namely 'open' and 'run' was included in the 'file' menu. Finally, the 'file' menu was incorporated in the menubar.

For the 'open' menu item i used a 'callback function' named 'file selection' which inturn calls a 'callback function' named 'store path' to save the path and name of the selected file. (the codes for the above mentioned functions, were copied from the gtk-2+ tutorials). I used 'gpointer data' to save the 'file path' while 'open's callback function was called.
In the next step, when the 'run' menu item is selected, i wanted to use the 'filepath' (saved as gpointer data using the previous 'open' menu's selction) and open that selected file in the background to perform some calclations and generate a new output file.

Unfortunately, i was not able to do that. I get segmentation faults. here is the actual code. I greatly appreciate your help and suggestions...


Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>

void create_file_selection(gpointer data);
void file_print(gpointer data);
void store_filename(GtkFileSelection *file_selection, gpointer data);

GtkWidget *file_selection_box;

int main( int   argc, char *argv[] )
{
    GtkWidget *window;
    char buf[128];
    int i;
    gtk_init (&argc, &argv);

    // create a new window
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request (GTK_WIDGET (window), 700, 700);
    gtk_window_set_title (GTK_WINDOW (window), "Auto-FACE");
    g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);

   // create a table and put a menubar inside it
    GtkWidget *table;
    table = gtk_table_new (12, 12, TRUE);
    gtk_container_add (GTK_CONTAINER (window), table);

    GtkWidget *menu_bar;
    menu_bar = gtk_menu_bar_new ();
    gtk_widget_set_size_request (GTK_WIDGET (menu_bar), 500, 35);
    gtk_table_attach_defaults (GTK_TABLE (table), menu_bar, 0, 12, 0, 1);
    gtk_widget_show (menu_bar);

   // create first menu and its submenu - file -> open
    GtkWidget *root_file_menu,*file_menu,*open_item,*run_item;
    file_menu = gtk_menu_new();
    root_file_menu= gtk_menu_item_new_with_label ("File");
    open_item = gtk_menu_item_new_with_label ("Open");
    gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), open_item);

    gchar *file_name,file_name1[300];
    strcpy(file_name1,"Test path");
    file_name=&file_name1[0];

    g_signal_connect(GTK_OBJECT (open_item), "activate", GTK_SIGNAL_FUNC (create_file_selection), (gpointer) file_name);
    gtk_widget_show (open_item);
    run_item = gtk_menu_item_new_with_label ("Run");
    gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), run_item);
    g_signal_connect(GTK_OBJECT (run_item), "activate", GTK_SIGNAL_FUNC (file_print), (gpointer) file_name);
    gtk_widget_show (run_item);
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_file_menu), file_menu);
    gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_file_menu);
    gtk_widget_show (file_menu);
    gtk_widget_show (root_file_menu);
    gtk_widget_show (window);
    gtk_main ();
    return 0;
}

// File open and selection menu
void create_file_selection(gpointer data)
{   
file_selection_box = gtk_file_selection_new("Please select a file for editing.");
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(file_selection_box)->ok_button),
                                  "clicked", GTK_SIGNAL_FUNC (store_filename), (gpointer) data);
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(file_selection_box)->ok_button),
            "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) file_selection_box);
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(file_selection_box)->cancel_button),
                "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) file_selection_box);
gtk_widget_show (file_selection_box);
}

void store_filename(GtkFileSelection *file_selection, gpointer data)
{   
  gchar *filename;
  data=gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selection_box));
  g_print ("Test:%s",(gchar *)data);
}
 
void file_print(gpointer data)
{   
FILE *infile,*outfile;
char *file_name,line[300];
file_name=data;
g_print ("inside file print:%s\n",(gchar *)data);
infile=fopen(file_name,"r");
while(!feof(infile))
  {
    fgets(line, sizeof(line),infile);
    puts(line);
  }
fclose(infile);
}


Last edited by janarbio on Mon Jan 07, 2013 3:49 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Wed Jan 02, 2013 8:49 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 750
Location: UK
Hello,

You do not say which version of GTK+ v2 you are using. May of the functions and data types you are using are obsolete with some functions being made obsolete in the transaction from v1 to v2.

With regard to how GTK+ works, all the widgets do not work independently and in parallel. It works in an event driven way like many other graphical tool kits and only using a single thread,

_________________
E.


Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Wed Jan 02, 2013 10:55 pm 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Hi Errol,

Thanks for your previous reply, I'm using gtk2.0 version. It is pretty old, but firstly, I want to understand the GTK concepts using older version.

If I can get past this problem of passing and modifying the 'gpointer data', I can convert my 'terminal based open sourced programs' into a simple graphic based ones for user's convenience.

To state my actual problem again....
1) The user chooses an input file (which contains initial parameters. i.e a txt file)
2) The program then stores the path and name of the user selected file
3) Subsequently the calculation is initiated by parsing and reading the input file and generating the output.
4) The results are either displayed as a message box or saved as an output file.

I was trying to do this in the following way:
created two menu items namely: 'open' and 'run'
initialized a string: gchar *data;

passed the 'data' as a gpointer data for the callback function of 'open' on event 'clicked'. And this sucessfully stored the file name along with its path. But in the next step, I wanted to pass the 'data' (now modified by clicking 'open'), as an input 'gpointer data' for the callback function of 'run' item on activation. Unfortunately, the second step is not working. Is there a way I can make it happen.

Ultimately, what I need to know is to how a 'gpointer data' is sequentially passed and modified by a series of callback functions affliated to different menu items in a sequential fashion. Any help is greatly appreciated.

Thank you,
Best regards,


Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Thu Jan 03, 2013 7:37 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 750
Location: UK
If the GTK+ version that you have is genuinely 2.0 then that dates from at latest November 2002 making that over ten years old. GTK+ has progressed a lot since then even in the 2.xx series. I would advise that you up-grade to version 3 or to version 2.24. This way you are not learning things that would need to be unlearned very soon after, or picking up practice that is now considered not good.

Going back to your original problem.

In your function store_filename() you are not actually storing the file name. What is happening is that the local pointer is modified which then goes out of scope at the end of the function. What I expect you wanted to do is copy the string to where the pointer points to. Also you are using fixed sized data storage for storing the file name. This can easily lead to a buffer overflow if the user enters a very long file name. The best way would be to allocate memory as and when needed. If you do want to keep using a fixed sized buffer then use the macro FILENAME_MAX though this is not recommended.

_________________
E.


Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Thu Jan 03, 2013 4:57 pm 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Hi Errol,

Thanks for your suggestion on upgrading to latest version. Soon, I will try to install Gtk-3 alogside Gtk-2 .

I modified the function 'store_filename()' as follows
Code:
void store_filename(GtkFileSelection *file_selection, gpointer data)
{
  gchar *filename;
  strcpy(data,gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selection_box)));
  g_print ("Test:%s",(gchar *)data);
}

Iam trying to pass a 'char pointer' named 'file_name' declared in main(), which is passed on to 'create_file_selection()' and finally to 'store_filename()', where its value is modified. After modifyng its value using 'open' item, a subsequent click of 'run' item, didnt print the actual path. Can you kindly show me the right way to code it.
Also, inside the function file_print() if i use file pointers, i get segmentation fault (here i have commented that part of code appropriately).
Code:
void file_print(gpointer data)
{   
FILE *infile,*outfile;
g_print ("inside file print:%s\n",(gchar *)data);
/*
infile=fopen(file_name,"r");
while(!feof(infile))
{
  fgets(line, sizeof(line),infile);
  puts(line);
}
fclose(infile);
*/
}

Since, iam focussing mainly on correctly passing the 'gpointer data' from one function to other, i did'nt pay much attention to the allocation size of 'filename'. Certainly, in the future code, i will define FILENAME_MAX properly.

Thank you,


Last edited by janarbio on Mon Jan 07, 2013 3:46 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Thu Jan 03, 2013 11:51 pm 
Offline
Familiar Face

Joined: Thu Sep 13, 2012 10:49 pm
Posts: 6
It looks to me like you're using a fixed data pointer as some kind of write buffer. glib has some wonderfully useful routines you may find very useful, and gtk is built upon it:

http://developer.gnome.org/glib/2.30/glib-String-Utility-Functions.html

You need to remember the difference between

Code:
gchar *data = "/tmp/foo";


which is a pointer to a static field that is compiled right into the program, and

Code:
gchar *data;
strcpy ( data, "/tmp/foo" );


which will segfault as the data pointer has no memory yet, it's just a pointer to nothing, or a pointer to anything, nobody knows. It could be 2 bytes ( segfault) or the entire text of Moby Dick (no segfault, but the memory is completely wasted because you're now only using 8 bytes of a few million).

if you're going to assign something to gchar *data, I would use:

Code:
if ( data )
   g_free(data);
data = g_strdup("/tmp/foo");

It malloc's a fresh new memory chunk just for the purpose. No segfault.

Check out g_strdup_printf() too. I use it all the time.


Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Fri Jan 04, 2013 7:00 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 750
Location: UK
Miven,

I have already mentioned the use of fixed sized buffers to janarbio which he now knows about. His main problem is that he is using a version of GTK+ that dates over ten years old and is using code that was deprecated and in some cases has been removed from modern versions of GTK+.

Just to clarify the use of g_free(). You do not need to do a check to see if the pointer is not NULL before calling g_free(). This is done internally to g_free() and is stated in the documentation. By doing the extra check all you are doing is adding extra bloat to your code and slowing it down a little bit. So you example becomes.
Code:
  g_free(data);
  data = g_strdup("/tmp/foo");

_________________
E.


Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Sun Jan 06, 2013 2:05 am 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Hi Errol and Miven,

Thanks for your valuable suggestions.

It took me some time to install gtk3+ and modify the previous code based on the available tutorial files. The code pasted below is intended to perform the following.
1) Opens a main window -> with 1 menuitem "file"-> containing 2 menuitems "Open" and "Run".
2) On clicking "Open"-> Filechooserdialog opens.

Further, the "Filechooserdialog box" has three gdkevent "selection-changed", "current-folder-changed" and "response" with three callbacks namely, "print_selected", "print_current_folder" and response_cb, whose prototype are as follows.
Code:
  g_signal_connect (dialog, "selection-changed", G_CALLBACK (print_selected),NULL);
  g_signal_connect (dialog, "current-folder-changed", G_CALLBACK (print_current_folder), NULL);
  g_signal_connect (dialog, "response", G_CALLBACK (response_cb), NULL);

When I select a file, the callback function to "response" prints the fullpath of the selected file. Till this point, things are fine.

Now I have one minor problem and one major problem. The minor one is, with the following 'response_cb'
callback function, on clicking either the 'open' or 'close' buttons which are present by default in the file selection dialog box, the main window also closes. When I changed the function from 'response_cb' to 'gtk_widget_destroy', this problem was averted. (I'm not sure whether this is the correct way to do it.)
Code:
g_signal_connect (dialog, "response", G_CALLBACK (response_cb), NULL);

But the major one is the passing of the gpointer data to these callback functions. I searched for the standard prototype definitions of the callbacks for the mentioned gdkevents (selection-changed, current-folder-changed, response), I could find none, except for the functions defined in the demo files, which does not pass any gpointer data. i.e.
Code:
static void print_current_folder (GtkFileChooser *chooser);

Code:
static void print_selected (GtkFileChooser *chooser);

Code:
static void response_cb (GtkDialog *dialog, gint response_id);

But what I wanted is to pass a structure similar to the following example; to each of the callbacks and copy and store the filepath as it prints to the terminal.
Code:
typedef struct
{   gchar *filename;
   GtkFileChooser *chooser;
} Data_type;

Unfortunately, when I try to initialize and pass it as a data I ran into trouble as 'GtkFileChooser' is an object of a class and allocationg memory is through 'new' function available in c++. I'm not sure how malloc can be used in this instance,
Code:
    Data_type  data_type, *data_type_ptr;
    data_type_ptr=&data_type;
    //data_type_ptr->chooser=(GtkFileChooser *) malloc (GtkFileChooser );
    data_type_ptr->filename=(gchar *) malloc (MAX_CHAR);

Any help/suggestions on passing the data and printing it to terminal when the 'File->'run' menu is activated (after activation of 'File->open') would be greatly appreciated. Thank you,
The currently working code is as follows,
Code:
/* testmenubars.c -- test different packing directions Copyright (C) 2005  Red Hat, Inc. Author: Matthias Clasen */

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#define MAX_CHAR 500

static GtkFileChooserAction action;

static void print_current_folder (GtkFileChooser *chooser)
{
  gchar *uri;
  uri = gtk_file_chooser_get_current_folder_uri (chooser);
  g_print ("Current folder changed :\n  %s\n", uri ? uri : "(null)");
  g_free (uri);
}

static void print_selected (GtkFileChooser *chooser)
{
  GSList *uris = gtk_file_chooser_get_uris (chooser);
  GSList *tmp_list;

  g_print ("Selection changed :\n");
  for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
    {
      gchar *uri = tmp_list->data;
      g_print ("  %s\n", uri);     
      g_free (uri);
    }
  g_print ("\n");
  g_slist_free (uris);
}

static void response_cb (GtkDialog *dialog, gint response_id)
{
  if (response_id == GTK_RESPONSE_OK)
    {
      GSList *list;
      list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));

      if (list)
   {
     GSList *l;

     g_print ("Selected files:\n");

     for (l = list; l; l = l->next)
       {
         g_print ("%s\n", (char *) l->data);
         g_free (l->data);
       }

     g_slist_free (list);
   }
      else
   g_print ("No selected files\n");
    }
  else
    g_print ("Dialog was closed\n");

  gtk_main_quit ();
}

void file_open_dialog()
{   
   action = GTK_FILE_CHOOSER_ACTION_OPEN;
   GtkWidget *dialog;
   dialog =gtk_file_chooser_dialog_new("Select a file",NULL,GTK_FILE_CHOOSER_ACTION_OPEN,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
   g_signal_connect (dialog, "selection-changed", G_CALLBACK (print_selected),NULL);
  g_signal_connect (dialog, "current-folder-changed", G_CALLBACK (print_current_folder), NULL);
  g_signal_connect (dialog, "response", G_CALLBACK (response_cb), NULL);
//g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
  gtk_widget_show_all (dialog);
}

int main (int argc, char **argv)
{
  static GtkWidget *window = NULL;
  GtkWidget *box;
  gtk_init (&argc, &argv);
        GtkWidget *menubar;
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (window,"delete-event",G_CALLBACK (gtk_main_quit), NULL);
        gtk_window_set_title (GTK_WINDOW (window), "Automex");
        gtk_container_set_border_width (GTK_CONTAINER (window), 0);
        box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  GtkWidget *menuitem,*sub_menuitem;
  GtkWidget *menu;

  // Creating menubar
  menubar = gtk_menu_bar_new ();
  gtk_menu_bar_set_pack_direction (GTK_MENU_BAR (menubar), GTK_PACK_DIRECTION_LTR);
  gtk_menu_bar_set_child_pack_direction (GTK_MENU_BAR (menubar),GTK_PACK_DIRECTION_LTR);

  // Creating menuitem: File
  menuitem = gtk_image_menu_item_new_from_stock ("File", NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
  menu = gtk_menu_new ();

  // Creating submenuitem: Open
    sub_menuitem = gtk_menu_item_new_with_label ("Open");
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
    g_signal_connect (sub_menuitem,"activate",G_CALLBACK (file_open_dialog), NULL);
    gtk_widget_show (sub_menuitem);

  // Creating submenuitem: Run
    sub_menuitem = gtk_menu_item_new_with_label ("Run");
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
    gtk_widget_show (sub_menuitem);

  // Adding submenuitems to the menuitem
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);

    gtk_container_add (GTK_CONTAINER (window), box);
    gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);

    gtk_widget_show_all (box);
    gtk_widget_show (window);
    gtk_main ();
   return 0;
}


Last edited by janarbio on Mon Jan 07, 2013 3:43 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Sun Jan 06, 2013 6:46 am 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 177
Location: USA
http://developer.gnome.org/gtk3/stable/GtkFileChooser.html#GtkFileChooser.signals
http://developer.gnome.org/gtk3/stable/GtkDialog.html#GtkDialog.signals

Did you install Devhelp with GTK+3? I would really recommend it if you haven't. It makes looking up things very easy.

For passing a structure to your callback have a look at this example:
http://www.gtkforums.com/viewtopic.php?f=3&t=988&p=196157=Changing+menubar+content%2C+by+selecting+a+notebook+tab#p196157

Also I see you've used gtk_box_new() which is eventually going away. The manual recommends switching to GtkGrid.
http://www.gtkforums.com/viewtopic.php?f=3&t=988&p=195349=Gtk3+with+CSS%3A+GtkCalendar#p195349


Top
 Profile  
 
 Post subject: Re: File opening and reading
PostPosted: Sun Jan 06, 2013 11:09 pm 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Dear Zerohour, Errol and Mevin,
Thanks for your previous help. I found the prototype of the callbacks very useful.
I found where i was making the mistake, (which i would not have sorted out if you had not pointed me to the correct doc reference). (I will learn to use grid rather than boxes in future).

(Iam elaborating the problem so that it will be helpful for newbie like me...)
My objective was simple,
1) create a main Window -> with a menubar-> with a menu "file"-> with two submenuitems "Open" and "Run".
2) On clicking "open" submenuitem, "filechoosedialog box" opens. The selected filename with its full path is saved into a string variable.
3) On Clicking "run" submenuitem, the saved variable is printed to the terminal. (Infact this will be used to open the file, read and perform some useful calculations).

I had a problem using the callback functions correctlyas i was not aware that, the number and order of input arguments for the callbacks are very important. For example, In the below example
Code:
gchar *file_name_ptr,file_name[MAX_CHAR];
file_name_ptr=&file_name[0];
g_signal_connect(sub_menuitem,"activate",G_CALLBACK (file_name_retrieve), file_name_ptr );

I defined the call back to be
Code:
void file_name_retrieve (gchar *file_name_ptr)
{ g_print ("Run:  %s\n", file_name_ptr);}

Unfortunatley, the 'file_name_ptr' was not passed properly and when printed showed strange characters. But the prototype of callback of "activate" Gdkevent when used as 'g_signal_connect' has two arguments with a widget and a gpointer.
Code:
void callback_func( GtkWidget *widget, gpointer   callback_data );

My callback had only one argument, which was a gpointer, so whenever, i called 'file_name_retrieve', the passed argument was considered as a widget. hence, printed strange charcters. When i used,
Code:
gchar *file_name_ptr,file_name[MAX_CHAR];
file_name_ptr=&file_name[0];
g_signal_connect_swapped(sub_menuitem,"activate",G_CALLBACK (file_name_retrieve), file_name_ptr );

Things went well as the definition for g_signal_connect_swapped's callback function is
Code:
void callback_func( gpointer   callback_data ,GtkWidget *widget);

and it took the first argument correctly to be gchar*, as i intended.

Thanks again for the help by the forum admins, Iam pasting the working code that works the way i required.
If i am wrong in my expalnation pls correct me as i have just started programming in GTK .
Code:
/* testmenubars.c -- test different packing directions Copyright (C) 2005  Red Hat, Inc. Author: Matthias Clasen */

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib/gprintf.h>
#define MAX_CHAR 500

static GtkFileChooserAction action;

static void print_current_folder (GtkFileChooser *chooser)
{
  gchar *uri;
  uri = gtk_file_chooser_get_current_folder_uri (chooser);
  g_print ("Current folder changed :\n  %s\n", uri ? uri : "(null)");
  g_free (uri);
}

static void print_selected ( gchar *file_name,GtkFileChooser *chooser )
{
  GSList *uris = gtk_file_chooser_get_uris (chooser);
  GSList *tmp_list;
  g_print ("Selection changed :\n");
  for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
    {
      gchar *uri = tmp_list->data;
      strcpy(file_name,g_strdup(tmp_list->data));
      g_print ("  %s\t%s\n", uri,file_name);
      g_free (uri);
    }
  g_print ("\n");
  g_slist_free (uris);
}

static void response_cb (GtkDialog *dialog, int response_id)
{
  if (response_id == GTK_RESPONSE_OK)
    {
      GSList *list;
      list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
      if (list)
   {
     GSList *l;
     g_print ("Selected files:\n");
     for (l = list; l; l = l->next)
       {
         g_print ("%s\n", (char *) l->data);
         g_free (l->data);
       }
     g_slist_free (list);
   }
      else
   g_print ("No selected files\n");
    }
  else
    g_print ("Dialog was closed\n");
  gtk_main_quit ();
}

void file_open_dialog(gchar *file_name_ptr)
{
   action = GTK_FILE_CHOOSER_ACTION_OPEN;
   GtkWidget *dialog;
   dialog =gtk_file_chooser_dialog_new("Select a file",NULL,GTK_FILE_CHOOSER_ACTION_OPEN,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

  g_signal_connect_swapped(dialog, "selection-changed", G_CALLBACK (print_selected),file_name_ptr);
  g_signal_connect (dialog, "current-folder-changed", G_CALLBACK (print_current_folder), NULL);
  g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
  gtk_widget_show_all (dialog);
}

void file_name_retrieve (gchar *file_name_ptr)
{
     g_print ("Run:  %s\n", file_name_ptr);
     FILE *infile;
     char line[MAX_CHAR],file_name[MAX_CHAR];
     int file_len,i;
     file_len=strlen(file_name_ptr);   
     for(i=7;i<file_len;i++) {file_name[i-7]=file_name_ptr[i];}
        infile=fopen(file_name,"r");
        while(!feof(infile))
        { fgets(line,sizeof(line),infile);
           puts(line);
        }
        fclose(infile);
}

main (int argc, char **argv)
{
  static GtkWidget *window = NULL;
  GtkWidget *box;
  gtk_init (&argc, &argv);
      GtkWidget *menubar;
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      g_signal_connect (window,"delete-event",G_CALLBACK (gtk_main_quit), NULL);
      gtk_window_set_title (GTK_WINDOW (window), "Automex");
      gtk_container_set_border_width (GTK_CONTAINER (window), 0);
      box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
   GtkWidget *menuitem,*sub_menuitem;
  GtkWidget *menu;

  // Creating menubar
  menubar = gtk_menu_bar_new ();
  gtk_menu_bar_set_pack_direction (GTK_MENU_BAR (menubar), GTK_PACK_DIRECTION_LTR);
  gtk_menu_bar_set_child_pack_direction (GTK_MENU_BAR (menubar),GTK_PACK_DIRECTION_LTR);

  // Creating menuitem: File
  menuitem = gtk_image_menu_item_new_from_stock ("File", NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
  menu = gtk_menu_new ();

  // Creating submenuitem: Open
    gchar *file_name_ptr,file_name[MAX_CHAR];
    file_name_ptr=&file_name[0];
    sub_menuitem = gtk_menu_item_new_with_label ("Open");
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
    g_signal_connect_swapped (sub_menuitem,"activate",G_CALLBACK (file_open_dialog), file_name_ptr);
    gtk_widget_show (sub_menuitem);

  // Creating submenuitem: Run
    sub_menuitem = gtk_menu_item_new_with_label ("Run");
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
    g_signal_connect_swapped (sub_menuitem,"activate",G_CALLBACK (file_name_retrieve), file_name_ptr );
    gtk_widget_show (sub_menuitem);

  // Adding submenuitems to the menuitem
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
    gtk_container_add (GTK_CONTAINER (window), box);
    gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);

    gtk_widget_show_all (box);
    gtk_widget_show (window);
    gtk_main ();
   return 0;
}


Top
 Profile  
 
 Post subject: Re: [SOLVED] RE: File opening and reading
PostPosted: Wed Jan 09, 2013 9:20 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 750
Location: UK
Below is how I would write your code (still not great code). This shows how simple it is to use the new GtkGrid container. I have also modified it so that the "response" signal can be used. The original problem was that you had used gtk_main_quit() which eventually quit the application. gtk_widget_destroy() should have been used instead. This way would allow the use of Cancel, OK, etc.

With the file name I have used memory allocated from the heap instead of statically allocated memory. This is always safer as there is less risk of a buffer overflow or any limit on the size of the file name. In your function file_name_retrive() I have used the Glib function g_filename_from_uri(). This function converts from a URI to a file name with proper checking, again this is safer than assuming that the beginning of the URI will always be a fixed size. The way the code is set up it is only possible to select one file at a time. If you needed to you can ask the File Chooser to allow selection of more than one file and instead of passing around a single gchar * you can pass around a GSList. This should only take a little bit of extra work and thought.

You mentioned about C++ in a previous posting. There are bindings for C++ which you may find easier if you are more at home with the C++ way of doing things. Also whenever I am coding I always keep a off-line reference manual to hand (normally DevHelp). This way I can easily find out what parameters a signal call-back takes and look up those useful little functions that would make my code better.

Code:
/* testmenubars.c -- test different packing directions Copyright (C) 2005  Red Hat, Inc. Author: Matthias Clasen */

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib/gprintf.h>
#define MAX_CHAR 500

static GtkFileChooserAction action;

static void print_current_folder (GtkFileChooser *chooser)
{
  gchar *uri
    = gtk_file_chooser_get_current_folder_uri (chooser);
  g_print ("Current folder changed :\n  %s\n", uri ? uri : "(null)");
  g_free (uri);
}

static void print_selected ( GtkFileChooser *chooser, gpointer user_data )
{
  GSList *uris = gtk_file_chooser_get_uris (chooser);
  GSList *tmp_list;
  g_print ("Selection changed :\n");
  for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
    {
      g_print ("  %s\n", (char *) tmp_list->data);
    }
  g_print ("\n");
  g_slist_free_full (uris, g_free);
}

static void response_cb (GtkDialog *dialog, int response_id, gchar ** user_data)
{
  if (response_id == GTK_RESPONSE_OK)
    {
      GSList *list;
      list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
      if (list)
        {
          GSList *l;
          g_print ("Selected files:\n");
          for (l = list; l; l = l->next)
            {
              g_print ("%s\n", (gchar *) l->data);
              g_free (*user_data);
              *user_data = g_strdup ((gchar *) l->data);
            }
          g_slist_free_full (list, g_free);
        }
      else
        g_print ("No selected files\n");
    }
      else
        g_print ("Dialog was closed\n");
  gtk_widget_destroy (GTK_WIDGET (dialog));
}

void file_open_dialog(gchar **file_name_ptr)
{
  action = GTK_FILE_CHOOSER_ACTION_OPEN;
  GtkWidget *dialog;
  dialog = gtk_file_chooser_dialog_new("Select a file"
    ,NULL,GTK_FILE_CHOOSER_ACTION_OPEN,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

  g_signal_connect (dialog, "selection-changed", G_CALLBACK (print_selected), NULL);
  g_signal_connect (dialog, "current-folder-changed", G_CALLBACK (print_current_folder), NULL);
  g_signal_connect (dialog, "response", G_CALLBACK (response_cb), file_name_ptr);
  gtk_widget_show_all (dialog);
}

void file_name_retrieve (gchar **file_name_ptr)
{
  g_print ("Run:  %s\n", *file_name_ptr);
  FILE *infile;
  char line[MAX_CHAR];
  gchar *file_name;

  if (*file_name_ptr == NULL) return;
  file_name = g_filename_from_uri(*file_name_ptr, NULL, NULL);
  if (file_name == NULL) return;

  g_print ("Run filename: %s\n", file_name);

  infile = fopen(file_name,"r");
  g_free (file_name);
  while(!feof(infile))
    {
      fgets(line, sizeof(line), infile);
      fputs(line, stdout);
    }
  fclose(infile);
}

int main (int argc, char **argv)
{
  static GtkWidget *window;
  GtkWidget *grid;
  GtkWidget *menuitem,*sub_menuitem;
  GtkWidget *menu;
  GtkWidget *menubar;
  gchar *file_name_ptr = NULL;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (window,"delete-event",G_CALLBACK (gtk_main_quit), NULL);
  gtk_window_set_title (GTK_WINDOW (window), "Automex");
  grid = gtk_grid_new ();

  // Creating menubar
  menubar = gtk_menu_bar_new ();

  // Creating menuitem: File
  menuitem = gtk_image_menu_item_new_from_stock ("File", NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
  menu = gtk_menu_new ();

  // Creating submenuitem: Open
  sub_menuitem = gtk_menu_item_new_with_label ("Open");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
  g_signal_connect_swapped (sub_menuitem,"activate",G_CALLBACK (file_open_dialog), &file_name_ptr);

  // Creating submenuitem: Run
  sub_menuitem = gtk_menu_item_new_with_label ("Run");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
  g_signal_connect_swapped (sub_menuitem,"activate",G_CALLBACK (file_name_retrieve), &file_name_ptr );

  // Adding submenuitems to the menuitem
  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
  gtk_container_add (GTK_CONTAINER (window), grid);
  gtk_grid_attach (GTK_GRID (grid), menubar, 0, 0, 1, 1);

  gtk_widget_show_all (window);
  gtk_main ();

  return 0;
}

_________________
E.


Top
 Profile  
 
 Post subject: Re: [SOLVED] RE: File opening and reading
PostPosted: Wed Jan 09, 2013 5:36 pm 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Thank you very much Errol!
I appreciate your patience in rewriting the code and exemplifying the usage of allocating memory from the heap, grid and filename conversion from url format to normal format. I will start adopting this better way of coding. Thanks again.


Top
 Profile  
 
 Post subject: Re: [SOLVED] RE: File opening and reading
PostPosted: Thu Jan 10, 2013 12:00 am 
Offline
Familiar Face

Joined: Wed Jan 02, 2013 6:04 pm
Posts: 14
Hi Errol,
Thanks for your good suggestions. I tried modifying the code to select multiple files and also passing GSList as the gpointer data. The program compiled well. But, i think the way i copied the contents of one GSList to another inside a function is not the best way. Your suggestions on this problem will be very useful to me.
(For some reasons iam not able to use the function correctly)
Code:
another_list = g_slist_copy_deep (list, (GCopyFunc) g_object_ref, NULL);


Code:
/* testmenubars.c -- test different packing directions Copyright (C) 2005  Red Hat, Inc. Author: Matthias Clasen */

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib/gprintf.h>

static GtkFileChooserAction action;

static void response_cb (GtkDialog *dialog, int response_id, GSList * user_data)
{
if (response_id == GTK_RESPONSE_OK)
    {
      GSList *list;
      *user_data = *gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (dialog));
       if (user_data)
        {
          GSList *l;
          g_print ("Selected files:\n");
          for (l = user_data; l; l= l->next)
            {   g_print ("Open: %s\n", (gchar *) l->data);   }
            // printf("size: %d\n",g_slist_length(user_data));
           g_slist_free_full (l,g_free);
        }
      else { g_print ("No selected files\n");}
    }
      else
        g_print ("Dialog was closed\n");
        gtk_widget_destroy (GTK_WIDGET (dialog));
}

void file_name_retrieve (GSList * user_data)
{
      GSList *l;
           for (l = user_data; l; l = l->next)
       { g_print ("Run: %s\n", (gchar *) l->data); }
             // printf("size: %d\n",g_slist_length(user_data));
             g_slist_free_full (l, g_free);
             g_slist_free_full (user_data, g_free);        
}

void file_open_dialog(GSList *f_names)
{
  gboolean multiple=TRUE;
  action = GTK_FILE_CHOOSER_ACTION_OPEN;
  GtkWidget *dialog;
  dialog = gtk_file_chooser_dialog_new("Select a file"
    ,NULL,GTK_FILE_CHOOSER_ACTION_OPEN,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
  gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog),multiple);
  g_signal_connect (dialog, "response", G_CALLBACK (response_cb), f_names);
  gtk_widget_show_all (dialog);
}

int main (int argc, char **argv)
{
  static GtkWidget *window;
  GtkWidget *grid;
  GtkWidget *menuitem,*sub_menuitem;
  GtkWidget *menu;
  GtkWidget *menubar;
  GSList *f_names=g_slice_new (GSList);
  gchar *file_name_ptr = NULL;
  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (window,"delete-event",G_CALLBACK (gtk_main_quit), NULL);
  gtk_window_set_title (GTK_WINDOW (window), "Automex");
  grid = gtk_grid_new ();

  // Creating menubar
  menubar = gtk_menu_bar_new ();

  // Creating menuitem: File
  menuitem = gtk_image_menu_item_new_from_stock ("File", NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
  menu = gtk_menu_new ();

  // Creating submenuitem: Open
  sub_menuitem = gtk_menu_item_new_with_label ("Open");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
  g_signal_connect_swapped (sub_menuitem,"activate",G_CALLBACK (file_open_dialog), f_names);

  // Creating submenuitem: Run
  sub_menuitem = gtk_menu_item_new_with_label ("Run");
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), sub_menuitem);
  g_signal_connect_swapped (sub_menuitem,"activate",G_CALLBACK (file_name_retrieve), f_names );

  // Adding submenuitems to the menuitem
  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
  gtk_container_add (GTK_CONTAINER (window), grid);
  gtk_grid_attach (GTK_GRID (grid), menubar, 0, 0, 1, 1);

  gtk_widget_show_all (window);
  gtk_main ();

  return 0;
}


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 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