diff --git a/doc/manual/Makefile b/doc/manual/Makefile index 4298d8fdf..58ac1cd8b 100644 --- a/doc/manual/Makefile +++ b/doc/manual/Makefile @@ -64,6 +64,8 @@ SOURCEFIGS = \ figures/plot-2d.png \ figures/plot-2d-with-error-bars.png \ figures/plot-3d.png \ + figures/gtk-config-lena-dual-stripe-device-view.png \ + figures/gtk-config-lena-dual-stripe-eNB-tx-power.png \ ${SRC}/stats/doc/Stat-framework-arch.png \ ${SRC}/stats/doc/Wifi-default.png \ ${SRC}/stats/doc/dcf-overview.dia \ diff --git a/doc/manual/figures/gtk-config-lena-dual-stripe-device-view.png b/doc/manual/figures/gtk-config-lena-dual-stripe-device-view.png new file mode 100644 index 000000000..186b51e4c Binary files /dev/null and b/doc/manual/figures/gtk-config-lena-dual-stripe-device-view.png differ diff --git a/doc/manual/figures/gtk-config-lena-dual-stripe-eNB-tx-power.png b/doc/manual/figures/gtk-config-lena-dual-stripe-eNB-tx-power.png new file mode 100644 index 000000000..cd76e79bd Binary files /dev/null and b/doc/manual/figures/gtk-config-lena-dual-stripe-eNB-tx-power.png differ diff --git a/doc/manual/source/attributes.rst b/doc/manual/source/attributes.rst index f53c2561a..dacffb881 100644 --- a/doc/manual/source/attributes.rst +++ b/doc/manual/source/attributes.rst @@ -27,29 +27,29 @@ In the course of this chapter we will discuss the various ways to set or modify the values used by |ns3| model objects. In increasing order of specificity, these are: -+---------------------------------------+-------------------------------------+ -| Method | Scope | -+=======================================+=====================================+ -| Default Attribute values set when | Affect all instances of the class. | -| Attributes are defined in | | -| :cpp:func:`GetTypeId ()`. | | -+---------------------------------------+-------------------------------------+ -| | :cpp:class:`CommandLine` | Affect all future instances. | -| | :cpp:func:`Config::SetDefault()` | | -| | :cpp:class:`ConfigStore` | | -+---------------------------------------+-------------------------------------+ -| :cpp:class:`ObjectFactory` | Affects all instances created with | -| | the factory. | -+---------------------------------------+-------------------------------------+ -| Helper methods with (string/ | Affects all instances created by | -| AttributeValue) parameter pairs | the helper. | -+---------------------------------------+-------------------------------------+ -| | :cpp:func:`MyClass::SetX ()` | Alters this particular instance. | -| | :cpp:func:`Object::SetAttribute ()` | Generally this is the only form | -| | :cpp:func:`Config::Set()` | which can be scheduled to alter | -| | an instance once the simulation | -| | is running. | -+---------------------------------------+-------------------------------------+ ++-------------------------------------+------------------------------------+ +| Method | Scope | ++=====================================+====================================+ +| Default Attribute values set when | Affect all instances of the class. | +| Attributes are defined in | | +| :cpp:func:`GetTypeId ()`. | | ++-------------------------------------+------------------------------------+ +| :cpp:class:`CommandLine` | Affect all future instances. | +| :cpp:func:`Config::SetDefault()` | | +| :cpp:class:`ConfigStore` | | ++-------------------------------------+------------------------------------+ +| :cpp:class:`ObjectFactory` | Affects all instances created with | +| | the factory. | ++-------------------------------------+------------------------------------+ +| Helper methods with (string/ | Affects all instances created by | +| AttributeValue) parameter pairs | the helper. | ++-------------------------------------+------------------------------------+ +| :cpp:func:`MyClass::SetX ()` | Alters this particular instance. | +| :cpp:func:`Object::SetAttribute ()` | Generally this is the only form | +| :cpp:func:`Config::Set()` | which can be scheduled to alter | +| | an instance once the simulation | +| | is running. | ++-------------------------------------+------------------------------------+ By "specificity" we mean that methods in later rows in the table override the values set by, and typically affect fewer instances than, @@ -1158,20 +1158,61 @@ write out the resulting attributes to a separate file called Simulator::Run (); } +ConfigStore use cases (pre- and post-simulation) +++++++++++++++++++++++++++++++++++++++++++++++++ + +It is worth stressing that ConfigStore can be used for different purposes, and this is +reflected in where in the script ConfigStore is invoked. + +The typical use-cases are: + +* Change an Object default attributes +* Inspect/change a *specific* Object attributes +* Inspect the simulation Objects and their attributes + +As a matter of fact, some Objects might be created when the simulation starts. +Hence, ConfigStore will not "report" their attributes if invoked earlier in the code. + +A typical workflow might involve running the simulation, calling ConfigStore +at the end of the simulation (after ``Simulator::Run ()`` and before ``Simulator::Destroy ()``) +This will show all the attributes in the Objects, both those with default values, and those +with values changed during the simulation execution. + +To change these values, you'll need to either change the default (class-wide) attribute values +(in this case call ConfigStore before the Object creation), or specific object attribute +(in this case call ConfigStore after the Object creation, typically just before ``Simulator::Run ()``. + + ConfigStore GUI +++++++++++++++ There is a GTK-based front end for the ConfigStore. This allows users to use a -GUI to access and change variables. Screenshots of this feature are available -in the `|ns3| Overview `_ -presentation. +GUI to access and change variables. -To use this feature, one must install ``libgtk`` and ``libgtk-dev``; an example +Some screenshots are presented here. They are the result of using GtkConfig on +``src/lte/examples/lena-dual-stripe.cc`` after ``Simulator::Run ()``. + +.. _GtkConfig: + +.. figure:: figures/gtk-config-lena-dual-stripe-device-view.* + +.. figure:: figures/gtk-config-lena-dual-stripe-eNB-tx-power.* + + +To use this feature, one must install ``libgtk-3-dev``; an example Ubuntu installation command is: .. sourcecode:: bash - $ sudo apt-get install libgtk2.0-0 libgtk2.0-dev + $ sudo apt-get install libgtk-3-dev + +On a MacOS it is possible to install GTK-3 using `Homebrew `_. +The installation command is: + +.. sourcecode:: bash + + $ brew install gtk+3 adwaita-icon-theme + To check whether it is configured or not, check the output of the step: @@ -1183,7 +1224,7 @@ To check whether it is configured or not, check the output of the step: Python Bindings : enabled Python API Scanning Support : enabled NS-3 Click Integration : enabled - GtkConfigStore : not enabled (library 'gtk+-2.0 >= 2.12' not found) + GtkConfigStore : not enabled (library 'gtk+-3.0 >= 3.0' not found) In the above example, it was not enabled, so it cannot be used until a suitable version is installed and: @@ -1206,3 +1247,9 @@ are no :cpp:class:`ConfigStore` attributes involved:: Now, when you run the script, a GUI should pop up, allowing you to open menus of attributes on different nodes/objects, and then launch the simulation execution when you are done. + +Note that "launch the simulation" means to proceed with the simulation script. +If GtkConfigStore has been called after ``Simulator::Run ()`` the simulation will +not be started again - it will just end. + + diff --git a/src/config-store/model/display-functions.cc b/src/config-store/model/display-functions.cc index d1f28e558..5194e1352 100644 --- a/src/config-store/model/display-functions.cc +++ b/src/config-store/model/display-functions.cc @@ -16,6 +16,7 @@ * Authors: Faker Moatamri * Mathieu Lacage */ + #include "display-functions.h" #include "raw-text-config.h" #include "ns3/config.h" @@ -31,8 +32,12 @@ void cell_data_function_col_1 (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { - ModelNode *node; + ModelNode *node = 0; gtk_tree_model_get (model, iter, COL_NODE, &node, -1); + if (!node) + { + return; + } if (node->type == ModelNode::NODE_ATTRIBUTE) { StringValue str; @@ -54,11 +59,16 @@ void cell_data_function_col_0 (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { - ModelNode *node; + ModelNode *node = 0; gtk_tree_model_get (model, iter, COL_NODE, &node, -1); g_object_set (renderer, "editable", FALSE, (char*) 0); - switch (node->type) + if (!node) { + return; + } + + switch (node->type) + { case ModelNode::NODE_OBJECT: g_object_set (renderer, "text", node->object->GetInstanceTypeId ().GetName ().c_str (), (char*) 0); break; @@ -78,7 +88,7 @@ cell_data_function_col_0 (GtkTreeViewColumn *col, GtkCellRenderer *renderer, Gtk case ModelNode::NODE_ATTRIBUTE: g_object_set (renderer, "text", node->name.c_str (), (char*) 0); break; - } + } } /** @@ -91,8 +101,12 @@ cell_edited_callback (GtkCellRendererText *cell, gchar *path_string, GtkTreeModel *model = GTK_TREE_MODEL (user_data); GtkTreeIter iter; gtk_tree_model_get_iter_from_string (model, &iter, path_string); - ModelNode *node; + ModelNode *node = 0; gtk_tree_model_get (model, &iter, COL_NODE, &node, -1); + if (!node) + { + return; + } NS_ASSERT (node->type == ModelNode::NODE_ATTRIBUTE); node->object->SetAttribute (node->name, StringValue (new_text)); } @@ -136,16 +150,20 @@ cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, } int col = get_col_number_from_tree_view_column (column); - ModelNode *node; + ModelNode *node = 0; gtk_tree_model_get (model, &iter, COL_NODE, &node, -1); + if (!node) + { + return FALSE; + } switch (node->type) - { + { case ModelNode::NODE_OBJECT: if (col == 0) { std::string tip = "This object is of type " - + node->object->GetInstanceTypeId ().GetName (); + + node->object->GetInstanceTypeId ().GetName (); gtk_tooltip_set_text (tooltip, tip.c_str ()); return TRUE; } @@ -156,7 +174,7 @@ cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, PointerValue ptr; node->object->GetAttribute (node->name, ptr); std::string tip = "This object is of type " - + ptr.GetObject ()->GetInstanceTypeId ().GetName (); + + ptr.GetObject ()->GetInstanceTypeId ().GetName (); gtk_tooltip_set_text (tooltip, tip.c_str ()); return TRUE; } @@ -167,7 +185,7 @@ cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, if (col == 0) { std::string tip = "This object is of type " - + node->object->GetInstanceTypeId ().GetName (); + + node->object->GetInstanceTypeId ().GetName (); gtk_tooltip_set_text (tooltip, tip.c_str ()); return TRUE; } @@ -177,7 +195,7 @@ cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, uint32_t attrIndex = 0; TypeId tid; for (tid = node->object->GetInstanceTypeId (); tid.HasParent (); tid - = tid.GetParent ()) + = tid.GetParent ()) { for (uint32_t i = 0; i < tid.GetAttributeN (); ++i) { @@ -188,7 +206,7 @@ cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, } } } -out: if (col == 0) + out: if (col == 0) { std::string tip = tid.GetAttribute (attrIndex).help; gtk_tooltip_set_text (tooltip, tip.c_str ()); @@ -208,7 +226,7 @@ out: if (col == 0) return TRUE; } break; - } + } return FALSE; } @@ -253,67 +271,6 @@ create_view (GtkTreeStore *model) return view; } -/** - * This is the action done when the user presses on the save button. - * It will save the config to a file. - * - * \param button (unused) - * \param user_data - */ -void -save_clicked (GtkButton *button, gpointer user_data) -{ - GtkWidget *parent_window = GTK_WIDGET (user_data); - GtkWidget *dialog; - - dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_SAVE, - "_Cancel", GTK_RESPONSE_CANCEL, "_Save", - GTK_RESPONSE_ACCEPT, (char *) 0); - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), - TRUE); - - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "config.txt"); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - char *filename; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - RawTextConfigSave config; - config.SetFilename (filename); - config.Attributes (); - g_free (filename); - } - - gtk_widget_destroy (dialog); -} - -/** - * If the user presses the button load, it will load the config file into memory. - */ -void -load_clicked (GtkButton *button, gpointer user_data) -{ - GtkWidget *parent_window = GTK_WIDGET (user_data); - GtkWidget *dialog; - - dialog = gtk_file_chooser_dialog_new ("Open File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_OPEN, - "_Cancel", GTK_RESPONSE_CANCEL, "_Open", - GTK_RESPONSE_ACCEPT, (char *) 0); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - char *filename; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - RawTextConfigLoad config; - config.SetFilename (filename); - config.Attributes (); - } - - gtk_widget_destroy (dialog); -} - /** * Exit the window when exit button is pressed */ @@ -342,9 +299,12 @@ gboolean clean_model_callback (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { - ModelNode *node; + ModelNode *node = 0; gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COL_NODE, &node, -1); - delete node; + if (node) + { + delete node; + } gtk_tree_store_set (GTK_TREE_STORE (model), iter, COL_NODE, (ModelNode*) 0, -1); return FALSE; @@ -360,8 +320,12 @@ cell_data_function_col_1_config_default (GtkTreeViewColumn *col, GtkCellRenderer GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { - ModelTypeid *node; + ModelTypeid *node = 0; gtk_tree_model_get (model, iter, COL_TYPEID, &node, -1); + if (!node) + { + return; + } if (node->type == ModelTypeid::NODE_ATTRIBUTE) { g_object_set (renderer, "text", node->defaultValue.c_str (), (char*) 0); @@ -380,18 +344,23 @@ void cell_data_function_col_0_config_default (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { - ModelTypeid *node; + ModelTypeid *node = 0; gtk_tree_model_get (model, iter, COL_NODE, &node, -1); g_object_set (renderer, "editable", FALSE, (char*) 0); - switch (node->type) + if (!node) { + return; + } + + switch (node->type) + { case ModelTypeid::NODE_TYPEID: g_object_set (renderer, "text", node->tid.GetName ().c_str (), (char*) 0); break; case ModelTypeid::NODE_ATTRIBUTE: g_object_set (renderer, "text", node->name.c_str (), (char*) 0); break; - } + } } @@ -407,8 +376,12 @@ cell_edited_callback_config_default (GtkCellRendererText *cell, gchar *path_stri GtkTreeModel *model = GTK_TREE_MODEL (user_data); GtkTreeIter iter; gtk_tree_model_get_iter_from_string (model, &iter, path_string); - ModelTypeid *node; + ModelTypeid *node = 0; gtk_tree_model_get (model, &iter, COL_NODE, &node, -1); + if (!node) + { + return; + } NS_ASSERT (node->type == ModelTypeid::NODE_ATTRIBUTE); if (Config::SetDefaultFailSafe (node->tid.GetAttributeFullName (node->index),StringValue (new_text))) { @@ -448,11 +421,15 @@ cell_tooltip_callback_config_default (GtkWidget *widget, gint x, gint y, } int col = get_col_number_from_tree_view_column (column); - ModelTypeid *node; + ModelTypeid *node = 0; gtk_tree_model_get (model, &iter, COL_NODE, &node, -1); + if (!node) + { + return FALSE; + } switch (node->type) - { + { case ModelTypeid::NODE_TYPEID: if (col == 0) { @@ -483,7 +460,7 @@ cell_tooltip_callback_config_default (GtkWidget *widget, gint x, gint y, return TRUE; } break; - } + } return FALSE; } @@ -497,29 +474,37 @@ cell_tooltip_callback_config_default (GtkWidget *widget, gint x, gint y, void save_clicked_default (GtkButton *button, gpointer user_data) { - GtkWidget *parent_window = GTK_WIDGET (user_data); - GtkWidget *dialog; + GtkWindow *parent_window = GTK_WINDOW (user_data); - dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_SAVE, - "_Cancel", GTK_RESPONSE_CANCEL, "_Save", - GTK_RESPONSE_ACCEPT, (char *) 0); - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), - TRUE); + GtkFileChooserNative *native; + GtkFileChooser *chooser; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE; + gint res; - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "config.txt"); + native = gtk_file_chooser_native_new ("Save File", + parent_window, + action, + "_Save", + "_Cancel"); + chooser = GTK_FILE_CHOOSER (native); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE); + + gtk_file_chooser_set_current_name (chooser, ("config-defaults.txt")); + + res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native)); + if (res == GTK_RESPONSE_ACCEPT) { char *filename; - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + filename = gtk_file_chooser_get_filename (chooser); RawTextConfigSave config; config.SetFilename (filename); config.Default (); g_free (filename); } - gtk_widget_destroy (dialog); + g_object_unref (native); } /** @@ -531,24 +516,108 @@ save_clicked_default (GtkButton *button, gpointer user_data) void load_clicked_default (GtkButton *button, gpointer user_data) { - GtkWidget *parent_window = GTK_WIDGET (user_data); - GtkWidget *dialog; + GtkWindow *parent_window = GTK_WINDOW (user_data); + GtkFileChooserNative *native; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; + gint res; - dialog = gtk_file_chooser_dialog_new ("Open File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_OPEN, - "_Cancel", GTK_RESPONSE_CANCEL, "_Open", - GTK_RESPONSE_ACCEPT, (char *) 0); + native = gtk_file_chooser_native_new ("Open File", + parent_window, + action, + "_Open", + "_Cancel"); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native)); + if (res == GTK_RESPONSE_ACCEPT) { char *filename; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + GtkFileChooser *chooser = GTK_FILE_CHOOSER (native); + filename = gtk_file_chooser_get_filename (chooser); RawTextConfigLoad config; config.SetFilename (filename); config.Default (); + g_free (filename); } - gtk_widget_destroy (dialog); + g_object_unref (native); +} + +/** + * This is the action done when the user presses on the save button. + * It will save the config to a file. + * + * \param button (unused) + * \param user_data + */ +void +save_clicked_attribute (GtkButton *button, gpointer user_data) +{ + GtkWindow *parent_window = GTK_WINDOW (user_data); + + GtkFileChooserNative *native; + GtkFileChooser *chooser; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE; + gint res; + + native = gtk_file_chooser_native_new ("Save File", + parent_window, + action, + "_Save", + "_Cancel"); + chooser = GTK_FILE_CHOOSER (native); + + gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE); + + gtk_file_chooser_set_current_name (chooser, ("config-attributes.txt")); + + res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native)); + if (res == GTK_RESPONSE_ACCEPT) + { + char *filename; + + filename = gtk_file_chooser_get_filename (chooser); + RawTextConfigSave config; + config.SetFilename (filename); + config.Attributes (); + g_free (filename); + } + + g_object_unref (native); +} + +/** + * If the user presses the button load, it will load the config file into memory. + * + * \param button (unused) + * \param user_data + */ +void +load_clicked_attribute (GtkButton *button, gpointer user_data) +{ + GtkWindow *parent_window = GTK_WINDOW (user_data); + GtkFileChooserNative *native; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; + gint res; + + native = gtk_file_chooser_native_new ("Open File", + parent_window, + action, + "_Open", + "_Cancel"); + + res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native)); + if (res == GTK_RESPONSE_ACCEPT) + { + char *filename; + GtkFileChooser *chooser = GTK_FILE_CHOOSER (native); + filename = gtk_file_chooser_get_filename (chooser); + RawTextConfigLoad config; + config.SetFilename (filename); + config.Attributes (); + g_free (filename); + } + + g_object_unref (native); } /** @@ -599,9 +668,12 @@ gboolean clean_model_callback_config_default (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { - ModelTypeid *node; + ModelTypeid *node = 0; gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COL_TYPEID, &node, -1); - delete node; + if (node) + { + delete node; + } gtk_tree_store_set (GTK_TREE_STORE (model), iter, COL_TYPEID, (ModelTypeid*) 0, -1); return FALSE; } diff --git a/src/config-store/model/display-functions.h b/src/config-store/model/display-functions.h index 467d301de..2d067258e 100644 --- a/src/config-store/model/display-functions.h +++ b/src/config-store/model/display-functions.h @@ -63,17 +63,6 @@ cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, */ GtkWidget * create_view (GtkTreeStore *model); -/** - * This is the action done when the user presses on the save button. - * It will save the config to a file. - */ -void -save_clicked (GtkButton *button, gpointer user_data); -/** - * If the user presses the button load, it will load the config file into memory. - */ -void -load_clicked (GtkButton *button, gpointer user_data); /** * Exit the window when exit button is pressed */ @@ -106,16 +95,27 @@ void cell_data_function_col_0_config_default (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data); /** - * This is the action done when the user presses on the save button. + * This is the action done when the user presses on the save button for the Default attributes. * It will save the config to a file. */ void save_clicked_default (GtkButton *button, gpointer user_data); /** - * If the user presses the button load, it will load the config file into memory. + * If the user presses the button load, it will load the config file into memory for the Default attributes. */ void load_clicked_default (GtkButton *button, gpointer user_data); +/** + * This is the action done when the user presses on the save button for the Attributes. + * It will save the config to a file. + */ +void +save_clicked_attribute (GtkButton *button, gpointer user_data); +/** + * If the user presses the button load, it will load the config file into memory for the Attributes. + */ +void +load_clicked_attribute (GtkButton *button, gpointer user_data); /** * This functions is called whenever there is a change in the value of an attribute * If the input value is ok, it will be updated in the default value and in the diff --git a/src/config-store/model/gtk-config-store.cc b/src/config-store/model/gtk-config-store.cc index ea293c5bb..4b652f5d4 100644 --- a/src/config-store/model/gtk-config-store.cc +++ b/src/config-store/model/gtk-config-store.cc @@ -113,10 +113,10 @@ GtkConfigStore::ConfigureAttributes (void) GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); GtkWidget *save = gtk_button_new_with_label ("Save"); - g_signal_connect (save, "clicked", (GCallback) save_clicked, window); + g_signal_connect (save, "clicked", (GCallback) save_clicked_attribute, window); gtk_box_pack_end (GTK_BOX (hbox), save, FALSE, FALSE, 0); GtkWidget *load = gtk_button_new_with_label ("Load"); - g_signal_connect (load, "clicked", (GCallback) load_clicked, window); + g_signal_connect (load, "clicked", (GCallback) load_clicked_attribute, window); gtk_box_pack_end (GTK_BOX (hbox), load, FALSE, FALSE, 0); GtkWidget *exit = gtk_button_new_with_label ("Run Simulation"); g_signal_connect (exit, "clicked", (GCallback) exit_clicked_callback, window);