1 /*
2 voiceGUI.c
3 code for listing and selecting Gnaural voices
4 Depends on:
5 glib.h
6 gtk/gtk.h
7 main.h
8 voiceGUI.h
9 ScheduleGUI.h
10
11 Theory: give main_UpdateGUI_Voices() a GtkVBox, and this fills it with a table
12
13 Copyright (C) 2011 Bret Logan
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 //TODO:
31 // - 20100625: Duplicate Voices not actually updating list (i think it updates list before BB or SG have the new data)
32 // - 20100624: Make list NOT keep refilling from SG/BB, but literally delete the specific LIST row when voice deleted, etc.
33 // - 20100624: Verify that SG ID's can be in arbitrary order for everything to still function right
34 // - 20100623: figure out why main_UpdateGUI_Voices is getting called double times
35 // - 20100622: make voice list box sizeable
36 // - 20100623: make windows pop-out (dissociable)
37 // - 20100624: add "Solo"
38 // - 20100625: figure out why a voice has to be visible to be deleted
39
40 #include <glib.h>
41 #include <gtk/gtk.h>
42 #include "main.h"
43 #include "voiceGUI.h"
44 #include "ScheduleGUI.h"
45 #include "BinauralBeat.h"
46
47 /////////////////////////////////////////////////////////////
48 //Globals variables:
49 GtkWidget *VG_TreeView = NULL; //GtkWidget so i can add to other widgets, but cast to GtkTreeView when needed
50 gboolean VG_RelistFlag = FALSE; //gets set to tell lister to redo list
51 enum
52 {
53 VG_COLUMN_COUNT,
54 VG_COLUMN_VIEW,
55 VG_COLUMN_MUTE,
56 VG_COLUMN_TYPE,
57 VG_COLUMN_DESC,
58 VG_COLUMN_COUNTTOTS,
59 VG_COLUMN_COUNTSELS,
60 VG_COLUMNCOUNT
61 };
62
63 /////////////////////////////////////////////////////
64 //20070629: returns the SG_Voice that matches the ID or NULL if
65 //there is no match. Pray to god that IDs are always unique, 'k?
VG_GetVoice(int ID)66 SG_Voice *VG_GetVoice (int ID)
67 {
68 SG_Voice *curVoice = SG_FirstVoice;
69
70 while (curVoice != NULL)
71 {
72 if (curVoice->ID == ID)
73 {
74 return curVoice;
75 }
76 curVoice = curVoice->NextVoice;
77 }
78 SG_DBGOUT_INT ("No SG ID", ID);
79 VG_RelistFlag = TRUE;
80 return NULL;
81 }
82
83 /////////////////////////////////////////////////////
84 //20070629: returns the equivalent BB voice from a SG voice,
85 //needed because BB is arrays and SG linked-lists, but BB is always
86 //sync'd to SG's list order
87 //IMPORTANT: ERROR RETURNS -1
VG_GetVoiceIndex(SG_Voice * refVoice)88 int VG_GetVoiceIndex (SG_Voice * refVoice)
89 {
90 SG_Voice *curVoice = SG_FirstVoice;
91 int count = 0;
92
93 while (curVoice != NULL)
94 {
95 if (curVoice == refVoice)
96 {
97 return count;
98 }
99 count++;
100 curVoice = curVoice->NextVoice;
101 }
102 SG_DBGOUT ("NO SUCH VOICE!");
103 VG_RelistFlag = TRUE;
104 return -1;
105 }
106
107 /////////////////////////////////////
108 //20100624: status: works ok
VG_GetVoiceCount()109 gint VG_GetVoiceCount ()
110 {
111 return BB_VoiceCount;
112 }
113
114 /////////////////////////////////////////////////////////
115 //20100623: need to rework
116 //Purpose: to manually highlight a specific entry in vgui
VG_List_SetSelectedVoice(GtkTreeModel * model,GtkTreeSelection * selection,gint index)117 void VG_List_SetSelectedVoice (GtkTreeModel * model,
118 GtkTreeSelection * selection, gint index)
119 {
120 int i;
121 GtkTreeIter iter;
122 gtk_tree_model_get_iter_first (model, &iter);
123 for (i = 0; i < index; i++)
124 gtk_tree_model_iter_next (model, &iter);
125 gtk_tree_selection_select_iter (selection, &iter);
126 }
127
128 /////////////////////////////////////
129 //20100622: status: works ok
VG_Checkbox_View(GtkCellRendererToggle * cell,gchar * path_str,gpointer data)130 static void VG_Checkbox_View (GtkCellRendererToggle * cell,
131 gchar * path_str, gpointer data)
132 {
133 GtkTreeModel *model = (GtkTreeModel *) data;
134 GtkTreeIter iter;
135 GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
136 gboolean CheckboxState;
137 gint voiceID;
138
139 // get toggled iter and extract checkbox state and voiceID from it:
140 gtk_tree_model_get_iter (model, &iter, path);
141 gtk_tree_model_get (model, &iter, VG_COLUMN_VIEW, &CheckboxState,
142 VG_COLUMN_COUNT, &voiceID, -1);
143
144 SG_DBGOUT_INT ("View, SG ID", voiceID);
145
146 //get voice index:
147 SG_Voice *curVoice = VG_GetVoice (voiceID);
148 if (NULL != curVoice)
149 {
150 curVoice->hide = CheckboxState;
151
152 if (TRUE == curVoice->hide)
153 {
154 SG_VoiceTestLegalSelection ();
155 if (curVoice->state == SG_SELECTED)
156 curVoice->state = SG_UNSELECTED;
157 }
158 }
159
160 // toggle the checkbox value FALSE/TRUE:
161 CheckboxState ^= 1;
162
163 // set new value
164 gtk_list_store_set (GTK_LIST_STORE (model), &iter, VG_COLUMN_VIEW,
165 CheckboxState, -1);
166
167 // clean up
168 gtk_tree_path_free (path);
169 SG_ConvertDataToXY (main_drawing_area); //20110519
170 }
171
172 /////////////////////////////////////
173 //20100622
VG_Checkbox_Mute(GtkCellRendererToggle * cell,gchar * path_str,gpointer data)174 static void VG_Checkbox_Mute (GtkCellRendererToggle * cell,
175 gchar * path_str, gpointer data)
176 {
177 GtkTreeModel *model = (GtkTreeModel *) data;
178 GtkTreeIter iter;
179 GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
180 gboolean CheckboxState;
181 gint voiceID;
182
183 // get toggled iter
184 gtk_tree_model_get_iter (model, &iter, path);
185 gtk_tree_model_get (model, &iter, VG_COLUMN_MUTE, &CheckboxState,
186 VG_COLUMN_COUNT, &voiceID, -1);
187
188 SG_DBGOUT_INT ("Mute, SG ID:", voiceID);
189
190 // do something with the value
191 CheckboxState ^= 1;
192
193 //get voice index:
194 SG_Voice *curVoice = VG_GetVoice (voiceID);
195 if (NULL != curVoice)
196 {
197 curVoice->mute = CheckboxState;
198 voiceID = VG_GetVoiceIndex (curVoice);
199 if (-1 != voiceID)
200 {
201 BB_Voice[voiceID].mute = CheckboxState;
202 SG_DBGOUT_INT ("Mute, BB ID", voiceID);
203 }
204 }
205 // set new value
206 gtk_list_store_set (GTK_LIST_STORE (model), &iter, VG_COLUMN_MUTE,
207 CheckboxState, -1);
208 // clean up
209 gtk_tree_path_free (path);
210 }
211
212 ////////////////////////////////
213 //20100622: status: working, not done
VG_onSelectionChange(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreePath * path,gboolean path_currently_selected,gpointer userdata)214 gboolean VG_onSelectionChange (GtkTreeSelection * selection,
215 GtkTreeModel * model,
216 GtkTreePath * path,
217 gboolean path_currently_selected,
218 gpointer userdata)
219 {
220 // g_print ("New Row Selected (%s line %d)\n",__FILE__, __LINE__);
221 GtkTreeIter iter;
222
223 if (gtk_tree_model_get_iter (model, &iter, path))
224 {
225 int voiceID;
226 //20100624: voiceID should never be assumed to be an actual count
227 //index because it can be wildly out of whack when voices are deleted
228 gtk_tree_model_get (model, &iter, VG_COLUMN_COUNT, &voiceID, -1);
229 if (!path_currently_selected)
230 {
231 SG_DBGOUT_INT ("Selected SG Voice:", voiceID);
232 SG_SelectVoice (VG_GetVoice (voiceID)); //this looks for that ID, not using it a literal count
233 }
234 else
235 {
236 SG_DBGOUT_INT ("Unselected SG Voice:", voiceID);
237 }
238 }
239 //SG_DBGOUT_INT ("BB-VG=", VG_VerifyCount(GTK_TREE_VIEW (VG_TreeView)));
240 return TRUE; // allow selection state to change
241 }
242
243 ///////////////////////////////////////////////////////////////////
244 //20100622: Brings up Voices Properties box for selected row
245 // status: working, not done
VG_onRightButton(GtkWidget * treeview,GdkEventButton * event,gpointer userdata)246 gboolean VG_onRightButton (GtkWidget * treeview,
247 GdkEventButton * event, gpointer userdata)
248 {
249 if (NULL == gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)))
250 {
251 SG_DBGOUT ("Treeview == NULL");
252 }
253 //VG_RefillList (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview))); //20100624 - critical!
254 // single click with the right mouse button:
255 if (event->type == GDK_BUTTON_PRESS && event->button == 3)
256 {
257 //g_print ("Single right click on the tree view.\n");
258 SG_Voice *curVoice = SG_SelectVoice (NULL); //return currently selected voice
259 main_VoicePropertiesDialog (main_drawing_area, curVoice);
260 //VG_DestroyTreeView ();
261 //VG_RefillList (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview))); //20100624 - critical!
262 //main_UpdateGUI_Voices (main_vboxVoices);
263
264 // optional: select row if no row is selected or only
265 // one other row is selected
266 if (0)
267 {
268 GtkTreeSelection *selection;
269
270 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
271
272 // Note: gtk_tree_selection_count_selected_rows() does not
273 // exist in gtk+-2.0, only in gtk+ >= v2.2 !
274 if (gtk_tree_selection_count_selected_rows (selection) <= 1)
275 {
276 GtkTreePath *path;
277
278 // Get tree path for row that was clicked
279 if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview),
280 (gint) event->x,
281 (gint) event->y,
282 &path, NULL, NULL, NULL))
283 {
284 gtk_tree_selection_unselect_all (selection);
285 gtk_tree_selection_select_path (selection, path);
286 gtk_tree_path_free (path);
287 }
288 }
289 } // end of optional bit
290 //view_popup_menu(treeview, event, userdata);
291 return TRUE; // we handled this
292 }
293 return FALSE; // we did not handle this
294 }
295
296 /////////////////////////////////////////////
297 //20100625 - gives user ability to edit descriptions on-the-fly
VG_EditDescription_callback(GtkCellRendererText * cell,gchar * path_string,gchar * new_text,gpointer user_data)298 void VG_EditDescription_callback (GtkCellRendererText * cell,
299 gchar * path_string,
300 gchar * new_text, gpointer user_data)
301 {
302 int voiceID;
303 GtkTreeIter iter;
304 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (VG_TreeView));
305 gtk_tree_model_get_iter_from_string (model, &iter, path_string);
306 gtk_tree_model_get (model, &iter, VG_COLUMN_COUNT, &voiceID, -1);
307 SG_DBGOUT (new_text);
308 SG_Voice *curVoice = VG_GetVoice (voiceID);
309 if (NULL != curVoice)
310 {
311 SG_StringAllocateAndCopy (&(curVoice->description), (char *) new_text);
312 gtk_list_store_set (GTK_LIST_STORE (model), &iter, VG_COLUMN_DESC, new_text,
313 -1);
314 }
315 }
316
317 /////////////////////////////////////////////
318 //20100625 - toggles all-on or all off
VG_Mute_column_clicked(GtkTreeViewColumn * column,gpointer user_data)319 void VG_Mute_column_clicked (GtkTreeViewColumn * column, gpointer user_data)
320 {
321 SG_Voice *curVoice = SG_FirstVoice;
322 int VoiceIndex = 0;
323 static gboolean val = TRUE;
324
325 while (curVoice != NULL)
326 {
327 curVoice->mute = BB_Voice[VoiceIndex].mute = val;
328 curVoice = curVoice->NextVoice;
329 ++VoiceIndex;
330 }
331 val ^= 1;
332 VG_FillList (GTK_TREE_VIEW (VG_TreeView));
333 }
334
335 /////////////////////////////////////////////
336 //20100625 - toggles see-all or see-none
VG_View_column_clicked(GtkTreeViewColumn * column,gpointer user_data)337 void VG_View_column_clicked (GtkTreeViewColumn * column, gpointer user_data)
338 {
339 SG_Voice *curVoice = SG_FirstVoice;
340 static gboolean val = TRUE;
341
342 while (curVoice != NULL)
343 {
344 curVoice->hide = val;
345 curVoice = curVoice->NextVoice;
346 }
347 val ^= 1;
348 VG_FillList (GTK_TREE_VIEW (VG_TreeView));
349 SG_ConvertDataToXY (main_drawing_area); //20110519
350 }
351
352 //=====================
353 /////////////////////////////////////////////
354 //20100622 - Adds columns to the List store. Called after
355 // VG_List_CreateModel ()
VG_List_AddColumns(GtkTreeView * treeview)356 static void VG_List_AddColumns (GtkTreeView * treeview)
357 {
358 GtkCellRenderer *renderer;
359 GtkTreeViewColumn *column;
360 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
361
362 //These are the columns:
363 // VG_COLUMN_COUNT, int
364 // VG_COLUMN_VIEW, checkbox
365 // VG_COLUMN_MUTE, checkbox
366 // VG_COLUMN_TYPE, string
367 // VG_COLUMN_DESC, string
368 // VG_COLUMN_COUNTTOTS, int
369 // VG_COLUMN_COUNTSELS, int
370
371 //Now for the actual columns:
372 // VG_COLUMN_COUNT, int:
373 renderer = gtk_cell_renderer_text_new ();
374 g_object_set (G_OBJECT (renderer), "foreground", "red", NULL);
375 column = gtk_tree_view_column_new_with_attributes ("ID",
376 renderer,
377 "text",
378 VG_COLUMN_COUNT, NULL);
379 gtk_tree_view_column_set_sort_column_id (column, VG_COLUMN_COUNT);
380 gtk_tree_view_append_column (treeview, column);
381
382 // VG_COLUMN_VIEW, checkbox:
383 renderer = gtk_cell_renderer_toggle_new ();
384 g_signal_connect (renderer, "toggled", G_CALLBACK (VG_Checkbox_View), model);
385 column =
386 gtk_tree_view_column_new_with_attributes ("View", renderer, "active",
387 VG_COLUMN_VIEW, NULL);
388 gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), // set this column to a fixed sizing (of 50 pixels)
389 GTK_TREE_VIEW_COLUMN_FIXED);
390 gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
391 gtk_tree_view_column_set_clickable (column, TRUE);
392 gtk_tree_view_append_column (treeview, column);
393 g_signal_connect (G_OBJECT (column), "clicked",
394 G_CALLBACK (VG_View_column_clicked), NULL);
395
396 // VG_COLUMN_MUTE, checkbox:
397 renderer = gtk_cell_renderer_toggle_new ();
398 g_signal_connect (renderer, "toggled", G_CALLBACK (VG_Checkbox_Mute), model);
399 column =
400 gtk_tree_view_column_new_with_attributes ("Mute", renderer, "active",
401 VG_COLUMN_MUTE, NULL);
402 gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), // set this column to a fixed sizing (of 50 pixels)
403 GTK_TREE_VIEW_COLUMN_FIXED);
404 gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
405 gtk_tree_view_column_set_clickable (column, TRUE);
406 gtk_tree_view_append_column (treeview, column);
407 g_signal_connect (G_OBJECT (column), "clicked",
408 G_CALLBACK (VG_Mute_column_clicked), NULL);
409
410 // VG_COLUMN_TYPE, string:
411 renderer = gtk_cell_renderer_text_new ();
412 g_object_set (G_OBJECT (renderer), "foreground", "blue", NULL);
413 column = gtk_tree_view_column_new_with_attributes ("Type",
414 renderer,
415 "text",
416 VG_COLUMN_TYPE, NULL);
417 gtk_tree_view_column_set_sort_column_id (column, VG_COLUMN_TYPE);
418 gtk_tree_view_append_column (treeview, column);
419
420 // VG_COLUMN_DESC, string:
421 renderer = gtk_cell_renderer_text_new ();
422 g_object_set (renderer, "editable", TRUE, NULL);
423 g_signal_connect (renderer, "edited",
424 (GCallback) VG_EditDescription_callback, NULL);
425 column =
426 gtk_tree_view_column_new_with_attributes ("Description", renderer, "text",
427 VG_COLUMN_DESC, NULL);
428 gtk_tree_view_column_set_sort_column_id (column, VG_COLUMN_DESC);
429 gtk_tree_view_append_column (treeview, column);
430
431 // VG_COLUMN_COUNTTOTS, int:
432 renderer = gtk_cell_renderer_text_new ();
433 column = gtk_tree_view_column_new_with_attributes ("Total",
434 renderer,
435 "text",
436 VG_COLUMN_COUNTTOTS,
437 NULL);
438 gtk_tree_view_column_set_sort_column_id (column, VG_COLUMN_COUNTTOTS);
439 gtk_tree_view_append_column (treeview, column);
440
441 // VG_COLUMN_COUNTSELS, int:
442 renderer = gtk_cell_renderer_text_new ();
443 column = gtk_tree_view_column_new_with_attributes ("Selected",
444 renderer,
445 "text",
446 VG_COLUMN_COUNTSELS,
447 NULL);
448 gtk_tree_view_column_set_sort_column_id (column, VG_COLUMN_COUNTSELS);
449 gtk_tree_view_append_column (treeview, column);
450 }
451
452 /////////////////////////////////////////////
453 //20100622 - creates the List store and adds my data to it. Called
454 // first, before VG_List_AddColumns
VG_List_CreateModel()455 static GtkTreeModel *VG_List_CreateModel ()
456 {
457 GtkListStore *store;
458 GtkTreeIter iter;
459
460 //"Another way to refer to a row in a list or tree is GtkTreeIter. A tree iter is just a structure that contains a couple of pointers that mean something to the model you are using. Tree iters are used internally by models, and they often contain a direct pointer to the internal data of the row in question. You should never look at the content of a tree iter and you must not modify it directly either."
461
462 // create list store
463 store = gtk_list_store_new (VG_COLUMNCOUNT, // total count of colums
464 G_TYPE_INT, // VG_COLUMN_COUNT
465 G_TYPE_BOOLEAN, // VG_COLUMN_VIEW
466 G_TYPE_BOOLEAN, // VG_COLUMN_MUTE
467 G_TYPE_STRING, // VG_COLUMN_TYPE
468 G_TYPE_STRING, // VG_COLUMN_DESC
469 G_TYPE_INT, // VG_COLUMN_COUNTTOTS
470 G_TYPE_INT // VG_COLUMN_COUNTSELS
471 );
472
473 // add data to the list store
474 int VoiceIndex = 0;
475 int dpcount_all = 0;
476 int dpcount_selected = 0;
477 SG_Voice *curVoice = SG_FirstVoice;
478
479 /* populate the model: */
480 while (curVoice != NULL)
481 {
482 main_sTmp[0] = '\0';
483 main_VoiceInfoFormatter_type (curVoice, main_sTmp);
484 SG_CountVoiceDPs (curVoice, &dpcount_all, &dpcount_selected);
485 gtk_list_store_append (store, &iter);
486 gtk_list_store_set (store, &iter,
487 VG_COLUMN_COUNT, curVoice->ID,
488 VG_COLUMN_VIEW, TRUE == curVoice->hide ? FALSE : TRUE,
489 VG_COLUMN_MUTE, BB_Voice[VoiceIndex].mute,
490 VG_COLUMN_TYPE, main_sTmp,
491 VG_COLUMN_DESC, curVoice->description,
492 VG_COLUMN_COUNTTOTS, dpcount_all,
493 VG_COLUMN_COUNTSELS, dpcount_selected, -1);
494
495 //main loop update
496 ++VoiceIndex;
497 curVoice = curVoice->NextVoice;
498 }
499 ////////////////////////////////
500
501 return GTK_TREE_MODEL (store);
502 }
503
504 /////////////////////////////////////////////////////////
505 //20100624: hopefully fast count of rows
VG_CountRows(GtkTreeView * treeview)506 gint VG_CountRows (GtkTreeView * treeview)
507 {
508 int count = 0;
509 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
510 GtkTreeIter iter;
511 gtk_tree_model_get_iter_first (model, &iter);
512 do
513 {
514 //gtk_tree_model_get (model, &iter, VG_COLUMN_COUNT, &voiceID, -1);
515 //gtk_list_store_set (GTK_LIST_STORE (model), &iter, VG_COLUMN_COUNT, i++, -1);
516 ++count;
517 }
518 while (FALSE != gtk_tree_model_iter_next (model, &iter));
519 return count;
520 }
521
522 /////////////////////////////////////////////////////////
523 //20100624: Makes sure BB/SG have same number of voices as VG
524 //returns TRUE of counts were already sync'd
VG_VerifyCount(GtkTreeView * treeview)525 int VG_VerifyCount (GtkTreeView * treeview)
526 {
527 return (BB_VoiceCount - VG_CountRows (GTK_TREE_VIEW (treeview)));
528 }
529
530 /////////////////////////////////////////////////////////
531 //20100624: Only deletes it if it's full
VG_DestroyTreeView()532 void VG_DestroyTreeView ()
533 {
534 if (NULL != VG_TreeView)
535 {
536 SG_DBGOUT ("Destroying old VG_TreeView");
537 gtk_widget_destroy (VG_TreeView);
538 VG_TreeView = NULL;
539 }
540 }
541
542 /////////////////////////////////////////////
543 //20100624
VG_FillList(GtkTreeView * treeview)544 void VG_FillList (GtkTreeView * treeview)
545 {
546 SG_Voice *curVoice;
547 int voiceID;
548 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
549 GtkTreeIter iter;
550 gtk_tree_model_get_iter_first (model, &iter);
551
552 // add data to the list store
553 int dpcount_all = 0;
554 int dpcount_selected = 0;
555
556 // populate the model:
557 do
558 {
559 //first get the voiceID:
560 gtk_tree_model_get (model, &iter, VG_COLUMN_COUNT, &voiceID, -1);
561 //now match it up to the correct SG_Voice:
562 curVoice = VG_GetVoice (voiceID);
563 if (curVoice != NULL)
564 {
565 main_sTmp[0] = '\0';
566 main_VoiceInfoFormatter_type (curVoice, main_sTmp);
567 SG_CountVoiceDPs (curVoice, &dpcount_all, &dpcount_selected);
568 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
569 VG_COLUMN_COUNT, curVoice->ID,
570 VG_COLUMN_VIEW, TRUE == curVoice->hide ? FALSE : TRUE,
571 VG_COLUMN_MUTE, curVoice->mute,
572 VG_COLUMN_TYPE, main_sTmp,
573 VG_COLUMN_DESC, curVoice->description,
574 VG_COLUMN_COUNTTOTS, dpcount_all,
575 VG_COLUMN_COUNTSELS, dpcount_selected, -1);
576 }
577 else
578 {
579 //bad news if we got here - probably means SG has uncaringly
580 //reordered IDs, gotta rebuild. THAT'S A BUG
581 VG_DestroyTreeView ();
582 return;
583 }
584
585 // gtk_list_store_set (GTK_LIST_STORE (model), &iter, VG_COLUMN_COUNT, i++, -1);
586 }
587 while (FALSE != gtk_tree_model_iter_next (model, &iter));
588 }
589
590 /////////////////////////////////////////////////////////
591 //20100622: the big one.
592 //Purpose:
593 // - (once for init only) create a scrollable window to put inside GtkVBox user gives me
594 // - (once for init and then time a voice is added or subtracted) create a list to store SG/BB data
595 // - (every call) Be sure BB_VoiceCount and number of rows is identical (adding or subtracting as needed)
596 // - refill list with things that can change (more complicated than it seems, as list order is arbitrary)
main_UpdateGUI_Voices(GtkVBox * mainbox)597 void main_UpdateGUI_Voices (GtkVBox * mainbox)
598 {
599 static GtkWidget *sw = NULL; //create so I can delete something inside box user passed me
600 static int CellHeight = 24; //arbitrary, gets set for-real later
601 //############
602 //First do the stuff that only happens once:
603 //Create the scrollwindow to put in user's box if it doesn't exist yet:
604 if (NULL == sw)
605 {
606 // gtk_widget_destroy (sw);
607 //Make a scrollable window to put in user's thang:
608 sw = gtk_scrolled_window_new (NULL, NULL);
609 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
610 GTK_SHADOW_ETCHED_IN);
611 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
612 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
613 gtk_box_pack_start (GTK_BOX (mainbox), sw, TRUE, TRUE, 0);
614 }
615
616 //Create the list if it doesn't exist yet:
617 if (TRUE == VG_RelistFlag || NULL == VG_TreeView || 0 != VG_VerifyCount (GTK_TREE_VIEW (VG_TreeView))) //this part is a hack because i am finding weirdness in Voice IDs
618 {
619 VG_RelistFlag = FALSE;
620 SG_DBGOUT ("Creating new VG_TreeView");
621 // create tree model by loading my data
622 GtkTreeModel *treemodel = VG_List_CreateModel ();
623
624 VG_DestroyTreeView (); //only does it if != NULL
625
626 // create tree view
627 VG_TreeView = gtk_tree_view_new_with_model (treemodel);
628 //gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (treeview), TRUE) ;
629 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (VG_TreeView), TRUE);
630 gtk_tree_view_set_search_column (GTK_TREE_VIEW (VG_TreeView),
631 VG_COLUMN_DESC);
632 GtkTreeSelection *selection =
633 gtk_tree_view_get_selection (GTK_TREE_VIEW (VG_TreeView));
634 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
635
636 //start 20110519
637 int i = 0;
638 SG_Voice *selVoice = SG_SelectVoice (NULL);
639 if (NULL != selVoice)
640 {
641 i = VG_GetVoiceIndex (selVoice);
642 if (-1 == i)
643 i = 0;
644 }
645 VG_List_SetSelectedVoice (treemodel, selection, i); //20100624: need to rework
646 //end 20110519
647
648 //two different approaches to doing this, using the more dedicated one:
649 // g_signal_connect(selection, "changed", G_CALLBACK(VG_onSelectionChange), NULL);
650 gtk_tree_selection_set_select_function (selection, VG_onSelectionChange,
651 NULL, NULL);
652
653 //to determine when right mouse button is pressed:
654 g_signal_connect (VG_TreeView, "button-press-event",
655 (GCallback) VG_onRightButton, NULL);
656
657 g_object_unref (treemodel); //20100624: WHAT? Apparently OK, i use gtk_tree_view_get_model
658
659 gtk_container_add (GTK_CONTAINER (sw), VG_TreeView);
660
661 // add columns to the tree view
662 VG_List_AddColumns (GTK_TREE_VIEW (VG_TreeView));
663
664 //get height here so i don't have to do it over and over:
665 gtk_tree_view_column_cell_get_size (gtk_tree_view_get_column
666 (GTK_TREE_VIEW (VG_TreeView), 0), NULL,
667 NULL, NULL, NULL, &CellHeight);
668 //SG_DBGOUT_INT ("row height:", CellHeight);
669 CellHeight += 2;
670 gtk_widget_show_all (sw);
671 }
672 //End of stuff only done once
673 //############
674
675 // 20100623: try to keep a sensible amount of list showing:
676 if (6 > VG_GetVoiceCount ())
677 {
678 gtk_widget_set_usize (sw, 600, CellHeight * (1 + VG_GetVoiceCount ()));
679 }
680 else
681 {
682 gtk_widget_set_usize (sw, 600, CellHeight * 6);
683 }
684
685 VG_FillList (GTK_TREE_VIEW (VG_TreeView));
686 }
687