PageRenderTime 63ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/tabloader.c

https://gitlab.com/libreems-suite/megatunix
C | 1278 lines | 976 code | 92 blank | 210 comment | 136 complexity | ea087b78071e6a91f94cd45728ceef7f MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (C) 2002-2012 by Dave J. Andruczyk <djandruczyk at yahoo dot com>
  3. *
  4. * Linux Megasquirt tuning software
  5. *
  6. *
  7. * This software comes under the GPL (GNU Public License)
  8. * You may freely copy,distribute etc. this as long as the source code
  9. * is made available for FREE.
  10. *
  11. * No warranty is made or implied. You use this program at your own risk.
  12. */
  13. /*!
  14. \file src/tabloader.c
  15. \ingroup CoreMtx
  16. \brief The Tab loading/pre-rendering functions
  17. NOTE: This should be broken up into the plugins at some point to allow more
  18. flexibility in the gui layout of tabs and not restrict things to
  19. Glade+MTx Datamap .ini files
  20. \author David Andruczyk
  21. */
  22. #include <args.h>
  23. #include <config.h>
  24. #include <configfile.h>
  25. #include <combo_loader.h>
  26. #include <defines.h>
  27. #include <debugging.h>
  28. #include <enums.h>
  29. #include <firmware.h>
  30. #include <getfiles.h>
  31. #include <glade/glade.h>
  32. #include <glade/glade-parser.h>
  33. #include <gui_handlers.h>
  34. #include <init.h>
  35. #include <keybinder.h>
  36. #include <keyparser.h>
  37. #include <listmgmt.h>
  38. #include <notifications.h>
  39. #include <plugin.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <stringmatch.h>
  43. #include <tabloader.h>
  44. #include <tag_loader.h>
  45. #include <threads.h>
  46. #include <widgetmgmt.h>
  47. extern gconstpointer *global_data;
  48. gboolean descend_tree(GladeWidgetInfo *info, ConfigFile *);
  49. /*!
  50. \brief load_gui_tabs_pf() is called after interrogation completes
  51. successfully. It's purpose is to load all the glade files and
  52. datamaps as specified in the interrogation profile of the detected firmware.
  53. */
  54. G_MODULE_EXPORT gboolean load_gui_tabs_pf(void)
  55. {
  56. gint i = 0;
  57. gint cur = 0;
  58. ConfigFile *cfgfile = NULL;
  59. gchar * map_file = NULL;
  60. gchar * glade_file = NULL;
  61. gchar * tmpbuf = NULL;
  62. gchar * tab_name = NULL;
  63. gchar * tab_ident = NULL;
  64. gboolean tmpi = FALSE;
  65. GtkWidget *label = NULL;
  66. GtkWidget *container = NULL;
  67. GtkWidget *child = NULL;
  68. GtkWidget *notebook = NULL;
  69. GtkWidget *item = NULL;
  70. TabInfo *tabinfo = NULL;
  71. GPtrArray *tabinfos = NULL;
  72. extern GdkColor red;
  73. gboolean * hidden_list = NULL;
  74. Firmware_Details *firmware = NULL;
  75. CmdLineArgs *args = NULL;
  76. gchar * pathstub = NULL;
  77. ENTER();
  78. firmware = (Firmware_Details *)DATA_GET(global_data,"firmware");
  79. args = (CmdLineArgs *)DATA_GET(global_data,"args");
  80. if (DATA_GET(global_data,"tabs_loaded"))
  81. {
  82. EXIT();
  83. return FALSE;
  84. }
  85. if (!firmware)
  86. {
  87. EXIT();
  88. return FALSE;
  89. }
  90. if (!firmware->tab_list)
  91. {
  92. EXIT();
  93. return FALSE;
  94. }
  95. if (!firmware->tab_confs)
  96. {
  97. EXIT();
  98. return FALSE;
  99. }
  100. if (args->inhibit_tabs)
  101. {
  102. EXIT();
  103. return FALSE;
  104. }
  105. set_title(g_strdup(_("Loading Gui Tabs...")));
  106. notebook = lookup_widget("toplevel_notebook");
  107. hidden_list = (gboolean *)DATA_GET(global_data,"hidden_list");
  108. tabinfos = g_ptr_array_new();
  109. while (firmware->tab_list[i])
  110. {
  111. pathstub = g_build_filename(GUI_DATA_DIR,firmware->tab_list[i],NULL);
  112. glade_file = get_file((const gchar *)DATA_GET(global_data,"project_name"),pathstub,"glade");
  113. g_free(pathstub);
  114. pathstub = g_build_filename(GUI_DATA_DIR,firmware->tab_confs[i],NULL);
  115. map_file = get_file((const gchar *)DATA_GET(global_data,"project_name"),pathstub,"datamap");
  116. g_free(pathstub);
  117. if (!g_file_test(glade_file,G_FILE_TEST_EXISTS))
  118. {
  119. MTXDBG(TABLOADER|CRITICAL,_("GLADE FILE: \"%s.glade\" NOT FOUND\n"),firmware->tab_list[i]);
  120. update_logbar("interr_view","warning",g_strdup(_("Glade File: ")),FALSE,FALSE,TRUE);
  121. update_logbar("interr_view","info",g_strdup_printf("\"%s.glade\"",firmware->tab_list[i]),FALSE,FALSE,TRUE);
  122. update_logbar("interr_view","warning",g_strdup(_(" is MISSING!\n")),FALSE,FALSE,TRUE);
  123. i++;
  124. continue;
  125. }
  126. if (!g_file_test(map_file,G_FILE_TEST_EXISTS))
  127. {
  128. MTXDBG(TABLOADER|CRITICAL,_("DATAMAP: \"%s.datamap\" NOT FOUND\n"),firmware->tab_confs[i]);
  129. update_logbar("interr_view","warning",g_strdup(_("Datamap File: ")),FALSE,FALSE,TRUE);
  130. update_logbar("interr_view","info",g_strdup_printf("\"%s.datamap\"",firmware->tab_confs[i]),FALSE,FALSE,TRUE);
  131. update_logbar("interr_view","warning",g_strdup(_(" is MISSING!\n")),FALSE,FALSE,TRUE);
  132. i++;
  133. continue;
  134. }
  135. cfgfile = cfg_open_file(map_file);
  136. if (cfgfile)
  137. {
  138. tabinfo = g_new0(TabInfo, 1);
  139. tabinfo->glade_file = g_strdup(glade_file);
  140. tabinfo->datamap_file = g_strdup(map_file);
  141. cfg_read_string(cfgfile,"global","tab_name",&tab_name);
  142. label = gtk_label_new(NULL);
  143. tabinfo->tab_label = label;
  144. gtk_label_set_markup_with_mnemonic(GTK_LABEL(label),tab_name);
  145. if (cfg_read_boolean(cfgfile,"global","ellipsize",&tmpi))
  146. {
  147. if (tmpi)
  148. {
  149. OBJ_SET(label,"ellipsize_preferred",GINT_TO_POINTER(TRUE));
  150. if (DATA_GET(global_data,"ellipsize_tabs"))
  151. gtk_label_set_ellipsize(GTK_LABEL(label),PANGO_ELLIPSIZE_END);
  152. }
  153. }
  154. if (cfg_read_string(cfgfile,"global","bind_to_list",&tmpbuf))
  155. {
  156. OBJ_SET_FULL(label,"bind_to_list",g_strdup(tmpbuf),g_free);
  157. bind_to_lists(label,tmpbuf);
  158. g_free(tmpbuf);
  159. if (cfg_read_string(cfgfile,"global","match_type",&tmpbuf))
  160. {
  161. tmpi = translate_string(tmpbuf);
  162. g_free(tmpbuf);
  163. OBJ_SET(label,"match_type",GINT_TO_POINTER(tmpi));
  164. }
  165. }
  166. gtk_misc_set_alignment(GTK_MISC(label),0,0.5);
  167. container = gtk_vbox_new(1,0);
  168. if (cfg_read_string(cfgfile,"topframe","tab_ident",&tab_ident))
  169. {
  170. tmpi = translate_string(tab_ident);
  171. g_free(tab_ident);
  172. OBJ_SET(container,"tab_ident",GINT_TO_POINTER(tmpi));
  173. }
  174. g_free(tab_name);
  175. OBJ_SET_FULL(label,"glade_file",g_strdup(glade_file),cleanup);
  176. OBJ_SET_FULL(label,"datamap_file",g_strdup(map_file),cleanup);
  177. OBJ_SET(label,"not_rendered",GINT_TO_POINTER(TRUE));
  178. gtk_notebook_append_page(GTK_NOTEBOOK(notebook),container,label);
  179. gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook),container,TRUE);
  180. gtk_widget_show(container);
  181. cur = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook))-1;
  182. tabinfo->page_num = cur;
  183. tabinfo->notebook = GTK_NOTEBOOK(notebook);
  184. if (hidden_list[cur] == TRUE)
  185. {
  186. child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),cur);
  187. label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook),child);
  188. gtk_widget_hide(child);
  189. gtk_widget_hide(label);
  190. item = lookup_widget("show_tab_visibility_menuitem");
  191. gtk_widget_modify_text(gtk_bin_get_child(GTK_BIN(item)),GTK_STATE_NORMAL,&red);
  192. }
  193. g_ptr_array_add(tabinfos,(gpointer)tabinfo);
  194. }
  195. cfg_free(cfgfile);
  196. g_free(map_file);
  197. g_free(glade_file);
  198. i++;
  199. if (!firmware)
  200. break;
  201. }
  202. preload_deps(tabinfos);
  203. DATA_SET_FULL(global_data,"tabinfos",tabinfos,dealloc_tabinfos);
  204. DATA_SET(global_data,"tabs_loaded",GINT_TO_POINTER(TRUE));
  205. MTXDBG(TABLOADER,_("All is well, leaving...\n\n"));
  206. set_title(g_strdup(_("Gui Tabs Loaded...")));
  207. gdk_flush();
  208. EXIT();
  209. return TRUE;
  210. }
  211. /*!
  212. \brief load_gui_tabs_pf() is called after interrogation completes
  213. successfully. It's purpose is to load all the glade files and datamaps
  214. as specified in the interrogation profile of the detected firmware.
  215. \param notebook is the pointer to the notebook the new tab should be placed
  216. \param page is the page number to load
  217. \returns TRUE on success, FALSE on failure
  218. */
  219. G_MODULE_EXPORT gboolean load_actual_tab(GtkNotebook *notebook, gint page)
  220. {
  221. ConfigFile *cfgfile = NULL;
  222. gchar * map_file = NULL;
  223. gchar * glade_file = NULL;
  224. gchar * tmpbuf = NULL;
  225. GladeXML *xml = NULL;
  226. GtkWidget *label = NULL;
  227. GtkWidget *topframe = NULL;
  228. GtkWidget *placeholder = NULL;
  229. GHashTable *groups = NULL;
  230. GList *tab_widgets = NULL;
  231. BindGroup *bindgroup = NULL;
  232. extern GdkColor red;
  233. ENTER();
  234. placeholder = gtk_notebook_get_nth_page(notebook,page);
  235. label = gtk_notebook_get_tab_label(notebook,placeholder);
  236. glade_file = (gchar *)OBJ_GET(label,"glade_file");
  237. map_file = (gchar *)OBJ_GET(label,"datamap_file");
  238. xml = glade_xml_new(glade_file,"topframe",NULL);
  239. g_return_val_if_fail(xml,FALSE);
  240. thread_update_logbar("interr_view",NULL,g_strdup(_("Load of tab: ")),FALSE,FALSE);
  241. thread_update_logbar("interr_view","info", g_strdup_printf("\"%s\"",glade_file),FALSE,FALSE);
  242. thread_update_logbar("interr_view",NULL,g_strdup(_(" completed.\n")),FALSE,FALSE);
  243. thread_update_logbar("interr_view",NULL,g_strdup(_("Load of tabconf: ")),FALSE,FALSE);
  244. thread_update_logbar("interr_view","info", g_strdup_printf("\"%s\"",map_file),FALSE,FALSE);
  245. cfgfile = cfg_open_file(map_file);
  246. if (cfgfile)
  247. {
  248. topframe = glade_xml_get_widget(xml,"topframe");
  249. if (topframe == NULL)
  250. {
  251. MTXDBG(TABLOADER|CRITICAL,_("\"topframe\" not found in xml, ABORTING!!\n"));
  252. set_title(g_strdup(_("ERROR Gui Tab XML problem, \"topframe\" element not found!!!")));
  253. EXIT();
  254. return FALSE;
  255. }
  256. OBJ_SET_FULL(topframe,"glade_xml",(gpointer)xml,g_object_unref);
  257. // bind_data() is recursive and will take
  258. // care of all children
  259. bindgroup = g_new0(BindGroup,1);
  260. groups = load_groups(cfgfile);
  261. bindgroup->cfgfile = cfgfile;
  262. bindgroup->groups = groups;
  263. bindgroup->map_file = g_strdup(map_file);
  264. /* tab_widgets = g_list_prepend(tab_widgets,topframe);
  265. OBJ_SET(topframe,"tab_widgets",tab_widgets);
  266. */
  267. bindgroup->topframe = topframe;
  268. bind_data(topframe,(gpointer)bindgroup);
  269. g_free(bindgroup->map_file);
  270. if (groups)
  271. g_hash_table_destroy(groups);
  272. groups = NULL;
  273. /* Clear not_rendered flag */
  274. OBJ_SET(label,"not_rendered",NULL);
  275. populate_master(topframe,(gpointer)cfgfile);
  276. gtk_box_pack_start(GTK_BOX(placeholder),topframe,TRUE,TRUE,0);
  277. OBJ_SET(placeholder,"topframe",topframe);
  278. glade_xml_signal_autoconnect(xml);
  279. g_free(bindgroup);
  280. if (cfg_read_string(cfgfile,"global","post_functions",&tmpbuf))
  281. {
  282. run_post_functions(tmpbuf);
  283. g_free(tmpbuf);
  284. }
  285. cfg_free(cfgfile);
  286. gtk_widget_show(topframe);
  287. /*printf("Current length of tab_widgets is %i\n",g_list_length(OBJ_GET(topframe,"tab_widgets")));*/
  288. thread_update_logbar("interr_view",NULL,g_strdup(_(" completed.\n")),FALSE,FALSE);
  289. }
  290. update_groups_pf();
  291. update_sources_pf();
  292. /* Allow gui to update as it should.... */
  293. gdk_flush();
  294. EXIT();
  295. return TRUE;
  296. }
  297. /*!
  298. \brief free's the data from the struct Group structure
  299. \param value is the pointer to the struct Group to be deallocated
  300. \see load_groups
  301. */
  302. G_MODULE_EXPORT void group_free(gpointer value)
  303. {
  304. Group *group = (Group *)value;
  305. gint i = 0;
  306. DataType keytype = MTX_INT;
  307. ENTER();
  308. for (i=0;i<group->num_keys;i++)
  309. {
  310. keytype = (DataType)translate_string(group->keys[i]);
  311. OBJ_SET(group->object,group->keys[i],NULL);
  312. }
  313. g_object_unref(group->object);
  314. g_strfreev(group->keys);
  315. g_free(group->keytypes);
  316. g_free(group);
  317. EXIT();
  318. return;
  319. }
  320. /*!
  321. \brief Called from the load_gui_tabs_pf function in order to
  322. load common settings for a group of controls.
  323. \param cfgfile is the pointer to the configuration file to read
  324. the group information from.
  325. \see group_free
  326. \see load_gui_tabs_pf
  327. \returns a GHashTable * to a newly created hashtable of the groups that were
  328. loaded. The groups are indexed in the hashtable by group name.
  329. */
  330. G_MODULE_EXPORT GHashTable * load_groups(ConfigFile *cfgfile)
  331. {
  332. gint x = 0;
  333. gint tmpi = 0;
  334. gchar * tmpbuf = NULL;
  335. gchar **groupnames = NULL;
  336. gchar *section = NULL;
  337. gint num_groups = 0;
  338. Group *group = NULL;
  339. GHashTable *groups = NULL;
  340. void (*load_dep_obj)(GObject *,ConfigFile *,const gchar *,const gchar *) = NULL;
  341. ENTER();
  342. if(cfg_read_string(cfgfile,"global","groups",&tmpbuf))
  343. {
  344. groupnames = parse_keys(tmpbuf,&num_groups,",");
  345. MTXDBG(TABLOADER,_("Number of groups to load settings for is %i\n"),num_groups);
  346. g_free(tmpbuf);
  347. }
  348. else
  349. {
  350. EXIT();
  351. return NULL;
  352. }
  353. groups = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,group_free);
  354. for (x=0;x<num_groups;x++)
  355. {
  356. /* Create structure and allocate ram for it */
  357. group = g_new0(Group, 1);
  358. section = g_strdup(groupnames[x]);
  359. if(cfg_read_string(cfgfile,section,"keys",&tmpbuf))
  360. {
  361. group->keys = parse_keys(tmpbuf,&group->num_keys,",");
  362. MTXDBG(TABLOADER,_("Number of keys for section %s is %i\n"),section,group->num_keys);
  363. g_free(tmpbuf);
  364. }
  365. else
  366. {
  367. MTXDBG(TABLOADER,_("\"keys\" key in section \"%s\" NOT found, aborting this group.\n"),section);
  368. g_free(group);
  369. g_free(section);
  370. continue;
  371. }
  372. group->object = (GObject *)g_object_new(GTK_TYPE_INVISIBLE,NULL);
  373. g_object_ref_sink(group->object);
  374. /* If this widget has a "depend_on" tag we need to
  375. * load the dependency information and store it for
  376. * use when needed...
  377. */
  378. if (cfg_read_string(cfgfile,section,"depend_on",&tmpbuf))
  379. {
  380. if (get_symbol("load_dependencies_obj",(void **)&load_dep_obj))
  381. load_dep_obj(group->object,cfgfile,section,"depend_on");
  382. g_free(tmpbuf);
  383. }
  384. /* Adds on "default" options to any other groups */
  385. if (g_ascii_strcasecmp(section,"defaults") != 0)
  386. group->page = bind_group_data(cfgfile, group->object, groups, "defaults");
  387. if (cfg_read_int(cfgfile,section,"page",&tmpi))
  388. group->page = tmpi;
  389. /* Binds the rest of the settings, overriding any defaults */
  390. bind_keys(group->object,cfgfile,section,group->keys,group->num_keys);
  391. /* Store it in the hashtable... */
  392. g_hash_table_insert(groups,g_strdup(section),(gpointer)group);
  393. g_free(section);
  394. }
  395. g_strfreev(groupnames);
  396. if (group)
  397. {
  398. EXIT();
  399. return groups;
  400. }
  401. EXIT();
  402. return NULL;
  403. }
  404. /*!
  405. \brief bind_group_data() is called to bind data widget that is defined in
  406. a group. (saves from having to duplicate a large number of keys/values for
  407. a big group of widgets) This function will set the necessary data on the
  408. Gui object.
  409. \param cfg is the pointer to the config file object to read data from
  410. \param object is the widget to bind the data to
  411. \param groups is the hashtable that holds the group common data
  412. \param groupname is the textual name of the group to get the data for to
  413. be bound to the widget
  414. \returns the page of the group
  415. */
  416. G_MODULE_EXPORT gint bind_group_data(ConfigFile *cfg, GObject *object, GHashTable *groups, const gchar *groupname)
  417. {
  418. gint i = 0;
  419. gint tmpi = 0;
  420. Group *group = NULL;
  421. DataType keytype = MTX_STRING;
  422. ENTER();
  423. group = (Group *)g_hash_table_lookup(groups,groupname);
  424. if (!group)
  425. {
  426. MTXDBG(TABLOADER|CRITICAL,_("Group \"%s\" not found in file %s\n"),groupname,cfg->filename);
  427. EXIT();
  428. return -1;
  429. }
  430. /* Copy data from the group object to the */
  431. /* Grab hidden data if it exists */
  432. if (OBJ_GET(group->object, "dep_object"))
  433. OBJ_SET(object,"dep_object",OBJ_GET(group->object, "dep_object"));
  434. for (i=0;i<group->num_keys;i++)
  435. {
  436. keytype = (DataType)translate_string(group->keys[i]);
  437. switch((DataType)keytype)
  438. {
  439. case MTX_INT:
  440. case MTX_BOOL:
  441. case MTX_ENUM:
  442. tmpi = (GINT)OBJ_GET(group->object,group->keys[i]);
  443. OBJ_SET(object,group->keys[i],GINT_TO_POINTER(tmpi));
  444. if (strstr(group->keys[i], "temp_dep"))
  445. {
  446. OBJ_SET(object,"widget_temp",DATA_GET(global_data,"mtx_temp_units"));
  447. }
  448. break;
  449. case MTX_FLOAT:
  450. OBJ_SET_FULL(object,group->keys[i],g_memdup(OBJ_GET(group->object,group->keys[i]),sizeof(gfloat)),g_free);
  451. break;
  452. case MTX_STRING:
  453. OBJ_SET_FULL(object,group->keys[i],(gchar *)g_strdup((gchar *)OBJ_GET(group->object,group->keys[i])),g_free);
  454. if (OBJ_GET(object,"tooltip") != NULL)
  455. gtk_widget_set_tooltip_text((GtkWidget *)OBJ_GET(object,"self"),(gchar *)OBJ_GET(object,"tooltip"));
  456. if (OBJ_GET(group->object, "bind_to_list"))
  457. bind_to_lists((GtkWidget *)OBJ_GET(object,"self"),(gchar *)OBJ_GET(group->object, "bind_to_list"));
  458. break;
  459. default:
  460. break;
  461. }
  462. }
  463. EXIT();
  464. return group->page;
  465. }
  466. /*!
  467. \brief bind_to_lists() binds a widget to any number of string named lists.
  468. \param widget is the widget to bind to lists
  469. \param lists is the command seperated string list of lists to bind this
  470. widget into.
  471. */
  472. G_MODULE_EXPORT void bind_to_lists(GtkWidget * widget, const gchar * lists)
  473. {
  474. gint bind_num_keys = 0;
  475. gchar **tmpvector = NULL;
  476. GList *dest_list = NULL;
  477. gint i = 0;
  478. ENTER();
  479. if (!lists)
  480. {
  481. printf(_("Error, bind_to_lists(), lists is NULL\n"));
  482. EXIT();
  483. return;
  484. }
  485. tmpvector = parse_keys(lists,&bind_num_keys,",");
  486. /* This looks convoluted, but it allows for an arbritrary
  487. * number of lists, that are indexed by a keyword.
  488. * The get_list function looks the list up in a hashtable, if
  489. * it isn't found (i.e. new list) it returns NULL which is OK
  490. * as g_list_prepend() uses that to create a new list, that
  491. * returned list is used to store back into the hashtable so
  492. * that the list is always stored and up to date...
  493. */
  494. for (i=0;i<bind_num_keys;i++)
  495. {
  496. dest_list = get_list(tmpvector[i]);
  497. dest_list = g_list_prepend(dest_list,(gpointer)widget);
  498. store_list(tmpvector[i],dest_list);
  499. }
  500. g_strfreev(tmpvector);
  501. EXIT();
  502. return;
  503. }
  504. /*!
  505. \brief Removed a pointer/widget from a list of lists
  506. \param lists is the comma separated list of list names
  507. \param data is the pointer to the item to remove from each list
  508. */
  509. G_MODULE_EXPORT void remove_from_lists(const gchar * lists, gpointer data)
  510. {
  511. gint i = 0;
  512. gint bind_num_keys = 0;
  513. gchar **tmpvector = NULL;
  514. GList *list = NULL;
  515. ENTER();
  516. if (!lists)
  517. {
  518. EXIT();
  519. return;
  520. }
  521. tmpvector = parse_keys(lists,&bind_num_keys,",");
  522. for (i=0;i<bind_num_keys;i++)
  523. {
  524. list = get_list(tmpvector[i]);
  525. list = g_list_remove(list,(gpointer)data);
  526. store_list(tmpvector[i],list);
  527. }
  528. g_strfreev(tmpvector);
  529. EXIT();
  530. return;
  531. }
  532. /*!
  533. \brief bind_data() is a recursive function that is called for every container
  534. widget in a glade frame and it's purpose is to search the datamap file passed
  535. for the widget names in the glade file and if it's fond in the datamap to
  536. load all the attribues listed and bind them to the object using GTK+'s
  537. object model.
  538. \param widget is the widget passed to load attributes on
  539. \param user_data is the pointer to a BingGroup structure.
  540. */
  541. G_MODULE_EXPORT void bind_data(GtkWidget *widget, gpointer user_data)
  542. {
  543. BindGroup *bindgroup = (BindGroup *)user_data;
  544. ConfigFile *cfgfile = bindgroup->cfgfile;
  545. GHashTable *groups = bindgroup->groups;
  546. gchar * tmpbuf = NULL;
  547. gchar * section = NULL;
  548. gchar ** keys = NULL;
  549. gint num_keys = 0;
  550. gint offset = 0;
  551. gint page = 0;
  552. gint index = 0;
  553. gchar * initializer = NULL;
  554. GdkColor color;
  555. gchar *size = NULL;
  556. gint count = 0;
  557. gint tmpi = 0;
  558. gboolean hidden = FALSE;
  559. gchar *ptr = NULL;
  560. gchar **vector = NULL;
  561. gchar **vec2 = NULL;
  562. void (*func)(void) = NULL;
  563. GList *list = NULL;
  564. GList *list2 = NULL;
  565. const gchar *name = NULL;
  566. gboolean indexed = FALSE;
  567. Firmware_Details *firmware = NULL;
  568. GList ***ecu_widgets = NULL;
  569. GList *tab_widgets = NULL;
  570. void (*load_dep_obj)(GObject *, ConfigFile *,const gchar *,const gchar *) = NULL;
  571. ENTER();
  572. MTXDBG(TABLOADER,_("Entered"));
  573. ecu_widgets = (GList ***)DATA_GET(global_data,"ecu_widgets");
  574. firmware = (Firmware_Details *)DATA_GET(global_data,"firmware");
  575. g_return_if_fail(ecu_widgets);
  576. g_return_if_fail(firmware);
  577. if (!GTK_IS_WIDGET(widget))
  578. {
  579. EXIT();
  580. return;
  581. }
  582. if (GTK_IS_WIDGET(widget))
  583. if (GTK_IS_CONTAINER(widget))
  584. gtk_container_foreach(GTK_CONTAINER(widget),bind_data,user_data);
  585. name = gtk_widget_get_name(widget);
  586. if (!name)
  587. {
  588. EXIT();
  589. return;
  590. }
  591. if (NULL != (ptr = g_strrstr_len(name,strlen(name),"_of_")))
  592. {
  593. indexed = TRUE;
  594. ptr = g_strrstr_len(name,ptr-name,"_");
  595. tmpbuf = g_strdelimit(g_strdup(ptr),"_",' ');
  596. section = g_strndup(name,ptr-name);
  597. /*printf("(indexed) section is %s\n",section);*/
  598. gint result = sscanf(tmpbuf,"%d of %d",&index,&count);
  599. /*printf("sscanf result %i\n",result);*
  600. * printf("Found indexed value for \"%s\", index %i, count %i\n",tmpbuf,index,count);
  601. */
  602. g_free(tmpbuf);
  603. }
  604. else
  605. section = g_strdup(name);
  606. if(cfg_read_string(cfgfile, section, "keys", &tmpbuf))
  607. {
  608. keys = parse_keys(tmpbuf,&num_keys,",");
  609. MTXDBG(TABLOADER,_("Number of keys for %s is %i\n"),section,num_keys);
  610. g_free(tmpbuf);
  611. }
  612. else
  613. {
  614. g_free(section);
  615. EXIT();
  616. return;
  617. }
  618. page = -1;
  619. /* Store ptr to self in qdata, needed for bind_to_lists from groups*/
  620. OBJ_SET(widget,"self",widget);
  621. /* Bind the data in the "defaults" group per tab to EVERY var in that
  622. * tab
  623. */
  624. page = bind_group_data(cfgfile, G_OBJECT(widget), groups, "defaults");
  625. if(cfg_read_string(cfgfile, section, "group", &tmpbuf))
  626. {
  627. page = bind_group_data(cfgfile,G_OBJECT(widget),groups,tmpbuf);
  628. g_free(tmpbuf);
  629. }
  630. if ((!cfg_read_int(cfgfile, section, "page", &page)) && (page == -1))
  631. {
  632. MTXDBG(TABLOADER|CRITICAL,_("Object %s doesn't have a page assigned!!!!\n"),section);
  633. }
  634. /* Bind widgets to lists if they have the bind_to_list flag set...
  635. */
  636. tmpbuf = NULL;
  637. if (cfg_read_string(cfgfile, section, "bind_to_list", &tmpbuf))
  638. {
  639. bind_to_lists(widget, tmpbuf);
  640. g_free(tmpbuf);
  641. }
  642. if (cfg_read_boolean(cfgfile,section,"ellipsize",&tmpi))
  643. {
  644. if ((GTK_IS_LABEL(widget)) && (tmpi))
  645. {
  646. OBJ_SET(widget,"ellipsize_preferred",GINT_TO_POINTER(TRUE));
  647. if (DATA_GET(global_data,"ellipsize_tabs"))
  648. gtk_label_set_ellipsize(GTK_LABEL(widget),PANGO_ELLIPSIZE_END);
  649. }
  650. }
  651. /* Color selections */
  652. if (cfg_read_string(cfgfile, section, "active_fg", &tmpbuf))
  653. {
  654. gdk_color_parse(tmpbuf, &color);
  655. gtk_widget_modify_fg(widget, GTK_STATE_NORMAL, &color);
  656. g_free(tmpbuf);
  657. }
  658. if (cfg_read_string(cfgfile, section, "inactive_fg", &tmpbuf))
  659. {
  660. gdk_color_parse(tmpbuf, &color);
  661. gtk_widget_modify_fg(widget, GTK_STATE_INSENSITIVE, &color);
  662. g_free(tmpbuf);
  663. }
  664. /* If this widget has a "depend_on" tag we need to load the dependancy
  665. * information and store it for use when needed...
  666. */
  667. if (cfg_read_string(cfgfile,section,"depend_on",&tmpbuf))
  668. {
  669. if (get_symbol("load_dependencies_obj",(void **)&load_dep_obj))
  670. load_dep_obj(G_OBJECT(widget),cfgfile,section,"depend_on");
  671. g_free(tmpbuf);
  672. }
  673. /* If this widget (a textview) has "create_tags" we call a special
  674. * handler just for that..
  675. */
  676. if (cfg_read_string(cfgfile,section,"create_tags",&tmpbuf))
  677. {
  678. load_tags(G_OBJECT(widget),cfgfile,section);
  679. g_free(tmpbuf);
  680. }
  681. /* If this widget has "tooltip" set the tip on the widget */
  682. if (cfg_read_string(cfgfile,section,"tooltip",&tmpbuf))
  683. {
  684. gtk_widget_set_tooltip_text(widget,tmpbuf);
  685. g_free(tmpbuf);
  686. }
  687. /* If this widget (a label) has "set_label" we set the label on it
  688. */
  689. if (cfg_read_string(cfgfile,section,"set_label",&tmpbuf))
  690. {
  691. /* printf("setting label on %s to \"%s\"\n",glade_get_widget_name(widget),tmpbuf);*/
  692. gtk_label_set_text(GTK_LABEL(widget),tmpbuf);
  693. g_free(tmpbuf);
  694. }
  695. /* If this widget is temp dependant, set the current units on it
  696. */
  697. if (cfg_read_string(cfgfile,section,"temp_dep",&tmpbuf))
  698. {
  699. OBJ_SET(widget,"widget_temp",DATA_GET(global_data,"mtx_temp_units"));
  700. g_free(tmpbuf);
  701. }
  702. /* If this widget has "register_as", register it with the supplied name
  703. */
  704. if (cfg_read_string(cfgfile,section,"register_as",&tmpbuf))
  705. {
  706. register_widget(tmpbuf,widget);
  707. g_free(tmpbuf);
  708. }
  709. /* If this widget has visible_functions defined */
  710. if (cfg_read_string(cfgfile,section,"visible_functions",&tmpbuf))
  711. {
  712. vector = g_strsplit(tmpbuf,",",-1);
  713. g_free(tmpbuf);
  714. for (guint i=0;i<g_strv_length(vector);i++)
  715. {
  716. vec2 = g_strsplit(vector[i],":",2);
  717. if (g_strv_length(vec2) != 2)
  718. {
  719. printf("ERROR in %s, visible_functions param is missing the framerate parameter (func:fps)\n",cfgfile->filename);
  720. g_strfreev(vec2);
  721. continue;
  722. }
  723. gint fps = (GINT)g_strtod(vec2[1],NULL);
  724. get_symbol(vec2[0],(void **)&func);
  725. if (func)
  726. {
  727. list = g_list_prepend(list,(gpointer)func);
  728. list2 = g_list_prepend(list2,GINT_TO_POINTER(fps));
  729. }
  730. g_strfreev(vec2);
  731. }
  732. g_strfreev(vector);
  733. OBJ_SET_FULL(widget,"func_list",list,g_list_free);
  734. OBJ_SET_FULL(widget,"func_fps_list",list2,g_list_free);
  735. }
  736. /* If this widget has "initializer" there's a global variable
  737. * with it's name on it
  738. */
  739. if (cfg_read_string(cfgfile,section,"initializer",&initializer))
  740. {
  741. gint widget_type = 0;
  742. if (!cfg_read_string(cfgfile,section,"widget_type",&tmpbuf))
  743. MTXDBG(TABLOADER|CRITICAL,_("Object %s has initializer, but no widget_type!!!!\n"),section);
  744. else
  745. widget_type = translate_string(tmpbuf);
  746. g_free(tmpbuf);
  747. switch (widget_type)
  748. {
  749. case MTX_RANGE:
  750. gtk_range_set_value(GTK_RANGE(widget),(GINT)DATA_GET(global_data,initializer));
  751. break;
  752. case MTX_SPINBUTTON:
  753. gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),(GINT)DATA_GET(global_data,initializer));
  754. break;
  755. case MTX_ENTRY:
  756. gtk_entry_set_text(GTK_ENTRY(widget),(gchar *)DATA_GET(global_data,initializer));
  757. default:
  758. break;
  759. }
  760. g_free(initializer);
  761. }
  762. /* Hidden widgets have special handlers and should NOT be updated normally */
  763. cfg_read_boolean(cfgfile,section, "hidden", &hidden);
  764. offset = -1;
  765. cfg_read_int(cfgfile,section, "offset", &offset);
  766. if (offset >= 0 && indexed)
  767. {
  768. /*printf("indexed widget %s\n",name); */
  769. if (cfg_read_string(cfgfile, section, "size", &size))
  770. {
  771. offset += index * get_multiplier ((DataSize)translate_string (size));
  772. g_free(size);
  773. }
  774. else
  775. {
  776. if(OBJ_GET(widget, "size"))
  777. {
  778. offset += index * get_multiplier ((DataSize)(GINT)OBJ_GET(widget, "size"));
  779. }
  780. else
  781. {
  782. MTXDBG(TABLOADER|CRITICAL,_("Indexed Object %s has index and offset, but no size!!!!\n"),section);
  783. g_free(section);
  784. EXIT();
  785. return;
  786. }
  787. }
  788. /*printf("widget %s, offset %i\n",name,offset);*/
  789. OBJ_SET(widget,"offset",GINT_TO_POINTER(offset));
  790. }
  791. if (offset >= 0)
  792. {
  793. /* The way we do it now is to STORE widgets in LISTS for each
  794. * offset, thus we can have multiple on screen controls bound
  795. * to single data offset in the ECU
  796. */
  797. if (page < 0)
  798. {
  799. MTXDBG(TABLOADER|CRITICAL,_("Attempting to append widget beyond bounds of Firmware Parameters, there is a bug with this datamap widget %s, page %i, at offset %i...\n\n"),section,page,offset);
  800. g_free(section);
  801. EXIT();
  802. return;
  803. }
  804. if (page < firmware->total_pages)
  805. {
  806. if (offset >= firmware->page_params[page]->length)
  807. MTXDBG(TABLOADER|CRITICAL,_("Attempting to append widget beyond bounds of Firmware Parameters, there is a bug with this datamap widget %s, at offset %i...\n\n"),section,offset);
  808. else if (!hidden)
  809. {
  810. tab_widgets = OBJ_GET(bindgroup->topframe,"tab_widgets");
  811. tab_widgets = g_list_prepend(tab_widgets, widget);
  812. OBJ_SET(bindgroup->topframe,"tab_widgets",tab_widgets);
  813. ecu_widgets[page][offset] = g_list_prepend(
  814. ecu_widgets[page][offset],
  815. (gpointer)widget);
  816. }
  817. }
  818. else
  819. MTXDBG(TABLOADER|CRITICAL,_("Attempting to append widget beyond bounds of Firmware Parameters, there is a bug with this datamap for widget %s, at page %i offset %i...\n\n"),section,page,offset);
  820. }
  821. /* If there is a "group" key in a section it means that it gets the
  822. * rest of it's setting from the groupname listed. This reduces
  823. * redundant keys all throughout the file...
  824. */
  825. bind_keys(G_OBJECT(widget), cfgfile, section, keys, num_keys);
  826. g_strfreev(keys);
  827. /* If this widget has the "choices" key (combobox)
  828. */
  829. if (cfg_read_string(cfgfile,section,"choices",&tmpbuf))
  830. {
  831. combo_setup(G_OBJECT(widget),cfgfile,section);
  832. g_free(tmpbuf);
  833. }
  834. if (cfg_read_string(cfgfile,section,"post_functions_with_arg",&tmpbuf))
  835. {
  836. run_post_functions_with_arg(tmpbuf,widget);
  837. g_free(tmpbuf);
  838. }
  839. if (cfg_read_string(cfgfile,section,"post_functions",&tmpbuf))
  840. {
  841. run_post_functions(tmpbuf);
  842. g_free(tmpbuf);
  843. }
  844. if (cfg_read_boolean(cfgfile,section,"show_widget",&tmpi))
  845. {
  846. if (tmpi)
  847. gtk_widget_show(widget);
  848. else
  849. gtk_widget_hide(widget);
  850. }
  851. if (cfg_read_string(cfgfile,section,"set_tab_labels",&tmpbuf))
  852. {
  853. if (GTK_IS_NOTEBOOK(widget))
  854. {
  855. vector=g_strsplit(tmpbuf,",",-1);
  856. if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget)) == g_strv_length(vector))
  857. {
  858. for (int i=0;i<g_strv_length(vector);i++)
  859. {
  860. gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(widget),
  861. gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget),i),
  862. vector[i]);
  863. }
  864. }
  865. g_strfreev(vector);
  866. }
  867. g_free(tmpbuf);
  868. }
  869. g_free(section);
  870. MTXDBG(TABLOADER,_("Leaving"));
  871. EXIT();
  872. return;
  873. }
  874. /*!
  875. \brief run_post_functions() is called to run a function AFTER tab loading.
  876. It'll search the exported symbols of MegaTunix for the function and if
  877. found execute it
  878. \param functions is the CSV list of functions to run
  879. */
  880. G_MODULE_EXPORT void run_post_functions(const gchar * functions)
  881. {
  882. ENTER();
  883. run_post_functions_with_arg(functions,NULL);
  884. EXIT();
  885. return;
  886. }
  887. /*!
  888. \brief run_post_functions_with_arg() is called to run a function AFTER
  889. tab loading is complete. It'll search the exported symbols of MegaTunix
  890. for the function and if found execute it with the passed widget as an
  891. argument.
  892. \param functions is the CSV list of functions to run
  893. \param widget is the pointer to widget to be passed to the function
  894. */
  895. G_MODULE_EXPORT void run_post_functions_with_arg(const gchar * functions, GtkWidget *widget)
  896. {
  897. void (*post_func_w_arg)(GtkWidget *) = NULL;
  898. void (*post_func)(void) = NULL;
  899. gchar ** vector = NULL;
  900. guint i = 0;
  901. ENTER();
  902. vector = g_strsplit(functions,",",-1);
  903. for (i=0;i<g_strv_length(vector);i++)
  904. {
  905. /* If widget defined, pass to post function */
  906. if (widget)
  907. {
  908. if (get_symbol(vector[i],(void **)&post_func_w_arg))
  909. post_func_w_arg(widget);
  910. else
  911. MTXDBG(TABLOADER|CRITICAL,_("Error finding symbol \"%s\", error:\n\t%s\n"),vector[i],g_module_error());
  912. }
  913. else /* If no widget find funct with no args.. */
  914. {
  915. if (get_symbol(vector[i],(void **)&post_func))
  916. post_func();
  917. else
  918. MTXDBG(TABLOADER|CRITICAL,_("Error finding symbol \"%s\", error:\n\t%s\n"),vector[i],g_module_error());
  919. }
  920. }
  921. g_strfreev(vector);
  922. EXIT();
  923. return;
  924. }
  925. /*!
  926. \brief Pre-loads the dependencies related to a tab/group of tabs
  927. \param data is the pointer to a GPtrArray list of tab infos, used to traverse
  928. each tab config file to preload the needed interdependancy structures
  929. */
  930. gboolean preload_deps(gpointer data)
  931. {
  932. Firmware_Details *firmware = NULL;
  933. GPtrArray *array = (GPtrArray *)data;
  934. TabInfo *tabinfo = NULL;
  935. GladeInterface *iface = NULL;
  936. GladeWidgetInfo *info = NULL;
  937. ConfigFile *cfgfile = NULL;
  938. guint i = 0;
  939. guint j = 0;
  940. ENTER();
  941. firmware = (Firmware_Details *)DATA_GET(global_data,"firmware");
  942. g_return_val_if_fail(firmware,FALSE);
  943. for (i=0;i<array->len;i++)
  944. {
  945. tabinfo = (TabInfo *)g_ptr_array_index(array,i);
  946. iface = glade_parser_parse_file(tabinfo->glade_file,NULL);
  947. cfgfile = cfg_open_file(tabinfo->datamap_file);
  948. if ((!cfgfile) || (!iface))
  949. continue;
  950. for(j=0;j<iface->n_toplevels;j++)
  951. {
  952. info = iface->toplevels[j];
  953. descend_tree(info,cfgfile);
  954. }
  955. glade_interface_destroy(iface);
  956. cfg_free(cfgfile);
  957. }
  958. io_cmd(firmware->get_all_command,NULL);
  959. EXIT();
  960. return FALSE; /* Make it not run again... */
  961. }
  962. /*!
  963. \brief descends into a GladeWidgetInfo tree looking for special case
  964. widgets to handle
  965. \param info is the pointer to a GladeWidgetInfo structure
  966. \param cfgfile is the pointer to the corresponding datamap file
  967. \returns TRUE, unless eat end of the tree
  968. */
  969. gboolean descend_tree(GladeWidgetInfo *info,ConfigFile *cfgfile)
  970. {
  971. static GHashTable *widget_2_tab_hash = NULL;
  972. static ConfigFile *last_cfgfile = NULL;
  973. static gchar * prefix = NULL;
  974. gchar *groups = NULL;
  975. gchar *bitvals = NULL;
  976. gchar *source_key = NULL;
  977. gchar *source_values = NULL;
  978. gint bitval = 0;
  979. gint bitmask = 0;
  980. gint offset = 0;
  981. gint page = 0;
  982. /*gint canID = 0;*/
  983. DataSize size = MTX_U08;
  984. GObject *object = NULL;
  985. GList *list = NULL;
  986. guint i = 0;
  987. ENTER();
  988. if (!widget_2_tab_hash)
  989. {
  990. widget_2_tab_hash = (GHashTable *)DATA_GET(global_data,"widget_2_tab_hash");
  991. g_return_val_if_fail(widget_2_tab_hash,FALSE);
  992. }
  993. /*
  994. if (!info->parent)
  995. printf("%s is a TOPLEVEL\n",info->name);
  996. else if (info->n_children == 0)
  997. {
  998. printf("%s is a BOTTOM WIDGET\n",info->name);
  999. EXIT();
  1000. return FALSE;
  1001. }
  1002. else
  1003. printf("%s\n",info->name);
  1004. printf("widget %s has %i children\n",info->name,info->n_children);
  1005. */
  1006. for (i=0;i<info->n_children;i++)
  1007. descend_tree(info->children[i].child,cfgfile);
  1008. if (last_cfgfile != cfgfile)
  1009. {
  1010. if (prefix)
  1011. cleanup(prefix);
  1012. if(!cfg_read_string(cfgfile,"global","id_prefix", &prefix))
  1013. prefix = NULL;
  1014. last_cfgfile = cfgfile;
  1015. }
  1016. if (cfg_find_section(cfgfile,info->name)) // This widget exists
  1017. {
  1018. if (prefix)
  1019. g_hash_table_insert(widget_2_tab_hash,g_strdup_printf("%s%s",prefix,info->name),g_strdup(cfgfile->filename));
  1020. else
  1021. g_hash_table_insert(widget_2_tab_hash,g_strdup(info->name),g_strdup(cfgfile->filename));
  1022. }
  1023. if (cfg_read_string(cfgfile,info->name,"source_values",&source_values))
  1024. {
  1025. if (!cfg_read_string(cfgfile,info->name,"source_key",&source_key))
  1026. {
  1027. MTXDBG(TABLOADER|CRITICAL,_("%s needs source_key\n"),info->name);
  1028. EXIT();
  1029. return TRUE;
  1030. }
  1031. if (!cfg_read_int(cfgfile,info->name,"offset",&offset))
  1032. {
  1033. MTXDBG(TABLOADER|CRITICAL,_("%s needs offset\n"),info->name);
  1034. EXIT();
  1035. return TRUE;
  1036. }
  1037. if (!cfg_read_int(cfgfile,info->name,"bitmask",&bitmask))
  1038. {
  1039. MTXDBG(TABLOADER|CRITICAL,_("%s needs bitmask\n"),info->name);
  1040. EXIT();
  1041. return TRUE;
  1042. }
  1043. if (!cfg_read_string(cfgfile,info->name,"bitvals",&bitvals))
  1044. {
  1045. if (!cfg_read_int(cfgfile,info->name,"bitval",&bitval))
  1046. {
  1047. MTXDBG(TABLOADER|CRITICAL,_("%s needs bitvals or bitval\n"),info->name);
  1048. EXIT();
  1049. return TRUE;
  1050. }
  1051. }
  1052. if (!cfg_read_int(cfgfile,info->name,"page",&page))
  1053. {
  1054. if (!cfg_read_int(cfgfile,"defaults","page",&page))
  1055. {
  1056. MTXDBG(TABLOADER|CRITICAL,_("%s has no page defined!\n"),info->name);
  1057. EXIT();
  1058. return TRUE;
  1059. }
  1060. }
  1061. object = (GObject *)g_object_new(GTK_TYPE_INVISIBLE,NULL);
  1062. g_object_ref_sink(object);
  1063. /*OBJ_SET(object,"canID",GINT_TO_POINTER(canID));*/
  1064. OBJ_SET(object,"page",GINT_TO_POINTER(page));
  1065. OBJ_SET(object,"offset",GINT_TO_POINTER(offset));
  1066. OBJ_SET(object,"size",GINT_TO_POINTER(size));
  1067. OBJ_SET(object,"bitmask",GINT_TO_POINTER(bitmask));
  1068. if (bitvals)
  1069. OBJ_SET_FULL(object,"bitvals",g_strdup(bitvals),g_free);
  1070. else
  1071. OBJ_SET(object,"bitval",GINT_TO_POINTER(bitval));
  1072. OBJ_SET_FULL(object,"source_key",g_strdup(source_key),g_free);
  1073. OBJ_SET_FULL(object,"source_values",g_strdup(source_values),g_free);
  1074. list = (GList *)DATA_GET(global_data,"source_list");
  1075. list = g_list_prepend(list,object);
  1076. DATA_SET(global_data,"source_list",(gpointer)list);
  1077. cleanup(groups);
  1078. cleanup(bitvals);
  1079. cleanup(source_key);
  1080. cleanup(source_values);
  1081. }
  1082. if (cfg_read_string(cfgfile,info->name,"toggle_groups",&groups))
  1083. {
  1084. if (!cfg_read_int(cfgfile,info->name,"offset",&offset))
  1085. {
  1086. MTXDBG(TABLOADER|CRITICAL,_("%s needs offset\n"),info->name);
  1087. EXIT();
  1088. return TRUE;
  1089. }
  1090. if (!cfg_read_int(cfgfile,info->name,"bitmask",&bitmask))
  1091. {
  1092. MTXDBG(TABLOADER|CRITICAL,_("%s needs bitmask\n"),info->name);
  1093. EXIT();
  1094. return TRUE;
  1095. }
  1096. if (!cfg_read_string(cfgfile,info->name,"bitvals",&bitvals))
  1097. {
  1098. if (!cfg_read_int(cfgfile,info->name,"bitval",&bitval))
  1099. {
  1100. MTXDBG(TABLOADER|CRITICAL,_("%s needs bitvals or bitval\n"),info->name);
  1101. EXIT();
  1102. return TRUE;
  1103. }
  1104. }
  1105. if (!cfg_read_int(cfgfile,info->name,"page",&page))
  1106. {
  1107. if (!cfg_read_int(cfgfile,"defaults","page",&page))
  1108. {
  1109. MTXDBG(TABLOADER|CRITICAL,_("%s has no page defined!\n"),info->name);
  1110. EXIT();
  1111. return TRUE;
  1112. }
  1113. }
  1114. /*
  1115. if (!cfg_read_int(cfgfile,info->name,"canID",&canID))
  1116. {
  1117. if (!cfg_read_int(cfgfile,"defaults","canID",&canID))
  1118. {
  1119. printf("%s has no canID defined!\n",info->name);
  1120. EXIT();
  1121. return TRUE;
  1122. }
  1123. }
  1124. */
  1125. object = (GObject *)g_object_new(GTK_TYPE_INVISIBLE,NULL);
  1126. g_object_ref_sink(object);
  1127. /*OBJ_SET(object,"canID",GINT_TO_POINTER(canID));*/
  1128. OBJ_SET(object,"page",GINT_TO_POINTER(page));
  1129. OBJ_SET(object,"offset",GINT_TO_POINTER(offset));
  1130. OBJ_SET(object,"size",GINT_TO_POINTER(size));
  1131. OBJ_SET(object,"bitmask",GINT_TO_POINTER(bitmask));
  1132. if (bitvals)
  1133. OBJ_SET_FULL(object,"bitvals",g_strdup(bitvals),g_free);
  1134. else
  1135. OBJ_SET(object,"bitval",GINT_TO_POINTER(bitval));
  1136. OBJ_SET_FULL(object,"toggle_groups",g_strdup(groups),g_free);
  1137. list = (GList *)DATA_GET(global_data,"toggle_group_list");
  1138. list = g_list_prepend(list,object);
  1139. DATA_SET(global_data,"toggle_group_list",(gpointer)list);
  1140. cleanup(groups);
  1141. cleanup(bitvals);
  1142. cleanup(source_key);
  1143. cleanup(source_values);
  1144. }
  1145. EXIT();
  1146. return TRUE;
  1147. }
  1148. /*!
  1149. \brief loads a tab when its clicked upon
  1150. \param datamap is the datamap that goes with this tab
  1151. \returns TRUE on success, FALSE otherwise
  1152. */
  1153. G_MODULE_EXPORT gboolean handle_dependant_tab_load(gchar * datamap)
  1154. {
  1155. GPtrArray *tabinfos = NULL;
  1156. guint i = 0;
  1157. TabInfo *tabinfo = NULL;
  1158. ENTER();
  1159. g_return_val_if_fail(datamap,FALSE);
  1160. tabinfos = (GPtrArray *)DATA_GET(global_data,"tabinfos");
  1161. g_return_val_if_fail(tabinfos,FALSE);
  1162. for (i=0;i<tabinfos->len;i++)
  1163. {
  1164. tabinfo = (TabInfo *)g_ptr_array_index(tabinfos,i);
  1165. if (!tabinfo)
  1166. continue;
  1167. if (g_ascii_strcasecmp(tabinfo->datamap_file,datamap) == 0)
  1168. {
  1169. g_signal_handlers_block_by_func (G_OBJECT (tabinfo->notebook),
  1170. (gpointer)notebook_page_changed,
  1171. NULL);
  1172. set_title(g_strdup(_("Rendering Tab...")));
  1173. load_actual_tab(tabinfo->notebook,tabinfo->page_num);
  1174. g_signal_handlers_unblock_by_func (G_OBJECT (tabinfo->notebook),
  1175. (gpointer)notebook_page_changed,
  1176. NULL);
  1177. set_title(g_strdup(_("Tab Loaded")));
  1178. EXIT();
  1179. return TRUE;
  1180. }
  1181. }
  1182. EXIT();
  1183. return FALSE;
  1184. }