1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003-2010 Stuart D. Brorson.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 /*------------------------------------------------------------------*/
22 * \brief Functions for the toplevel window
24 * This file holds functions used to handle the toplevel window and
25 * various widgets held by that window. Widges used to handle
26 * (GtkSheet *sheet) itself are held in a different file.
34 /*------------------------------------------------------------------
35 * Includes required to run graphical widgets.
36 *------------------------------------------------------------------*/
45 /*------------------------------------------------------------------
46 * Gattrib specific includes
47 *------------------------------------------------------------------*/
48 #include <libgeda/libgeda.h> /* geda library fcns */
49 #include "../include/struct.h" /* typdef and struct declarations */
50 #include "../include/prototype.h" /* function prototypes */
51 #include "../include/globals.h"
53 #ifdef HAVE_LIBDMALLOC
57 /*------------------------------------------------------------------
58 * Gattrib specific defines
59 *------------------------------------------------------------------*/
60 #define GATTRIB_THEME_ICON_NAME "geda-gattrib"
63 x_window_create_menu(GtkWindow
*window
, GtkWidget
**menubar
);
66 x_window_set_default_icon( void );
68 /*! \brief Initialises the toplevel gtksheet
70 * This function initializes the toplevel gtksheet stuff.
72 * It basically just initializes the following widgets:
74 * GTK_CONTAINER *main_vbox
77 * Note that it doesn't display the spreadsheet itself. This is done
78 * in x_sheet_build_sheet. I suppose I could postpone all initialization
79 * until x_sheet_build_sheet, but I figured that I could at least do
80 * some initialization here. In particular, the stuff to put up the
81 * menus is long & it is worthwhile to separate it from other code.
82 * Maybe I'll refactor this later.
90 /* Set default icon */
91 x_window_set_default_icon();
93 /* window is a global declared in globals.h. */
94 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
96 gtk_window_set_title( GTK_WINDOW(window
), "gattrib -- gEDA attribute editor");
97 gtk_window_set_default_size(GTK_WINDOW(window
), 750, 600);
99 gtk_signal_connect (GTK_OBJECT (window
), "delete_event",
100 GTK_SIGNAL_FUNC (gattrib_really_quit
), 0);
102 /* ----- Now create main_vbox. This is a container which organizes child ----- */
103 /* ----- widgets into a vertical column. ----- */
104 main_vbox
= gtk_vbox_new(FALSE
,1);
105 gtk_container_set_border_width(GTK_CONTAINER(main_vbox
), 1);
106 gtk_container_add(GTK_CONTAINER(window
), GTK_WIDGET(main_vbox
) );
108 /* ----- Now create menu bar ----- */
109 x_window_create_menu(GTK_WINDOW(window
), &menu_bar
);
110 gtk_box_pack_start(GTK_BOX (main_vbox
), menu_bar
, FALSE
, TRUE
, 0);
112 /* ----- Now init notebook widget ----- */
113 notebook
= gtk_notebook_new();
114 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook
), GTK_POS_BOTTOM
);
115 gtk_box_pack_start(GTK_BOX(main_vbox
), notebook
, TRUE
, TRUE
, 0);
117 /* ----- Now malloc -- but don't fill out -- space for sheets ----- */
118 /* This basically sets up the overhead for the sheets, as I understand
119 * it. The memory for the actual sheet cells is allocated later,
120 * when gtk_sheet_new is invoked, I think. */
121 sheets
= g_malloc0(NUM_SHEETS
* sizeof(GtkWidget
*));
125 /*------------------------------------------------------------------
126 * \brief File Open menu
128 * File open menu. Currently unimplemented.
129 * \todo this should really be done in two stages:
130 * -# close the current project and reinitialize structures
131 * -# load the new project
133 #ifdef UNIMPLEMENTED_FEATURES
137 x_dialog_unimplemented_feature();
141 file_list
= x_fileselect_open();
143 /* Load the files, don't check if it went OK */
144 x_fileselect_load_files(file_list
);
146 g_slist_foreach(file_list
, (GFunc
)g_free
, NULL
);
147 g_slist_free(file_list
);
153 * \brief File->Save menu item
155 * Implement the File->Save menu
160 s_toplevel_gtksheet_to_toplevel(); /* Dumps sheet data into TOPLEVEL */
161 s_page_save_all(pr_current
); /* saves all pages in design */
163 sheet_head
->CHANGED
= FALSE
;
167 * \brief File->Export CSV menu item
169 * Implement the File->Export CSV menu item
172 menu_file_export_csv()
176 /* first verify that we are on the correct page (components) */
177 cur_page
= gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
));
179 /* Check that we are on components page. */
181 x_dialog_export_file();
183 x_dialog_unimplemented_feature(); /* We only support export
189 * \brief Edit->New attrib menu item
191 * Implement the New attrib menu item
194 menu_edit_newattrib()
198 /* first verify that we are on the correct page (components) */
199 cur_page
= gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
));
201 /* Check that we are on components page. */
203 x_dialog_newattrib(); /* This creates dialog box */
208 * \brief Edit->Delete Attribute menu item
210 * Implements the Delete Attribute menu item
213 menu_edit_delattrib()
215 x_dialog_delattrib();
219 * The Gtk action table
221 static const GtkActionEntry actions
[] = {
222 /* name, stock-id, label, accelerator, tooltip, callback function */
224 { "file", NULL
, "_File"},
225 /* { "file-open", GTK_STOCK_OPEN, "Open", "<Control>O", "", menu_file_open}, */
226 { "file-save", GTK_STOCK_SAVE
, "Save", "<Control>S", "", menu_file_save
},
227 { "file-export-csv", NULL
, "Export CSV", "", "", menu_file_export_csv
},
228 /* { "file-print", GTK_STOCK_PRINT, "Print", "<Control>P", "", x_dialog_unimplemented_feature}, */
229 { "file-quit", GTK_STOCK_QUIT
, "Quit", "<Control>Q", "", G_CALLBACK(gattrib_really_quit
)},
232 { "edit", NULL
, "_Edit"},
233 { "edit-add-attrib", NULL
, "Add new attrib column", "", "", menu_edit_newattrib
},
234 { "edit-delete-attrib", NULL
, "Delete attrib column", "", "", menu_edit_delattrib
},
235 /* { "edit-find-attrib", GTK_STOCK_FIND, "Find attrib value", "<Control>F", "", x_dialog_unimplemented_feature}, */
236 /* { "edit-search-replace-attrib-value", NULL, "Search and replace attrib value", "", "", x_dialog_unimplemented_feature}, */
237 /* { "edit-search-for-refdes", NULL, "Search for refdes", "", "", x_dialog_unimplemented_feature}, */
239 /* Visibility menu */
240 { "visibility", NULL
, "_Visibility"},
241 { "visibility-invisible", NULL
, "Set selected invisible", "", "", s_visibility_set_invisible
},
242 { "visibility-name-only", NULL
, "Set selected name visible only", "", "", s_visibility_set_name_only
},
243 { "visibility-value-only", NULL
, "Set selected value visible only", "", "", s_visibility_set_value_only
},
244 { "visibility-name-value", NULL
, "Set selected name and value visible", "", "", s_visibility_set_name_and_value
},
247 { "help", NULL
, "_Help"},
248 { "help-about", GTK_STOCK_ABOUT
, "About", "", "", x_dialog_about_dialog
},
252 /*! \brief Create and attach the menu bar
254 * Create the menu bar and attach it to the main window.
256 * First, the GtkActionGroup object is created and filled with
257 * entries of type GtkActionEntry (each entry specifies a single
258 * action, such as opening a file). Then the GtkUIManager object
259 * is created and used to load menus.xml file with the menu
260 * description. Finally, the GtkAccelGroup is added to the
261 * main window to enable keyboard accelerators and a pointer
262 * to the menu bar is retrieved from the GtkUIManager object.
263 * \param window Window to add the menubar to
264 * \param [out] menubar Created menubar
267 x_window_create_menu(GtkWindow
*window
, GtkWidget
**menubar
)
271 GtkActionGroup
*action_group
;
272 GError
*error
= NULL
;
274 /* Create and fill the action group object */
275 action_group
= gtk_action_group_new("");
276 gtk_action_group_add_actions(action_group
, actions
, G_N_ELEMENTS(actions
), NULL
);
278 /* Create the UI manager object */
279 ui
= gtk_ui_manager_new();
281 gtk_ui_manager_insert_action_group(ui
, action_group
, 0);
283 menu_file
= g_build_filename(s_path_sys_data (), "gattrib-menus.xml", NULL
);
285 gtk_ui_manager_add_ui_from_file(ui
, menu_file
, &error
);
287 /* An error occured, terminate */
288 fprintf(stderr
, "Error loading %s:\n%s\n", menu_file
, error
->message
);
294 gtk_window_add_accel_group (window
, gtk_ui_manager_get_accel_group(ui
));
296 *menubar
= gtk_ui_manager_get_widget(ui
, "/ui/menubar/");
300 /*! \brief Add all items to the top level window
302 * This function updates the top level window
303 * after a new page is read in.
305 * It does the following:
307 * -# Create a new gtksheet having the current dimensions.
308 * -# Call x_gktsheet_add_row_labels(comp_count, master_*_list_head)
309 * -# Call x_gktsheet_add_col_labels(comp_attrib_count, master_*_attrib_list_head)
310 * -# Call x_gktsheet_add_row_labels(net_count, master_*_list_head)
311 * -# Call x_gktsheet_add_col_labels(net_attrib_count, master_*_attrib_list_head)
312 * -# loop on i, j -- call x_gtksheet_add_entry(i, j, attrib_value)
313 * -# Call gtk_widget_show(window) to show new window.
319 gint num_rows
, num_cols
;
320 gchar
*text
, *error_string
;
321 gint visibility
, show_name_value
;
323 /* Do these sanity check to prevent later segfaults */
324 if (sheet_head
->comp_count
== 0) {
325 error_string
= "No components found in entire design!\n"
326 "Do you have refdeses on your components?";
327 x_dialog_fatal_error(error_string
, 1);
330 if (sheet_head
->comp_attrib_count
== 0) {
331 error_string
= "No configurable component attributes found in entire design!\n"
332 "Please attach at least some attributes before running gattrib.";
333 x_dialog_fatal_error(error_string
, 2);
336 if (sheet_head
->pin_count
== 0) {
337 error_string
= "No pins found on any components!\n"
338 "Please check your design.";
339 x_dialog_fatal_error(error_string
, 3);
343 /* initialize the gtksheet. */
344 x_gtksheet_init(); /* this creates a new gtksheet having dimensions specified
345 * in sheet_head->comp_count, etc. . . */
347 if (sheet_head
->comp_count
> 0 ) {
348 x_gtksheet_add_row_labels(GTK_SHEET(sheets
[0]),
349 sheet_head
->comp_count
, sheet_head
->master_comp_list_head
);
350 x_gtksheet_add_col_labels(GTK_SHEET(sheets
[0]),
351 sheet_head
->comp_attrib_count
, sheet_head
->master_comp_attrib_list_head
);
354 #ifdef UNIMPLEMENTED_FEATURES
355 /* This is not ready. I need to implement net attributes */
356 if (sheet_head
->net_count
> 0 ) {
357 x_gtksheet_add_row_labels(GTK_SHEET(sheets
[1]),
358 sheet_head
->net_count
, sheet_head
->master_net_list_head
);
359 x_gtksheet_add_col_labels(GTK_SHEET(sheets
[1]),
360 sheet_head
->net_attrib_count
, sheet_head
->master_net_attrib_list_head
);
362 x_gtksheet_add_row_labels(GTK_SHEET(sheets
[1]), 1, NULL
);
363 x_gtksheet_add_col_labels(GTK_SHEET(sheets
[1]), 1, NULL
);
367 #ifdef UNIMPLEMENTED_FEATURES
368 if (sheet_head
->pin_count
> 0 ) {
369 x_gtksheet_add_row_labels(GTK_SHEET(sheets
[2]),
370 sheet_head
->pin_count
, sheet_head
->master_pin_list_head
);
371 x_gtksheet_add_col_labels(GTK_SHEET(sheets
[2]),
372 sheet_head
->pin_attrib_count
, sheet_head
->master_pin_attrib_list_head
);
376 /* ------ Comp sheet: put values in the individual cells ------- */
377 num_rows
= sheet_head
->comp_count
;
378 num_cols
= sheet_head
->comp_attrib_count
;
379 for (i
= 0; i
< num_rows
; i
++) {
380 for (j
= 0; j
< num_cols
; j
++) {
381 if ( (sheet_head
->component_table
)[i
][j
].attrib_value
) { /* NULL = no entry */
382 text
= (gchar
*) g_strdup( (sheet_head
->component_table
)[i
][j
].attrib_value
);
383 visibility
= (sheet_head
->component_table
)[i
][j
].visibility
;
384 show_name_value
= (sheet_head
->component_table
)[i
][j
].show_name_value
;
385 x_gtksheet_add_cell_item( GTK_SHEET(sheets
[0]), i
, j
, (gchar
*) text
,
386 visibility
, show_name_value
);
392 #ifdef UNIMPLEMENTED_FEATURES
393 /* ------ Net sheet: put values in the individual cells ------- */
394 num_rows
= sheet_head
->net_count
;
395 num_cols
= sheet_head
->net_attrib_count
;
396 for (i
= 0; i
< num_rows
; i
++) {
397 for (j
= 0; j
< num_cols
; j
++) {
398 if ( (sheet_head
->net_table
)[i
][j
].attrib_value
) { /* NULL = no entry */
399 text
= (gchar
*) g_strdup( (sheet_head
->net_table
)[i
][j
].attrib_value
);
400 visibility
= (sheet_head
->net_table
)[i
][j
].visibility
;
401 show_name_value
= (sheet_head
->component_table
)[i
][j
].show_name_value
;
402 x_gtksheet_add_cell_item( GTK_SHEET(sheets
[1]), i
, j
, (gchar
*) text
,
403 visibility
, show_name_value
);
410 #ifdef UNIMPLEMENTED_FEATURES
411 /* ------ Pin sheet: put pin attribs in the individual cells ------- */
412 num_rows
= sheet_head
->pin_count
;
413 num_cols
= sheet_head
->pin_attrib_count
;
414 for (i
= 0; i
< num_rows
; i
++) {
415 for (j
= 0; j
< num_cols
; j
++) {
416 if ( (sheet_head
->pin_table
)[i
][j
].attrib_value
) { /* NULL = no entry */
417 text
= (gchar
*) g_strdup( (sheet_head
->pin_table
)[i
][j
].attrib_value
);
418 /* pins have no visibility attributes, must therefore provide default. */
419 x_gtksheet_add_cell_item( GTK_SHEET(sheets
[2]), i
, j
, (gchar
*) text
,
420 VISIBLE
, SHOW_VALUE
);
427 gtk_widget_show_all( GTK_WIDGET(window
) );
431 /*! \brief Set application icon
433 * Setup default icon for GTK windows
435 * Sets the default window icon by name, to be found in the current icon
436 * theme. The name used is #defined above as GATTRIB_THEME_ICON_NAME.
439 x_window_set_default_icon( void )
441 gtk_window_set_default_icon_name( GATTRIB_THEME_ICON_NAME
);