1 /* vim: set fdm=marker: */
2 /** \file uisettings.c
3 * \brief GTK3 main settings dialog
4 *
5 * \author Bas Wassink <b.wassink@ziggo.nl>
6 */
7
8 /*
9 * $VICERES SaveResourcesOnExit all
10 * $VICERES ConfirmOnExit all
11 * $VICERES PauseOnSettings all
12 */
13
14 /*
15 * This file is part of VICE, the Versatile Commodore Emulator.
16 * See README for copyright notice.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31 * 02111-1307 USA.
32 */
33
34
35 /* The settings_grid is supposed to become this:
36 *
37 * +--------------+---------------------------+
38 * | treeview | |
39 * | with | |
40 * | settings | central widget, |
41 * | more | depending on which |
42 * | foo | item is selected in |
43 * | bar | the treeview |
44 * | whatever | |
45 * | burp | |
46 * +--------------+---------------------------+
47 *
48 * And this is handled by the dialog itself:
49 * +------------------------------------------+
50 * | load | save | load... | save... | close |
51 * +------------------------------------------+
52 */
53
54
55 #include "vice.h"
56
57 #include <gtk/gtk.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61
62 #include "archdep.h"
63 #include "lib.h"
64 #include "log.h"
65 #include "util.h"
66 #include "machine.h"
67 #include "resources.h"
68 #include "vsync.h"
69
70 #include "vice_gtk3.h"
71
72 #include "ui.h"
73 #include "settings_speed.h"
74 #include "settings_keyboard.h"
75 #include "settings_sound.h"
76 #include "settings_autostart.h"
77 #include "settings_drive.h"
78 #include "settings_fsdevice.h"
79 #include "settings_model.h"
80 #include "settings_misc.h"
81 #include "settings_ramreset.h"
82 #include "settings_video.h"
83 #include "settings_sampler.h"
84 #include "settings_printer.h"
85 #include "settings_controlport.h"
86 #include "settings_joystick.h"
87 #include "settings_soundchip.h"
88 #include "settings_monitor.h"
89 #include "settings_romset.h"
90 #include "settings_snapshot.h"
91 #ifdef HAVE_RAWNET
92 # include "settings_ethernet.h"
93 #endif
94 #include "settings_rs232.h"
95 #include "scpu64settingswidget.h"
96 #include "c64dtvflashsettingswidget.h"
97
98 /* I/O extension widgets */
99 #include "settings_io.h"
100 #include "c64memhackswidget.h"
101 #include "georamwidget.h"
102 #include "reuwidget.h"
103 #include "ramcartwidget.h"
104 #include "dqbbwidget.h"
105 #include "expertwidget.h"
106 #include "isepicwidget.h"
107 #include "easyflashwidget.h"
108 #include "gmod2widget.h"
109 #include "gmod3widget.h"
110 #include "mmcrwidget.h"
111 #include "mmc64widget.h"
112 #include "ide64widget.h"
113 #include "retroreplaywidget.h"
114 #include "ltkernalwidget.h"
115 #include "ramlinkwidget.h"
116 #include "netplaywidget.h"
117
118 #ifdef HAVE_RAWNET
119 # include "ethernetcartwidget.h"
120 # include "rrnetmk3widget.h"
121 #endif
122
123 #include "c128functionromwidget.h"
124 #include "ieee488widget.h"
125 #include "digimaxwidget.h"
126 #include "magicvoicewidget.h"
127 #ifdef HAVE_MIDI
128 # include "midiwidget.h"
129 #endif
130 #include "sfxsoundexpanderwidget.h"
131 #include "ds12c887widget.h"
132 #include "userportdeviceswidget.h"
133 #include "tapeportdeviceswidget.h"
134 #include "sidcartwidget.h"
135 #include "sfxsoundsamplerwidget.h"
136 #include "megacartwidget.h"
137 #include "petreuwidget.h"
138 #include "petcolourgraphicswidget.h"
139 #include "petdwwwidget.h"
140 #include "supersnapshotwidget.h"
141 #include "cpmwidget.h"
142 #include "burstmodewidget.h"
143 #include "c128fullbankswidget.h"
144 #include "plus4digiblasterwidget.h"
145 #include "finalexpansionwidget.h"
146 #include "vicflashwidget.h"
147 #include "ultimemwidget.h"
148 #include "vicieee488widget.h"
149 #include "vicioramwidget.h"
150 #include "vfliwidget.h"
151 #include "petdiagpinwidget.h"
152 #include "pethrewidget.h"
153 #include "settings_crt.h"
154 #include "uimachinewindow.h"
155
156 /* TODO: move up and sort headers */
157 #include "settings_peripherals_generic.h"
158 #include "settings_host_display.h"
159
160 /* VSID stuff */
161 #include "hvscsettingswidget.h"
162
163 /* CWD widget: moved from machine->host to host
164 *
165 * XXX: Probably at some point create settings_paths.{c,h} and have that use
166 * the CWD widget.
167 */
168 #include "cwdwidget.h"
169
170 /* JAM action widget
171 */
172 #include "jamactionwidget.h"
173
174
175 #include "uisettings.h"
176
177
178 /** \brief CSS to allow collapsing/expanding tree nodes with crsr keys
179 *
180 * Note the 'treeview' rule, before Gtk+ 3.20 this was 'GtkTreeView'
181 */
182 #define TREEVIEW_CSS \
183 "@binding-set SettingsTreeViewBinding\n" \
184 "{\n" \
185 " bind \"Left\" { \"select-cursor-parent\" ()\n" \
186 " \"expand-collapse-cursor-row\" (0,0,0) };\n" \
187 " bind \"Right\" { \"expand-collapse-cursor-row\" (0,1,0) };\n" \
188 "}\n" \
189 "\n" \
190 "treeview\n" \
191 "{\n" \
192 " -gtk-key-bindings: SettingsTreeViewBinding;\n" \
193 "}"
194
195
196 /** \brief Number of columns in the tree model
197 */
198 #define NUM_COLUMNS 3
199
200
201 /** \brief Column indici for the tree model
202 */
203 enum {
204 COLUMN_NAME = 0, /**< name */
205 COLUMN_ID, /**< id */
206 COLUMN_CALLBACK /**< callback function */
207 };
208
209
210 /** \brief Initial dialog width
211 *
212 * This is not how wide the dialog will actually become, that is determined by
213 * the Gtk theme applied. But it's a rough estimate.
214 */
215 #define DIALOG_WIDTH 800
216
217
218 /** \brief Initial dialog height
219 *
220 * This is not how tall the dialog will actually become, that is determined by
221 * the Gtk theme applied. But it's a rough estimate.
222 */
223 #define DIALOG_HEIGHT 560
224
225
226 /** \brief Maximum width the UI can be
227 *
228 * This again is not a really a fixed value, but more of an indicator when the
229 * UI might get too large after any decorations are applied. The idea is to
230 * have a UI that works on a 1280x768 resolution without requiring scrollbars.
231 */
232 #define DIALOG_WIDTH_MAX 1024
233
234
235 /** \brief Maximum height the UI can be
236 *
237 * This again is not a really a fixed value, but more of an indicator when the
238 * UI might get too large after any decorations are applied. The idea is to
239 * have a UI that works on a 1280x768 resolution without requiring scrollbars.
240 */
241 #define DIALOG_HEIGHT_MAX 640
242
243
244 /** \brief Enum used for the "response" callback of the settings dialog
245 *
246 * All values must be positive since Gtk reserves standard responses in its
247 * GtkResponse enum as negative values.
248 */
249 enum {
250 RESPONSE_RESET = 1, /**< reset current central widget */
251 RESPONSE_FACTORY, /**< set current central widget's resources to their
252 factory settings */
253 RESPONSE_DEFAULT /**< Restore default settings */
254 };
255
256
257 /*
258 * I/O extensions per emulator
259 */
260
261 /* {{{ c64_cartridges */
262 /** \brief List of C64 cartidge settings (x64, x64sc)
263 */
264 static ui_settings_tree_node_t c64_cartridges[] = {
265
266 { "GEO-RAM",
267 "geo-ram",
268 georam_widget_create, NULL },
269 { "RAM Expansion Module",
270 "reu",
271 reu_widget_create, NULL },
272 { "RamCart",
273 "ramcart",
274 ramcart_widget_create, NULL },
275 { "Double Quick Brown Box",
276 "dqbb",
277 dqbb_widget_create, NULL },
278 { "Expert Cartridge",
279 "expert-cart",
280 expert_widget_create, NULL },
281 { "ISEPIC",
282 "isepic",
283 isepic_widget_create, NULL },
284 { "EasyFlash",
285 "easyflash",
286 easyflash_widget_create, NULL },
287 { "GMod2",
288 "gmod2",
289 gmod2_widget_create, NULL },
290 { "GMod3",
291 "gmod3",
292 gmod3_widget_create, NULL },
293 { "IDE64",
294 "ide64",
295 ide64_widget_create, NULL },
296 { "Lt. Kernal Host Adapter",
297 "ltkernal",
298 ltkernal_widget_create, NULL },
299 { "RAMLink",
300 "ramlink",
301 ramlink_widget_create, NULL },
302 { "MMC64",
303 "mmc64",
304 mmc64_widget_create, NULL },
305 { "MMC Replay",
306 "mmcr",
307 mmcr_widget_create, NULL },
308 { "Retro Replay",
309 "retroreplay",
310 retroreplay_widget_create, NULL },
311 { "Super Snapshot V5",
312 "super-snapshot",
313 super_snapshot_widget_create, NULL },
314 #ifdef HAVE_RAWNET
315 { "Ethernet Cartridge",
316 "ethernet-cart",
317 ethernet_cart_widget_create, NULL },
318 { "RR-Net Mk3",
319 "rrnetmk3",
320 rrnetmk3_widget_create, NULL },
321 #endif
322 { "IEEE-448 Interface",
323 "ieee-488",
324 ieee488_widget_create, NULL },
325 { "DigiMAX",
326 "digimax",
327 digimax_widget_create, NULL },
328 { "Magic Voice",
329 "magic-voice",
330 magic_voice_widget_create, NULL },
331 #ifdef HAVE_MIDI
332 { "MIDI emulation",
333 "midi",
334 midi_widget_create, NULL },
335 #endif
336 { "SFX Sound Expander",
337 "sfx-expander",
338 sfx_sound_expander_widget_create, NULL },
339 { "SFX Sound Sampler",
340 "sfx-sampler",
341 sfx_sound_sampler_widget_create, NULL },
342 { "CP/M Cartridge",
343 "cpm-cart",
344 cpm_widget_create, NULL },
345 { "DS12C887 Real Time Clock",
346 "ds12c887-rtc",
347 ds12c887_widget_create, NULL },
348 UI_SETTINGS_TERMINATOR
349 };
350 /* }}} */
351
352 /* {{{ scpu64_cartridges */
353 /** \brief List of SuperCPU64 extensions (xscpu64)
354 */
355 static ui_settings_tree_node_t scpu64_cartridges[] = {
356 { "GEO-RAM",
357 "geo-ram",
358 georam_widget_create, NULL },
359 { "RAM Expansion Module",
360 "reu",
361 reu_widget_create, NULL },
362 { "RamCart",
363 "ramcart",
364 ramcart_widget_create, NULL },
365 { "Double Quick Brown Box",
366 "dqbb",
367 dqbb_widget_create, NULL },
368 { "Expert Cartridge",
369 "expert-cart",
370 expert_widget_create, NULL },
371 { "ISEPIC",
372 "isepic",
373 isepic_widget_create, NULL },
374 { "EasyFlash",
375 "easyflash",
376 easyflash_widget_create, NULL },
377 { "GMod2",
378 "gmod2",
379 gmod2_widget_create, NULL },
380 { "GMod3",
381 "gmod3",
382 gmod3_widget_create, NULL },
383 { "IDE64",
384 "ide64",
385 ide64_widget_create, NULL },
386 { "MMC64",
387 "mmc64",
388 mmc64_widget_create, NULL },
389 { "MMC Replay",
390 "mmcr",
391 mmcr_widget_create, NULL },
392 { "RAMLink",
393 "ramlink",
394 ramlink_widget_create, NULL },
395 { "Retro Replay",
396 "retroreplay",
397 retroreplay_widget_create, NULL },
398 { "Super Snapshot V5",
399 "super-snapshot",
400 super_snapshot_widget_create, NULL },
401 #ifdef HAVE_RAWNET
402 { "Ethernet Cartridge",
403 "ethernet-cart",
404 ethernet_cart_widget_create, NULL },
405 { "RR-Net Mk3",
406 "rrnetmk3",
407 rrnetmk3_widget_create, NULL },
408 #endif
409 { "IEEE-448 Interface",
410 "ieee-488",
411 ieee488_widget_create, NULL },
412 { "DigiMAX",
413 "digimax",
414 digimax_widget_create, NULL },
415 { "Magic Voice",
416 "magic-voice",
417 magic_voice_widget_create, NULL },
418 #ifdef HAVE_MIDI
419 { "MIDI emulation",
420 "midi",
421 midi_widget_create, NULL },
422 #endif
423 { "SFX Sound Expander",
424 "sfx-expander",
425 sfx_sound_expander_widget_create, NULL },
426 { "SFX Sound Sampler",
427 "sfx-sampler",
428 sfx_sound_sampler_widget_create, NULL },
429 { "DS12C887 Real Time Clock",
430 "ds12c887-rtc",
431 ds12c887_widget_create, NULL },
432
433 UI_SETTINGS_TERMINATOR
434 };
435 /* }}} */
436
437 /* {{{ c128_cartridges */
438 /** \brief I/O extensions for C128
439 */
440 static ui_settings_tree_node_t c128_cartridges[] = {
441 { "GEO-RAM",
442 "geo-ram",
443 georam_widget_create, NULL },
444 { "RAM Expansion Module",
445 "reu",
446 reu_widget_create, NULL },
447 { "RamCart",
448 "ramcart",
449 ramcart_widget_create, NULL },
450 { "Double Quick Brown Box",
451 "dqbb",
452 dqbb_widget_create, NULL },
453 { "Expert Cartridge",
454 "expert-cart",
455 expert_widget_create, NULL },
456 { "ISEPIC",
457 "isepic",
458 isepic_widget_create, NULL },
459 { "EasyFlash",
460 "easyflash",
461 easyflash_widget_create, NULL },
462 { "GMod2",
463 "gmod2",
464 gmod2_widget_create, NULL },
465 { "GMod3",
466 "gmod3",
467 gmod3_widget_create, NULL },
468 { "IDE64",
469 "ide64",
470 ide64_widget_create, NULL },
471 { "Lt. Kernal Host Adapter",
472 "ltkernal",
473 ltkernal_widget_create, NULL },
474 { "RAMLink",
475 "ramlink",
476 ramlink_widget_create, NULL },
477 { "MMC64",
478 "mmc64",
479 mmc64_widget_create, NULL },
480 { "MMC Replay",
481 "mmcr",
482 mmcr_widget_create, NULL },
483 { "Retro Replay",
484 "retroreplay",
485 retroreplay_widget_create, NULL },
486 { "Super Snapshot V5",
487 "super-snapshot",
488 super_snapshot_widget_create, NULL },
489 #ifdef HAVE_RAWNET
490 { "Ethernet Cartridge",
491 "ethernet-cart",
492 ethernet_cart_widget_create, NULL },
493 { "RR-Net Mk3",
494 "rrnetmk3",
495 rrnetmk3_widget_create, NULL },
496 #endif
497 { "IEEE-448 Interface",
498 "ieee-488",
499 ieee488_widget_create, NULL },
500 { "DigiMAX",
501 "digimax",
502 digimax_widget_create, NULL },
503 { "Magic Voice",
504 "magic-voice",
505 magic_voice_widget_create, NULL },
506 #ifdef HAVE_MIDI
507 { "MIDI emulation",
508 "midi",
509 midi_widget_create, NULL },
510 #endif
511 { "SFX Sound Expander",
512 "sfx-expander",
513 sfx_sound_expander_widget_create, NULL },
514 { "SFX Sound Sampler",
515 "sfx-sampler",
516 sfx_sound_sampler_widget_create, NULL },
517 { "CP/M Cartridge",
518 "cpm-cart",
519 cpm_widget_create, NULL },
520 { "DS12C887 Real Time Clock",
521 "ds12c887-rtc",
522 ds12c887_widget_create, NULL },
523
524 UI_SETTINGS_TERMINATOR
525 };
526 /* }}} */
527
528 /* {{{ vic20_cartridges */
529 /** \brief List of VIC-20 I/O extensions
530 */
531 static ui_settings_tree_node_t vic20_cartridges[] = {
532 { "Mega Cart",
533 "mega-cart",
534 mega_cart_widget_create, NULL },
535 { "Final Expansion",
536 "final-expansion",
537 final_expansion_widget_create, NULL },
538 { "Vic Flash Plugin",
539 "vic-flash-plugin",
540 vic_flash_widget_create, NULL },
541 { "UltiMem",
542 "ultimem",
543 ultimem_widget_create, NULL },
544 { "VIC-1112 IEEE-488 interface",
545 "ieee-488",
546 vic_ieee488_widget_create, NULL },
547 { "DigiMAX (MasC=uerade",
548 "digimax",
549 digimax_widget_create, NULL },
550 { "DS12C887 RTC (MasC=uerade)",
551 "ds12c887-rtc",
552 ds12c887_widget_create, NULL },
553 { "GEO-RAM (MasC=uerade)",
554 "geo-ram",
555 georam_widget_create, NULL },
556 { "SFX Sound Expander (MasC=uerade)",
557 "sfx-expander",
558 sfx_sound_expander_widget_create, NULL },
559 { "SFX Sound Sampler (MasC=uerade)",
560 "sfx-sampler",
561 sfx_sound_sampler_widget_create, NULL },
562 #ifdef HAVE_RAWNET
563 { "Ethernet Cartridge (MasC=uerade)",
564 "ethernet-cart",
565 ethernet_cart_widget_create, NULL },
566 #endif
567 #ifdef HAVE_MIDI
568 { "MIDI emulation",
569 "midi",
570 midi_widget_create, NULL },
571 #endif
572
573 UI_SETTINGS_TERMINATOR
574 };
575 /* }}} */
576
577 /* {{{ plus4_io_extensions */
578 /** \brief List of Plus4 I/O extensions
579 */
580 static ui_settings_tree_node_t plus4_io_extensions[] = {
581 { "Digiblaster add-on",
582 "digiblaster",
583 plus4_digiblaster_widget_create, NULL },
584 { "SID Card",
585 "sid-card",
586 sidcart_widget_create, NULL },
587
588 UI_SETTINGS_TERMINATOR
589 };
590 /* }}} */
591
592 /* {{{ pet_io_extensions */
593 /** \brief List of PET I/O extensions
594 */
595 static ui_settings_tree_node_t pet_io_extensions[] = {
596 { "PET RAM Expansion Unit",
597 "pet-reu",
598 pet_reu_widget_create, NULL },
599 { "PET Colour graphics",
600 "pet-colour",
601 pet_colour_graphics_widget_create, NULL },
602 { "PET DWW hi-res graphics",
603 "pet-dww",
604 pet_dww_widget_create, NULL },
605 { "PET HRE hi-res graphics",
606 "pet-hre",
607 pet_hre_widget_create, NULL },
608 { "SID Card",
609 "sid-card",
610 sidcart_widget_create, NULL },
611 UI_SETTINGS_TERMINATOR
612 };
613 /* }}} */
614
615 /* {{{ cbm5x0_io_extensions */
616 /** \brief List of CBM 5x0 I/O extensions
617 */
618 #if 0
619 static ui_settings_tree_node_t cbm5x0_io_extensions[] = {
620 UI_SETTINGS_TERMINATOR
621 };
622 #endif
623 /* }}} */
624
625 /* {{{ cbm6x0_io_extensions */
626 /** \brief List of CBM 6x0 I/O extensions
627 */
628 #if 0
629 static ui_settings_tree_node_t cbm6x0_io_extensions[] = {
630 UI_SETTINGS_TERMINATOR
631 };
632 #endif
633 /* }}} */
634
635 /*
636 * Main tree nodes per emulator
637 */
638
639 /*****************************************************************************
640 * VSID tree nodes for the settings UI *
641 ****************************************************************************/
642
643 /* {{{ main_nodes_vsid */
644 /** \brief Main tree nodes for VSID
645 */
646 static ui_settings_tree_node_t main_nodes_vsid[] = {
647 { "Sound",
648 "sound",
649 settings_sound_create, NULL },
650 { "SID",
651 "sid",
652 settings_soundchip_widget_create, NULL },
653 { "Speed",
654 "speed",
655 settings_speed_widget_create, NULL },
656 /* XXX: basically a selection between 'PAL'/'NTSC' (50/60Hz) */
657 { "Model",
658 "model",
659 settings_model_widget_create, NULL },
660 #if 0
661 /* XXX: do we need this? Sidplay allows ROM selection for Basic, Kernal and
662 * Chargen, perhaps move into model settings, plenty of space there */
663 { "ROM",
664 "rom-settings",
665 settings_romset_widget_create, NULL },
666 #endif
667 #if 0
668 /* XXX: perhaps required for VSID-specific things */
669 { "Emulator",
670 "misc",
671 settings_misc_widget_create, NULL },
672 #endif
673 { "Monitor",
674 "monitor",
675 settings_monitor_widget_create, NULL },
676 { "HVSC",
677 "hvsc",
678 hvsc_settings_widget_create, NULL },
679
680 UI_SETTINGS_TERMINATOR
681 };
682 /* }}} */
683
684
685
686 /* {{{ host_nodes_generic */
687 /** \brief Child nodes for the 'Host' node for all machines
688 */
689 static ui_settings_tree_node_t host_nodes_generic[] = {
690 { "Autostart",
691 "autostart",
692 settings_autostart_widget_create, NULL },
693 { "Monitor",
694 "monitor",
695 settings_monitor_widget_create, NULL },
696 { "Netplay",
697 "netplay",
698 netplay_widget_create, NULL },
699 { "Snapshot/event/media recording",
700 "snapshot",
701 settings_snapshot_widget_create, NULL },
702 { "Current directory",
703 "cwd",
704 cwd_widget_create, NULL },
705 { "CPU JAM action",
706 "jam-action",
707 jam_action_widget_create, NULL },
708 UI_SETTINGS_TERMINATOR
709 };
710 /* }}} */
711
712
713 /*****************************************************************************
714 * C64 tree nodes for the settings UI *
715 ****************************************************************************/
716
717 #if 0
718 /* {{{ host_nodes_c64 */
719 /** \brief Child nodes for the C64 'Host' node
720 */
721 static ui_settings_tree_node_t host_nodes_c64[] = {
722 { "Autostart",
723 "autostart",
724 settings_autostart_widget_create, NULL },
725 { "Monitor",
726 "monitor",
727 settings_monitor_widget_create, NULL },
728 { "Netplay",
729 "netplay",
730 netplay_widget_create, NULL },
731 { "Snapshot/event/media recording",
732 "snapshot",
733 settings_snapshot_widget_create, NULL },
734 { "Current directory",
735 "cwd",
736 cwd_widget_create, NULL },
737 UI_SETTINGS_TERMINATOR
738 };
739 /* }}} */
740 #endif
741
742 /* {{{ machine_nodes_c64 */
743 /** \brief Child nodes for the C64 'Machine' node
744 */
745 static ui_settings_tree_node_t machine_nodes_c64[] = {
746 { "Model",
747 "model",
748 settings_model_widget_create, NULL },
749 { "ROM",
750 "rom-settings",
751 settings_romset_widget_create, NULL },
752 { "RAM",
753 "ram-reset",
754 settings_ramreset_widget_create, NULL },
755 { "Memory Expansion Hacks",
756 "mem-hacks",
757 c64_memhacks_widget_create, NULL },
758 { "I/O settings",
759 "io-settings",
760 settings_io_widget_create, NULL },
761 { "Burst Mode Modification",
762 "burstmode-mode",
763 burst_mode_widget_create, NULL },
764 UI_SETTINGS_TERMINATOR
765 };
766 /* }}} */
767
768 /* {{{ display_nodes_c64 */
769 /** \brief Child nodes for the C64 'Display' node
770 */
771 static ui_settings_tree_node_t display_nodes_c64[] = {
772 { "Host display",
773 "host-display",
774 settings_host_display_widget_create, NULL },
775 { "VIC-II",
776 "vicii",
777 settings_video_create, NULL },
778 { "CRT",
779 "crt",
780 settings_crt_widget_create, NULL },
781 UI_SETTINGS_TERMINATOR
782 };
783 /* }}} */
784
785 /* {{{ audio_nodes_c64 */
786 /** \brief Child nodes for the C64 'Audio' node
787 */
788 static ui_settings_tree_node_t audio_nodes_c64[] = {
789 { "Sound",
790 "sound",
791 settings_sound_create, NULL },
792 { "SID",
793 "sid",
794 settings_soundchip_widget_create, NULL },
795 { "Sampler",
796 "sampler",
797 settings_sampler_widget_create, NULL },
798 UI_SETTINGS_TERMINATOR
799 };
800 /* }}} */
801
802 /* {{{ input_nodes_c64 */
803 /** \brief Child nodes for the C64 'Input devices' node
804 */
805 static ui_settings_tree_node_t input_nodes_c64[] = {
806 { "Keyboard",
807 "keyboard",
808 settings_keyboard_widget_create, NULL },
809 { "Joystick",
810 "joystick",
811 settings_joystick_widget_create, NULL },
812 { "Control port",
813 "control-port",
814 settings_controlport_widget_create, NULL },
815 UI_SETTINGS_TERMINATOR
816 };
817 /* }}} */
818
819 /* {{{ peripheral_nodes_c64 */
820 /** \brief Child nodes for the C64 'Peripheral devices' node
821 */
822 static ui_settings_tree_node_t peripheral_nodes_c64[] = {
823 { "Generic",
824 "generic",
825 settings_peripherals_generic_widget_create, NULL },
826 /* "Output devices? drive is also input */
827 { "Drive",
828 "drive",
829 settings_drive_widget_create, NULL },
830 { "Filesystem Device",
831 "fsdevice",
832 settings_fsdevice_widget_create, NULL },
833 { "Printer",
834 "printer",
835 settings_printer_widget_create, NULL },
836 #ifdef HAVE_RS232DEV
837 { "RS232",
838 "rs232",
839 settings_rs232_widget_create, NULL },
840 #endif
841 { "Userport devices",
842 "userport-devices",
843 userport_devices_widget_create, NULL },
844 { "Tape port devices",
845 "tapeport-devices",
846 tapeport_devices_widget_create, NULL },
847 #ifdef HAVE_RAWNET
848 { "Ethernet",
849 "ethernet",
850 settings_ethernet_widget_create, NULL },
851 #endif
852 UI_SETTINGS_TERMINATOR
853 };
854 /* }}} */
855
856 /* {{{ main_nodes_c64 */
857 /** \brief Main tree nodes for x64/x64sc
858 */
859 static ui_settings_tree_node_t main_nodes_c64[] = {
860 { "Host",
861 "host",
862 NULL, host_nodes_generic },
863 { "Machine",
864 "machine",
865 NULL, machine_nodes_c64 },
866 { "Display",
867 "display",
868 NULL, display_nodes_c64 },
869 { "Audio",
870 "audio",
871 NULL, audio_nodes_c64 },
872 { "Input devices",
873 "input",
874 NULL, input_nodes_c64 },
875 { "Peripheral devices",
876 "peripheral", /* I'll misspell this many times */
877 NULL, peripheral_nodes_c64 },
878 { "Cartridges",
879 "cartridges",
880 NULL, c64_cartridges },
881 UI_SETTINGS_TERMINATOR
882 };
883 /* }}} */
884
885
886 /*****************************************************************************
887 * C64DTV tree nodes for the settings UI *
888 ****************************************************************************/
889
890 #if 0
891 /* {{{ host_nodes_c64dtv */
892 /** \brief Child nodes for the C64DTV 'Host' node
893 */
894 static ui_settings_tree_node_t host_nodes_c64dtv[] = {
895 { "Autostart",
896 "autostart",
897 settings_autostart_widget_create, NULL },
898 { "Monitor",
899 "monitor",
900 settings_monitor_widget_create, NULL },
901 { "Netplay",
902 "netplay",
903 netplay_widget_create, NULL },
904 { "Snapshot/event/media recording",
905 "snapshot",
906 settings_snapshot_widget_create, NULL },
907 UI_SETTINGS_TERMINATOR
908 };
909 /* }}} */
910 #endif
911
912 /* {{{ machine_nodes_c64dtv */
913 /** \brief Child nodes for the C64DTV 'Machine' node
914 */
915 static ui_settings_tree_node_t machine_nodes_c64dtv[] = {
916 { "Model",
917 "model",
918 settings_model_widget_create, NULL },
919 { "ROM",
920 "rom-settings",
921 settings_romset_widget_create, NULL },
922 { "RAM",
923 "ram-reset",
924 settings_ramreset_widget_create, NULL },
925 { "Flash",
926 "flash",
927 c64dtv_flash_settings_widget_create, NULL },
928 #if 0
929 { "I/O settings",
930 "io-settings",
931 settings_io_widget_create, NULL },
932 #endif
933
934 UI_SETTINGS_TERMINATOR
935 };
936 /* }}} */
937
938 /* {{{ display_nodes_c64dtv */
939 /** \brief Child nodes for the C64DTV 'Display' node
940 */
941 static ui_settings_tree_node_t display_nodes_c64dtv[] = {
942 { "Host display",
943 "host-display",
944 settings_host_display_widget_create, NULL },
945 { "VIC-II",
946 "vicii",
947 settings_video_create, NULL },
948 { "CRT",
949 "CRT",
950 settings_crt_widget_create, NULL },
951 UI_SETTINGS_TERMINATOR
952 };
953 /* }}} */
954
955 /* {{{ audio_nodes_c64dtv */
956 /** \brief Child nodes for the C64DTV 'Audio' node
957 */
958 static ui_settings_tree_node_t audio_nodes_c64dtv[] = {
959 { "Sound",
960 "sound",
961 settings_sound_create, NULL },
962 { "SID",
963 "sid",
964 settings_soundchip_widget_create, NULL },
965 { "Sampler",
966 "sampler",
967 settings_sampler_widget_create, NULL },
968 UI_SETTINGS_TERMINATOR
969 };
970 /* }}} */
971
972 /* {{{ input_nodes_c64dtv */
973 /** \brief Child nodes for the C64DTV 'Input devices' node
974 */
975 static ui_settings_tree_node_t input_nodes_c64dtv[] = {
976 { "Keyboard",
977 "keyboard",
978 settings_keyboard_widget_create, NULL },
979 { "Joystick",
980 "joystick",
981 settings_joystick_widget_create, NULL },
982 { "Control port",
983 "control-port",
984 settings_controlport_widget_create, NULL },
985 UI_SETTINGS_TERMINATOR
986 };
987 /* }}} */
988
989 /* {{{ peripheral_nodes_c64dtv */
990 /** \brief Child nodes for the C64DTV 'Peripheral devices' node
991 */
992 static ui_settings_tree_node_t peripheral_nodes_c64dtv[] = {
993 { "Generic",
994 "generic",
995 settings_peripherals_generic_widget_create, NULL },
996 { "Drive",
997 "drive",
998 settings_drive_widget_create, NULL },
999 { "Filesystem Device",
1000 "fsdevice",
1001 settings_fsdevice_widget_create, NULL },
1002 { "Printer",
1003 "printer",
1004 settings_printer_widget_create, NULL },
1005 UI_SETTINGS_TERMINATOR
1006 };
1007 /* }}} */
1008
1009 /* {{{ main_nodes_c64dtv */
1010 /** \brief Main tree nodes for x64dtv
1011 */
1012 static ui_settings_tree_node_t main_nodes_c64dtv[] = {
1013 { "Host", "host", NULL, host_nodes_generic },
1014 { "Machine", "machine", NULL, machine_nodes_c64dtv },
1015 { "Display", "display", NULL, display_nodes_c64dtv },
1016 { "Audio", "audio", NULL, audio_nodes_c64dtv },
1017 { "Input devices", "input", NULL, input_nodes_c64dtv },
1018 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_c64dtv },
1019 #if 0
1020 { "Emulator",
1021 "misc",
1022 settings_misc_widget_create, NULL },
1023 #endif
1024
1025
1026 UI_SETTINGS_TERMINATOR
1027 };
1028 /* }}} */
1029
1030
1031 /*****************************************************************************
1032 * C128 tree nodes for the settings UI *
1033 ****************************************************************************/
1034
1035 #if 0
1036 /* {{{ host_nodes_c128 */
1037 /** \brief Child nodes for the C128 'Host' node
1038 */
1039 static ui_settings_tree_node_t host_nodes_c128[] = {
1040 { "Autostart",
1041 "autostart",
1042 settings_autostart_widget_create, NULL },
1043 { "Monitor",
1044 "monitor",
1045 settings_monitor_widget_create, NULL },
1046 { "Netplay",
1047 "netplay",
1048 netplay_widget_create, NULL },
1049 { "Snapshot/event/media recording",
1050 "snapshot",
1051 settings_snapshot_widget_create, NULL },
1052
1053 UI_SETTINGS_TERMINATOR
1054 };
1055 /* }}} */
1056 #endif
1057
1058 /* {{{ machine_nodes_c128 */
1059 /** \brief Child nodes for the C128 'Machine' node
1060 */
1061 static ui_settings_tree_node_t machine_nodes_c128[] = {
1062 { "Model",
1063 "model",
1064 settings_model_widget_create, NULL },
1065 { "ROM",
1066 "rom-settings",
1067 settings_romset_widget_create, NULL },
1068 { "RAM",
1069 "ram-reset",
1070 settings_ramreset_widget_create, NULL },
1071 { "Function ROM",
1072 "function-rom",
1073 c128_function_rom_widget_create, NULL },
1074 { "Banks 2 & 3",
1075 "banks-23",
1076 c128_full_banks_widget_create, NULL },
1077 { "I/O settings",
1078 "io-settings",
1079 settings_io_widget_create, NULL },
1080
1081 UI_SETTINGS_TERMINATOR
1082 };
1083 /* }}} */
1084
1085 /* {{{ display_nodes_c128 */
1086 /** \brief Child nodes for the C128 'Display' node
1087 */
1088 static ui_settings_tree_node_t display_nodes_c128[] = {
1089 { "Host display",
1090 "host-display",
1091 settings_host_display_widget_create, NULL },
1092 { "VIC-II",
1093 "vicii",
1094 settings_video_create, NULL },
1095 { "VDC",
1096 "vdc",
1097 settings_video_create_vdc, NULL },
1098 { "CRT",
1099 "crt",
1100 settings_crt_widget_create, NULL },
1101 UI_SETTINGS_TERMINATOR
1102 };
1103 /* }}} */
1104
1105 /* {{{ audio_nodes_c128 */
1106 /** \brief Child nodes for the C128 'Audio' node
1107 */
1108 static ui_settings_tree_node_t audio_nodes_c128[] = {
1109 { "Sound",
1110 "sound",
1111 settings_sound_create, NULL },
1112 { "SID",
1113 "sid",
1114 settings_soundchip_widget_create, NULL },
1115 { "Sampler",
1116 "sampler",
1117 settings_sampler_widget_create, NULL },
1118 UI_SETTINGS_TERMINATOR
1119 };
1120 /* }}} */
1121
1122 /* {{{ input_nodes_c128 */
1123 /** \brief Child nodes for the C128 'Input devices' node
1124 */
1125 static ui_settings_tree_node_t input_nodes_c128[] = {
1126 { "Keyboard",
1127 "keyboard",
1128 settings_keyboard_widget_create, NULL },
1129 { "Joystick",
1130 "joystick",
1131 settings_joystick_widget_create, NULL },
1132 { "Control port",
1133 "control-port",
1134 settings_controlport_widget_create, NULL },
1135 UI_SETTINGS_TERMINATOR
1136 };
1137 /* }}} */
1138
1139 /* {{{ peripheral_nodes_c128 */
1140 /** \brief Child nodes for the C128 'Peripheral devices' node
1141 */
1142 static ui_settings_tree_node_t peripheral_nodes_c128[] = {
1143 { "Generic",
1144 "generic",
1145 settings_peripherals_generic_widget_create, NULL },
1146 /* "Output devices? drive is also input */
1147 { "Drive",
1148 "drive",
1149 settings_drive_widget_create, NULL },
1150 { "Filesystem Device",
1151 "fsdevice",
1152 settings_fsdevice_widget_create, NULL },
1153 { "Printer",
1154 "printer",
1155 settings_printer_widget_create, NULL },
1156 #ifdef HAVE_RS232DEV
1157 { "RS232",
1158 "rs232",
1159 settings_rs232_widget_create, NULL },
1160 #endif
1161 { "Userport devices",
1162 "userport-devices",
1163 userport_devices_widget_create, NULL },
1164 { "Tape port devices",
1165 "tapeport-devices",
1166 tapeport_devices_widget_create, NULL },
1167 #ifdef HAVE_RAWNET
1168 { "Ethernet",
1169 "ethernet",
1170 settings_ethernet_widget_create, NULL },
1171 #endif
1172 UI_SETTINGS_TERMINATOR
1173 };
1174 /* }}} */
1175
1176 /* {{{ main_nodes_c128 */
1177 /** \brief Main tree nodes for x128
1178 */
1179 static ui_settings_tree_node_t main_nodes_c128[] = {
1180 { "Host",
1181 "host",
1182 NULL, host_nodes_generic },
1183 { "Machine",
1184 "machine",
1185 NULL, machine_nodes_c128 },
1186 { "Display",
1187 "display",
1188 NULL, display_nodes_c128 },
1189 { "Audio",
1190 "audio",
1191 NULL, audio_nodes_c128 },
1192 { "Input devices",
1193 "input",
1194 NULL, input_nodes_c128 },
1195 { "Peripheral devices",
1196 "peripheral", /* I'll misspell this many times */
1197 NULL, peripheral_nodes_c128 },
1198 { "Cartridges",
1199 "cartridges",
1200 NULL, c128_cartridges },
1201 UI_SETTINGS_TERMINATOR
1202 };
1203 /* }}} */
1204
1205
1206 /*****************************************************************************
1207 * SCPU64 tree nodes for the settings UI *
1208 ****************************************************************************/
1209 #if 0
1210 /* {{{ host_nodes_scpu64 */
1211 /** \brief Child nodes for the SCPU64 'Host' node
1212 */
1213 static ui_settings_tree_node_t host_nodes_scpu64[] = {
1214 { "Autostart",
1215 "autostart",
1216 settings_autostart_widget_create, NULL },
1217 { "Monitor",
1218 "monitor",
1219 settings_monitor_widget_create, NULL },
1220 { "Netplay",
1221 "netplay",
1222 netplay_widget_create, NULL },
1223 { "Snapshot/event/media recording",
1224 "snapshot",
1225 settings_snapshot_widget_create, NULL },
1226
1227 UI_SETTINGS_TERMINATOR
1228 };
1229 /* }}} */
1230 #endif
1231
1232 /* {{{ machine_nodes_scpu64 */
1233 /** \brief Child nodes for the SCPU64 'Machine' node
1234 */
1235 static ui_settings_tree_node_t machine_nodes_scpu64[] = {
1236 { "Model",
1237 "model",
1238 settings_model_widget_create, NULL },
1239 { "SCPU64",
1240 "scpu64",
1241 scpu64_settings_widget_create, NULL },
1242 { "ROM",
1243 "rom-settings",
1244 settings_romset_widget_create, NULL },
1245 { "RAM",
1246 "ram-reset",
1247 settings_ramreset_widget_create, NULL },
1248 { "I/O settings",
1249 "io-settings",
1250 settings_io_widget_create, NULL },
1251 { "Burst Mode Modification",
1252 "burstmode-mode",
1253 burst_mode_widget_create, NULL },
1254 UI_SETTINGS_TERMINATOR
1255 };
1256 /* }}} */
1257
1258 /* {{{ display_nodes_scpu64 */
1259 /** \brief Child nodes for the SCPU64 'Display' node
1260 */
1261 static ui_settings_tree_node_t display_nodes_scpu64[] = {
1262 { "Host display",
1263 "host-display",
1264 settings_host_display_widget_create, NULL },
1265 { "VIC-II",
1266 "vicii",
1267 settings_video_create, NULL },
1268 { "CRT",
1269 "CRT",
1270 settings_crt_widget_create, NULL },
1271 UI_SETTINGS_TERMINATOR
1272 };
1273 /* }}} */
1274
1275 /* {{{ audio_nodes_scpu64 */
1276 /** \brief Child nodes for the SCPU64 'Peripheral devices' node
1277 */
1278 static ui_settings_tree_node_t audio_nodes_scpu64[] = {
1279 { "Sound",
1280 "sound",
1281 settings_sound_create, NULL },
1282 { "SID",
1283 "sid",
1284 settings_soundchip_widget_create, NULL },
1285 { "Sampler",
1286 "sampler",
1287 settings_sampler_widget_create, NULL },
1288 UI_SETTINGS_TERMINATOR
1289 };
1290 /* }}} */
1291
1292 /* {{{ input_nodes_scpu64 */
1293 /** \brief Child nodes for the SCPU64 'Input devices' node
1294 */
1295 static ui_settings_tree_node_t input_nodes_scpu64[] = {
1296 { "Keyboard",
1297 "keyboard",
1298 settings_keyboard_widget_create, NULL },
1299 { "Joystick",
1300 "joystick",
1301 settings_joystick_widget_create, NULL },
1302 { "Control port",
1303 "control-port",
1304 settings_controlport_widget_create, NULL },
1305 UI_SETTINGS_TERMINATOR
1306 };
1307 /* }}} */
1308
1309 /* {{{ peripheral_nodes_scpu64 */
1310 /** \brief Child nodes for the SCPU64 'Peripheral devices' node
1311 */
1312 static ui_settings_tree_node_t peripheral_nodes_scpu64[] = {
1313 { "Generic",
1314 "generic",
1315 settings_peripherals_generic_widget_create, NULL },
1316 { "Drive",
1317 "drive",
1318 settings_drive_widget_create, NULL },
1319 { "Filesystem Device",
1320 "fsdevice",
1321 settings_fsdevice_widget_create, NULL },
1322 { "Printer",
1323 "printer",
1324 settings_printer_widget_create, NULL },
1325 #ifdef HAVE_RS232DEV
1326 { "RS232",
1327 "rs232",
1328 settings_rs232_widget_create, NULL },
1329 #endif
1330 { "Userport devices",
1331 "userport-devices",
1332 userport_devices_widget_create, NULL },
1333 #ifdef HAVE_RAWNET
1334 { "Ethernet",
1335 "ethernet",
1336 settings_ethernet_widget_create, NULL },
1337 #endif
1338 UI_SETTINGS_TERMINATOR
1339 };
1340 /* }}} */
1341
1342 /* {{{ main_nodes_scpu64 */
1343 /** \brief Main tree nodes for xscpu64
1344 */
1345 static ui_settings_tree_node_t main_nodes_scpu64[] = {
1346 { "Host", "host", NULL, host_nodes_generic },
1347 { "Machine", "machine", NULL, machine_nodes_scpu64 },
1348 { "Display", "display", NULL, display_nodes_scpu64 },
1349 { "Audio", "audio", NULL, audio_nodes_scpu64 },
1350 { "Input devices", "input", NULL, input_nodes_scpu64 },
1351 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_scpu64 },
1352 { "Cartridges",
1353 "cartridges",
1354 NULL, scpu64_cartridges },
1355 UI_SETTINGS_TERMINATOR
1356 };
1357 /* }}} */
1358
1359
1360 /*****************************************************************************
1361 * VIC-20 tree nodes for the settings UI *
1362 ****************************************************************************/
1363 #if 0
1364 /* {{{ host_nodes_vic20 */
1365 /** \brief Child nodes for the VIC-20 'Host' node
1366 */
1367 static ui_settings_tree_node_t host_nodes_vic20[] = {
1368 { "Autostart",
1369 "autostart",
1370 settings_autostart_widget_create, NULL },
1371 { "Monitor",
1372 "monitor",
1373 settings_monitor_widget_create, NULL },
1374 { "Netplay",
1375 "netplay",
1376 netplay_widget_create, NULL },
1377 { "Snapshot/event/media recording",
1378 "snapshot",
1379 settings_snapshot_widget_create, NULL },
1380 UI_SETTINGS_TERMINATOR
1381 };
1382 /* }}} */
1383 #endif
1384
1385 /* {{{ machine_nodes_vic20 */
1386 /** \brief Child nodes for the VIC20 'Machine' node
1387 */
1388 static ui_settings_tree_node_t machine_nodes_vic20[] = {
1389 { "Model",
1390 "model",
1391 settings_model_widget_create, NULL },
1392 { "ROM",
1393 "rom-settings",
1394 settings_romset_widget_create, NULL },
1395 { "RAM",
1396 "ram-reset",
1397 settings_ramreset_widget_create, NULL },
1398 { "I/O settings",
1399 "io-settings",
1400 settings_io_widget_create, NULL },
1401 { "I/O RAM",
1402 "io-ram",
1403 vic_ioram_widget_create, NULL },
1404 { "VFLI modification",
1405 "vfli",
1406 vfli_widget_create, NULL },
1407 { "SID Card",
1408 "sid-card",
1409 sidcart_widget_create, NULL },
1410 UI_SETTINGS_TERMINATOR
1411 };
1412 /* }}} */
1413
1414 /* {{{ display_nodes_vic20 */
1415 /** \brief Child nodes for the VIC20 'Display' node
1416 */
1417 static ui_settings_tree_node_t display_nodes_vic20[] = {
1418 { "Host display",
1419 "host-display",
1420 settings_host_display_widget_create, NULL },
1421 { "VIC",
1422 "vic",
1423 settings_video_create, NULL },
1424 { "CRT",
1425 "CRT",
1426 settings_crt_widget_create, NULL },
1427 UI_SETTINGS_TERMINATOR
1428 };
1429 /* }}} */
1430
1431 /* {{{ audio_nodes_vic20 */
1432 /** \brief Child nodes for the VIC20 'Audio' node
1433 */
1434 static ui_settings_tree_node_t audio_nodes_vic20[] = {
1435 { "Sound",
1436 "sound",
1437 settings_sound_create, NULL },
1438 { "SID",
1439 "sid",
1440 settings_soundchip_widget_create, NULL },
1441 { "Sampler",
1442 "sampler",
1443 settings_sampler_widget_create, NULL },
1444 UI_SETTINGS_TERMINATOR
1445 };
1446 /* }}} */
1447
1448 /* {{{ input_nodes_vic20 */
1449 /** \brief Child nodes for the VIC20 'Input devices' node
1450 */
1451 static ui_settings_tree_node_t input_nodes_vic20[] = {
1452 { "Keyboard",
1453 "keyboard",
1454 settings_keyboard_widget_create, NULL },
1455 { "Joystick",
1456 "joystick",
1457 settings_joystick_widget_create, NULL },
1458 { "Control port",
1459 "control-port",
1460 settings_controlport_widget_create, NULL },
1461 UI_SETTINGS_TERMINATOR
1462 };
1463 /* }}} */
1464
1465 /* {{{ peripheral_nodes_vic20 */
1466 /** \brief Child nodes for the VIC20 'Peripheral devices' node
1467 */
1468 static ui_settings_tree_node_t peripheral_nodes_vic20[] = {
1469 { "Generic",
1470 "generic",
1471 settings_peripherals_generic_widget_create, NULL },
1472 { "Drive",
1473 "drive",
1474 settings_drive_widget_create, NULL },
1475 { "Filesystem Device",
1476 "fsdevice",
1477 settings_fsdevice_widget_create, NULL },
1478 { "Printer",
1479 "printer",
1480 settings_printer_widget_create, NULL },
1481 #ifdef HAVE_RS232DEV
1482 { "RS232",
1483 "rs232",
1484 settings_rs232_widget_create, NULL },
1485 #endif
1486 { "Userport devices",
1487 "userport-devices",
1488 userport_devices_widget_create, NULL },
1489 { "Tapeport devices",
1490 "tapeport-devices",
1491 tapeport_devices_widget_create, NULL },
1492 #ifdef HAVE_RAWNET
1493 { "Ethernet",
1494 "ethernet",
1495 settings_ethernet_widget_create, NULL },
1496 #endif
1497 UI_SETTINGS_TERMINATOR
1498 };
1499 /* }}} */
1500
1501 /* {{{ main_nodes_vic20 */
1502 /** \brief Main tree nodes for xvic
1503 */
1504 static ui_settings_tree_node_t main_nodes_vic20[] = {
1505 { "Host", "host", NULL, host_nodes_generic },
1506 { "Machine", "machine", NULL, machine_nodes_vic20 },
1507 { "Display", "display", NULL, display_nodes_vic20 },
1508 { "Audio", "audio", NULL, audio_nodes_vic20 },
1509 { "Input devices", "input", NULL, input_nodes_vic20 },
1510 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_vic20 },
1511 { "Cartridges", "cartridges",
1512 NULL, vic20_cartridges },
1513 #if 0
1514 { "Emulator",
1515 "misc",
1516 settings_misc_widget_create, NULL },
1517 #endif
1518 UI_SETTINGS_TERMINATOR
1519 };
1520 /* }}} */
1521
1522 /*****************************************************************************
1523 * Plus4/C16 tree nodes for the settings UI *
1524 ****************************************************************************/
1525
1526 #if 0
1527 /* {{{ host_nodes_plus4 */
1528 /** \brief Child nodes for the Plus4/C16 'Host' node
1529 */
1530 static ui_settings_tree_node_t host_nodes_plus4[] = {
1531 { "Autostart",
1532 "autostart",
1533 settings_autostart_widget_create, NULL },
1534 { "Monitor",
1535 "monitor",
1536 settings_monitor_widget_create, NULL },
1537 { "Netplay",
1538 "netplay",
1539 netplay_widget_create, NULL },
1540 { "Snapshot/event/media recording",
1541 "snapshot",
1542 settings_snapshot_widget_create, NULL },
1543
1544 UI_SETTINGS_TERMINATOR
1545 };
1546 /* }}} */
1547 #endif
1548
1549 /* {{{ machine_nodes_plus4 */
1550 /** \brief Child nodes for the Plus4 'Machine' node
1551 */
1552 static ui_settings_tree_node_t machine_nodes_plus4[] = {
1553 { "Model",
1554 "model",
1555 settings_model_widget_create, NULL },
1556 { "ROM",
1557 "rom-settings",
1558 settings_romset_widget_create, NULL },
1559 { "RAM",
1560 "ram-reset",
1561 settings_ramreset_widget_create, NULL },
1562 { "I/O settings",
1563 "io-settings",
1564 settings_io_widget_create, NULL },
1565 UI_SETTINGS_TERMINATOR
1566 };
1567 /* }}} */
1568
1569 /* {{{ display_nodes_plus4 */
1570 /** \brief Child nodes for the Plus4 'Display' node
1571 */
1572 static ui_settings_tree_node_t display_nodes_plus4[] = {
1573 { "Host display",
1574 "host-display",
1575 settings_host_display_widget_create, NULL },
1576 { "TED",
1577 "ted",
1578 settings_video_create, NULL },
1579 { "CRT",
1580 "CRT",
1581 settings_crt_widget_create, NULL },
1582 UI_SETTINGS_TERMINATOR
1583 };
1584 /* }}} */
1585
1586 /* {{{ audio_nodes_plus4 */
1587 /** \brief Child nodes for the Plus4 'Audio' node
1588 */
1589 static ui_settings_tree_node_t audio_nodes_plus4[] = {
1590 { "Sound",
1591 "sound",
1592 settings_sound_create, NULL },
1593 { "SID",
1594 "sid",
1595 settings_soundchip_widget_create, NULL },
1596 { "Sampler",
1597 "sampler",
1598 settings_sampler_widget_create, NULL },
1599 UI_SETTINGS_TERMINATOR
1600 };
1601 /* }}} */
1602
1603 /* {{{ input_nodes_plus4 */
1604 /** \brief Child nodes for the Plus4 'Input devices' node
1605 */
1606 static ui_settings_tree_node_t input_nodes_plus4[] = {
1607 { "Keyboard",
1608 "keyboard",
1609 settings_keyboard_widget_create, NULL },
1610 { "Joystick",
1611 "joystick",
1612 settings_joystick_widget_create, NULL },
1613 { "Control port",
1614 "control-port",
1615 settings_controlport_widget_create, NULL },
1616 UI_SETTINGS_TERMINATOR
1617 };
1618 /* }}} */
1619
1620 /* {{{ peripheral_nodes_plus4 */
1621 /** \brief Child nodes for the Plus4 'Peripheral devices' node
1622 */
1623 static ui_settings_tree_node_t peripheral_nodes_plus4[] = {
1624 { "Generic",
1625 "generic",
1626 settings_peripherals_generic_widget_create, NULL },
1627 { "Drive",
1628 "drive",
1629 settings_drive_widget_create, NULL },
1630 { "Filesystem Device",
1631 "fsdevice",
1632 settings_fsdevice_widget_create, NULL },
1633 { "Printer",
1634 "printer",
1635 settings_printer_widget_create, NULL },
1636 #ifdef HAVE_RS232DEV
1637 { "RS232",
1638 "rs232",
1639 settings_rs232_widget_create, NULL },
1640 #endif
1641 { "Userport devices",
1642 "userport-devices",
1643 userport_devices_widget_create, NULL },
1644 { "Tape port devices",
1645 "tapeport-devices",
1646 tapeport_devices_widget_create, NULL },
1647 #ifdef HAVE_RAWNET
1648 { "Ethernet",
1649 "ethernet",
1650 settings_ethernet_widget_create, NULL },
1651 #endif
1652 UI_SETTINGS_TERMINATOR
1653 };
1654 /* }}} */
1655
1656 /* {{{ main_nodes_plus4 */
1657 /** \brief Main tree nodes for xplus4
1658 */
1659 static ui_settings_tree_node_t main_nodes_plus4[] = {
1660 { "Host", "host", NULL, host_nodes_generic },
1661 { "Machine", "machine", NULL, machine_nodes_plus4 },
1662 { "Display", "display", NULL, display_nodes_plus4 },
1663 { "Audio", "audio", NULL, audio_nodes_plus4 },
1664 { "Input devices", "input", NULL, input_nodes_plus4 },
1665 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_plus4 },
1666 { "I/O Extensions",
1667 "io-extensions",
1668 NULL, plus4_io_extensions },
1669 UI_SETTINGS_TERMINATOR
1670 };
1671 /* }}} */
1672
1673
1674 /*****************************************************************************
1675 * PET tree nodes for the settings UI *
1676 ****************************************************************************/
1677
1678 #if 0
1679 /* {{{ host_nodes_pet */
1680 /** \brief Child nodes for the PET 'Host' node
1681 */
1682 static ui_settings_tree_node_t host_nodes_pet[] = {
1683 { "Autostart",
1684 "autostart",
1685 settings_autostart_widget_create, NULL },
1686 { "Monitor",
1687 "monitor",
1688 settings_monitor_widget_create, NULL },
1689 { "Netplay",
1690 "netplay",
1691 netplay_widget_create, NULL },
1692 { "Snapshot/event/media recording",
1693 "snapshot",
1694 settings_snapshot_widget_create, NULL },
1695
1696 UI_SETTINGS_TERMINATOR
1697 };
1698 /* }}} */
1699 #endif
1700
1701 /* {{{ machine_nodes_pet */
1702 /** \brief Child nodes for the PET 'Machine' node
1703 */
1704 static ui_settings_tree_node_t machine_nodes_pet[] = {
1705 { "Model",
1706 "model",
1707 settings_model_widget_create, NULL },
1708 { "ROM",
1709 "rom-settings",
1710 settings_romset_widget_create, NULL },
1711 { "RAM",
1712 "ram-reset",
1713 settings_ramreset_widget_create, NULL },
1714 { "PET userport diagnostic pin",
1715 "pet-diagpin",
1716 pet_diagpin_widget_create, NULL },
1717 { "I/O settings",
1718 "io-settings",
1719 settings_io_widget_create, NULL },
1720 UI_SETTINGS_TERMINATOR
1721 };
1722 /* }}} */
1723
1724 /* {{{ display_nodes_pet */
1725 /** \brief Child nodes for the PET 'Display' node
1726 */
1727 static ui_settings_tree_node_t display_nodes_pet[] = {
1728 { "Host display",
1729 "host-display",
1730 settings_host_display_widget_create, NULL },
1731 { "CRTC",
1732 "crtc",
1733 settings_video_create, NULL },
1734 { "CRT",
1735 "CRT",
1736 settings_crt_widget_create, NULL },
1737 UI_SETTINGS_TERMINATOR
1738 };
1739 /* }}} */
1740
1741 /* {{{ audio_nodes_pet */
1742 /** \brief Child nodes for the PET 'Audio' node
1743 */
1744 static ui_settings_tree_node_t audio_nodes_pet[] = {
1745 { "Sound",
1746 "sound",
1747 settings_sound_create, NULL },
1748 { "SID",
1749 "sid",
1750 settings_soundchip_widget_create, NULL },
1751 { "Sampler",
1752 "sampler",
1753 settings_sampler_widget_create, NULL },
1754 UI_SETTINGS_TERMINATOR
1755 };
1756 /* }}} */
1757
1758 /* {{{ input_nodes_pet */
1759 /** \brief Child nodes for the PET 'Input devices' node
1760 */
1761 static ui_settings_tree_node_t input_nodes_pet[] = {
1762 { "Keyboard",
1763 "keyboard",
1764 settings_keyboard_widget_create, NULL },
1765 { "Joystick",
1766 "joystick",
1767 settings_joystick_widget_create, NULL },
1768 { "Control port",
1769 "control-port",
1770 settings_controlport_widget_create, NULL },
1771 UI_SETTINGS_TERMINATOR
1772 };
1773 /* }}} */
1774
1775 /* {{{ peripheral_nodes_pet */
1776 /** \brief Child nodes for the PET 'Peripheral devices' node
1777 */
1778 static ui_settings_tree_node_t peripheral_nodes_pet[] = {
1779 { "Generic",
1780 "generic",
1781 settings_peripherals_generic_widget_create, NULL },
1782 { "Drive",
1783 "drive",
1784 settings_drive_widget_create, NULL },
1785 { "Filesystem Device",
1786 "fsdevice",
1787 settings_fsdevice_widget_create, NULL },
1788 { "Printer",
1789 "printer",
1790 settings_printer_widget_create, NULL },
1791 #ifdef HAVE_RS232DEV
1792 { "RS232",
1793 "rs232",
1794 settings_rs232_widget_create, NULL },
1795 #endif
1796 { "Userport devices",
1797 "userport-devices",
1798 userport_devices_widget_create, NULL },
1799 { "Tape port devices",
1800 "tapeport-devices",
1801 tapeport_devices_widget_create, NULL },
1802 #if 0 /* not implemented/supported */
1803 #ifdef HAVE_RAWNET
1804 { "Ethernet",
1805 "ethernet",
1806 settings_ethernet_widget_create, NULL },
1807 #endif
1808 #endif
1809 UI_SETTINGS_TERMINATOR
1810 };
1811 /* }}} */
1812
1813 /* {{{ main_nodes_pet */
1814 /** \brief Main tree nodes for xpet
1815 */
1816 static ui_settings_tree_node_t main_nodes_pet[] = {
1817 { "Host", "host", NULL, host_nodes_generic },
1818 { "Machine", "machine", NULL, machine_nodes_pet },
1819 { "Display", "display", NULL, display_nodes_pet },
1820 { "Audio", "audio", NULL, audio_nodes_pet },
1821 { "Input devices", "input", NULL, input_nodes_pet },
1822 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_pet },
1823 { "I/O extensions", "io-extensions",
1824 NULL, pet_io_extensions },
1825 UI_SETTINGS_TERMINATOR
1826 };
1827 /* }}} */
1828
1829
1830 /*****************************************************************************
1831 * CBM5x0 tree nodes for the settings UI *
1832 ****************************************************************************/
1833
1834 #if 0
1835 /* {{{ host_nodes_cbm5x0 */
1836 /** \brief Child nodes for the CBM5x0 'Host' node
1837 */
1838 static ui_settings_tree_node_t host_nodes_cbm5x0[] = {
1839 { "Autostart",
1840 "autostart",
1841 settings_autostart_widget_create, NULL },
1842 { "Monitor",
1843 "monitor",
1844 settings_monitor_widget_create, NULL },
1845 { "Netplay",
1846 "netplay",
1847 netplay_widget_create, NULL },
1848 { "Snapshot/event/media recording",
1849 "snapshot",
1850 settings_snapshot_widget_create, NULL },
1851 UI_SETTINGS_TERMINATOR
1852 };
1853 /* }}} */
1854 #endif
1855
1856 /* {{{ machine_nodes_cbm5x0 */
1857 /** \brief Child nodes for the CBM5x0 'Machine' node
1858 */
1859 static ui_settings_tree_node_t machine_nodes_cbm5x0[] = {
1860 { "Model",
1861 "model",
1862 settings_model_widget_create, NULL },
1863 { "ROM",
1864 "rom-settings",
1865 settings_romset_widget_create, NULL },
1866 { "RAM",
1867 "ram-reset",
1868 settings_ramreset_widget_create, NULL },
1869 { "I/O settings",
1870 "io-settings",
1871 settings_io_widget_create, NULL },
1872 UI_SETTINGS_TERMINATOR
1873 };
1874 /* }}} */
1875
1876 /* {{{ display_nodes_cbm5x0 */
1877 /** \brief Child nodes for the CBM5x0 'Display' node
1878 */
1879 static ui_settings_tree_node_t display_nodes_cbm5x0[] = {
1880 { "Host display",
1881 "host-display",
1882 settings_host_display_widget_create, NULL },
1883 { "VIC-II",
1884 "vicii",
1885 settings_video_create, NULL },
1886 { "CRT",
1887 "CRT",
1888 settings_crt_widget_create, NULL },
1889 UI_SETTINGS_TERMINATOR
1890 };
1891 /* }}} */
1892
1893 /* {{{ audio_nodes_cbm5x0 */
1894 /** \brief Child nodes for the CBM5x0 'Audio' node
1895 */
1896 static ui_settings_tree_node_t audio_nodes_cbm5x0[] = {
1897 { "Sound",
1898 "sound",
1899 settings_sound_create, NULL },
1900 { "SID",
1901 "sid",
1902 settings_soundchip_widget_create, NULL },
1903 { "Sampler",
1904 "sampler",
1905 settings_sampler_widget_create, NULL },
1906 UI_SETTINGS_TERMINATOR
1907 };
1908 /* }}} */
1909
1910 /* {{{ input_nodes_cbm5x0 */
1911 /** \brief Child nodes for the CBM5x0 'Input devices' node
1912 */
1913 static ui_settings_tree_node_t input_nodes_cbm5x0[] = {
1914 { "Keyboard",
1915 "keyboard",
1916 settings_keyboard_widget_create, NULL },
1917 { "Joystick",
1918 "joystick",
1919 settings_joystick_widget_create, NULL },
1920 { "Control port",
1921 "control-port",
1922 settings_controlport_widget_create, NULL },
1923 UI_SETTINGS_TERMINATOR
1924 };
1925 /* }}} */
1926
1927 /* {{{ peripheral_nodes_cbm5x0 */
1928 /** \brief Child nodes for the CBM5x0 'Peripheral devices' node
1929 */
1930 static ui_settings_tree_node_t peripheral_nodes_cbm5x0[] = {
1931 { "Generic",
1932 "generic",
1933 settings_peripherals_generic_widget_create, NULL },
1934 { "Drive",
1935 "drive",
1936 settings_drive_widget_create, NULL },
1937 { "Filesystem Device",
1938 "fsdevice",
1939 settings_fsdevice_widget_create, NULL },
1940 { "Printer",
1941 "printer",
1942 settings_printer_widget_create, NULL },
1943 #ifdef HAVE_RS232DEV
1944 { "RS232",
1945 "rs232",
1946 settings_rs232_widget_create, NULL },
1947 #endif
1948 { "Tape port devices",
1949 "tapeport-devices",
1950 tapeport_devices_widget_create, NULL },
1951
1952 UI_SETTINGS_TERMINATOR
1953 };
1954 /* }}} */
1955
1956 /* {{{ main_nodes_cbm5x0 */
1957 /** \brief Main tree nodes for xcbm5x0
1958 */
1959 static ui_settings_tree_node_t main_nodes_cbm5x0[] = {
1960 { "Host", "host", NULL, host_nodes_generic },
1961 { "Machine", "machine", NULL, machine_nodes_cbm5x0 },
1962 { "Display", "display", NULL, display_nodes_cbm5x0 },
1963 { "Audio", "audio", NULL, audio_nodes_cbm5x0 },
1964 { "Input devices", "input", NULL, input_nodes_cbm5x0 },
1965 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_cbm5x0 },
1966 #if 0
1967 { "I/O extensions", "io-extensions", NULL, cbm5x0_io_extensions },
1968 #endif
1969 #if 0
1970 { "Emulator",
1971 "misc",
1972 settings_misc_widget_create, NULL },
1973 #endif
1974 UI_SETTINGS_TERMINATOR
1975 };
1976 /* }}} */
1977
1978
1979 /*****************************************************************************
1980 * CBM-II tree nodes for the settings UI *
1981 ****************************************************************************/
1982
1983 #if 0
1984 /* {{{ host_nodes_cbm6x0 */
1985 /** \brief Child nodes for the CBM6x0 'Host' node
1986 */
1987 static ui_settings_tree_node_t host_nodes_cbm6x0[] = {
1988 { "Autostart",
1989 "autostart",
1990 settings_autostart_widget_create, NULL },
1991 { "Monitor",
1992 "monitor",
1993 settings_monitor_widget_create, NULL },
1994 { "Netplay",
1995 "netplay",
1996 netplay_widget_create, NULL },
1997 { "Snapshot/event/media recording",
1998 "snapshot",
1999 settings_snapshot_widget_create, NULL },
2000 UI_SETTINGS_TERMINATOR
2001 };
2002 /* }}} */
2003 #endif
2004
2005 /* {{{ machine_nodes_cbm6x0 */
2006 /** \brief Child nodes for the CBM6x0 'Machine' node
2007 */
2008 static ui_settings_tree_node_t machine_nodes_cbm6x0[] = {
2009 { "Model",
2010 "model",
2011 settings_model_widget_create, NULL },
2012 { "ROM",
2013 "rom-settings",
2014 settings_romset_widget_create, NULL },
2015 { "RAM",
2016 "ram-reset",
2017 settings_ramreset_widget_create, NULL },
2018 { "I/O settings",
2019 "io-settings",
2020 settings_io_widget_create, NULL },
2021 UI_SETTINGS_TERMINATOR
2022 };
2023 /* }}} */
2024
2025 /* {{{ display_nodes_cbm6x0 */
2026 /** \brief Child nodes for the CBM6x0 'Display' node
2027 */
2028 static ui_settings_tree_node_t display_nodes_cbm6x0[]= {
2029 { "Host display",
2030 "host-display",
2031 settings_host_display_widget_create, NULL },
2032 { "CRTC",
2033 "crtc",
2034 settings_video_create, NULL },
2035 { "CRT",
2036 "CRT",
2037 settings_crt_widget_create, NULL },
2038 UI_SETTINGS_TERMINATOR
2039 };
2040 /* }}} */
2041
2042 /* {{{ audio_nodes_cbm6x0 */
2043 /** \brief Child nodes for the CBM6x0 'Audio' node
2044 */
2045 static ui_settings_tree_node_t audio_nodes_cbm6x0[] = {
2046 { "Sound",
2047 "sound",
2048 settings_sound_create, NULL },
2049 { "SID",
2050 "sid",
2051 settings_soundchip_widget_create, NULL },
2052 { "Sampler",
2053 "sampler",
2054 settings_sampler_widget_create, NULL },
2055 UI_SETTINGS_TERMINATOR
2056 };
2057 /* }}} */
2058
2059 /* {{{ input_nodes_cbm6x0 */
2060 /** \brief Child nodes for the CBM6x0 'Input devices' node
2061 */
2062 static ui_settings_tree_node_t input_nodes_cbm6x0[] = {
2063 { "Keyboard",
2064 "keyboard",
2065 settings_keyboard_widget_create, NULL },
2066 { "Joystick",
2067 "joystick",
2068 settings_joystick_widget_create, NULL },
2069 { "Control port",
2070 "control-port",
2071 settings_controlport_widget_create, NULL },
2072
2073 UI_SETTINGS_TERMINATOR
2074 };
2075 /* }}} */
2076
2077 /* {{{ peripheral nodes_cbm6x0 */
2078 /** \brief Child nodes for the CBM6x0 'Peripheral devices' node
2079 */
2080 static ui_settings_tree_node_t peripheral_nodes_cbm6x0[] = {
2081 { "Generic",
2082 "generic",
2083 settings_peripherals_generic_widget_create, NULL },
2084 { "Drive",
2085 "drive",
2086 settings_drive_widget_create, NULL },
2087 { "Filesystem Device",
2088 "fsdevice",
2089 settings_fsdevice_widget_create, NULL },
2090 { "Printer",
2091 "printer",
2092 settings_printer_widget_create, NULL },
2093 #ifdef HAVE_RS232DEV
2094 { "RS232",
2095 "rs232",
2096 settings_rs232_widget_create, NULL },
2097 #endif
2098 { "Userport devices",
2099 "userport-devices",
2100 userport_devices_widget_create, NULL },
2101 { "Tape port devices",
2102 "tapeport_devices",
2103 tapeport_devices_widget_create, NULL },
2104
2105 UI_SETTINGS_TERMINATOR
2106 };
2107 /* }}} */
2108
2109 /* {{{ main_nodes_cbm6x0 */
2110 /** \brief Main tree nodes for xcbm6x0
2111 */
2112 static ui_settings_tree_node_t main_nodes_cbm6x0[] = {
2113 { "Host", "host", NULL, host_nodes_generic },
2114 { "Machine", "machine", NULL, machine_nodes_cbm6x0 },
2115 { "Display", "display", NULL, display_nodes_cbm6x0 },
2116 { "Audio", "audio", NULL, audio_nodes_cbm6x0 },
2117 { "Input devices", "input", NULL, input_nodes_cbm6x0 },
2118 { "Peripheral devices", "peripheral", NULL, peripheral_nodes_cbm6x0 },
2119 #if 0
2120 { "I/O extensions", "io-extensions",NULL, cbm6x0_io_extensions },
2121 #endif
2122 { "Snapshot/event/media recording",
2123 "snapshot",
2124 settings_snapshot_widget_create, NULL },
2125 #if 0
2126 { "Emulator",
2127 "misc",
2128 settings_misc_widget_create, NULL },
2129 #endif
2130 UI_SETTINGS_TERMINATOR
2131 };
2132 /* }}} */
2133
2134
2135 /** \brief Reference to the current 'central' widget in the settings dialog
2136 */
2137 static void ui_settings_set_central_widget(GtkWidget *widget);
2138
2139
2140 /** \brief Old pause state when popping up the dialog
2141 *
2142 * Used for the PauseOnSettings resource: if true, exiting the dialog will set
2143 * the emulators pause state to this.
2144 */
2145 static int settings_old_pause_state;
2146
2147
2148 /** \brief Reference to the settings dialog
2149 */
2150 static GtkWidget *settings_window = NULL;
2151
2152
2153 /** \brief Reference to the 'content area' widget of the settings dialog
2154 */
2155 static GtkWidget *settings_grid = NULL;
2156
2157
2158 /** \brief Reference to the tree model for the settings tree
2159 */
2160 static GtkTreeStore *settings_model = NULL;
2161
2162
2163 /** \brief Reference to the tree view for the settings tree
2164 */
2165 static GtkWidget *settings_tree = NULL;
2166
2167
2168 /** \brief Scroll window container for the settings treeview
2169 */
2170 static GtkWidget *scrolled_window = NULL;
2171
2172
2173 /** \brief Widget containing the treeview and the settings 'page'
2174 *
2175 * Allows resizing both the treeview and the setting with a 'grip'.
2176 */
2177 static GtkWidget *paned_widget = NULL;
2178
2179
2180 /** \brief Path to the last used settings page
2181 */
2182 static GtkTreePath *last_node_path = NULL;
2183
2184
2185 /** \brief Handler for the "destroy" event of the main dialog
2186 *
2187 * \param[in] widget main dialog (unused)
2188 * \param[in] data extra event data (unused)
2189 */
on_settings_dialog_destroy(GtkWidget * widget,gpointer data)2190 static void on_settings_dialog_destroy(GtkWidget *widget, gpointer data)
2191 {
2192 settings_window = NULL;
2193 }
2194
2195
2196 /** \brief Handler for the double click event of a tree node
2197 *
2198 * Expands or collapses the node and its children (if any)
2199 *
2200 * \param[in,out] tree_view tree view instance
2201 * \param[in] path tree view path
2202 * \param[in] column tree view column (unused)
2203 * \param[in] user_data extra event data (unused)
2204 */
on_row_activated(GtkTreeView * tree_view,GtkTreePath * path,GtkTreeViewColumn * column,gpointer user_data)2205 static void on_row_activated(GtkTreeView *tree_view,
2206 GtkTreePath *path,
2207 GtkTreeViewColumn *column,
2208 gpointer user_data)
2209 {
2210 if (gtk_tree_view_row_expanded(tree_view, path)) {
2211 gtk_tree_view_collapse_row(tree_view, path);
2212 } else {
2213 /*
2214 * Only expand the immediate children. A no-op at the moment since
2215 * we only have two levels of nodes in the tree, but perhaps useful
2216 * for later.
2217 */
2218 gtk_tree_view_expand_row(tree_view, path, FALSE);
2219 }
2220 }
2221
2222
2223 /** \brief Create the widget that is initially shown in the settings UI
2224 *
2225 * \param[in] parent parent widget (unused)
2226 *
2227 * \return GtkGrid
2228 */
ui_settings_inital_widget(GtkWidget * parent)2229 static GtkWidget *ui_settings_inital_widget(GtkWidget *parent)
2230 {
2231 GtkWidget *grid;
2232 GtkWidget *label;
2233
2234 grid = vice_gtk3_grid_new_spaced(64, 64);
2235 label = gtk_label_new(NULL);
2236 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
2237 gtk_label_set_markup(GTK_LABEL(label),
2238 "This is the first widget/dialog shown when people click on the"
2239 " settings UI.\n"
2240 "So perhaps we could show some instructions or something here.");
2241 gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
2242
2243 gtk_widget_show_all(grid);
2244 return grid;
2245 }
2246
2247
2248 #if 0
2249 /** \brief Paused state when popping up the UI
2250 */
2251 static int old_pause_state;
2252 #endif
2253
2254 /** \brief Handler for the "changed" event of the tree view
2255 *
2256 * \param[in] selection GtkTreeSelection associated with the tree model
2257 * \param[in] user_data data for the event (unused for now)
2258 *
2259 */
on_tree_selection_changed(GtkTreeSelection * selection,gpointer user_data)2260 static void on_tree_selection_changed(
2261 GtkTreeSelection *selection,
2262 gpointer user_data)
2263 {
2264 GtkTreeIter iter;
2265 GtkTreeModel *model;
2266
2267 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2268 gchar *name = NULL;
2269 gchar *parent_name = NULL;
2270 GtkWidget *(*callback)(void *) = NULL;
2271 const char *id;
2272
2273
2274 gtk_tree_model_get(model, &iter, COLUMN_NAME, &name, -1);
2275 gtk_tree_model_get(model, &iter, COLUMN_CALLBACK, &callback, -1);
2276 gtk_tree_model_get(model, &iter, COLUMN_ID, &id, -1);
2277 #if 0
2278 debug_gtk3("node name: %s", name);
2279 debug_gtk3("node ID: %s", id);
2280 #endif
2281 if (callback != NULL) {
2282 GtkTreeIter parent;
2283 char *title;
2284
2285 /* try to get parent's name */
2286 if (gtk_tree_model_iter_parent(model, &parent, &iter)) {
2287 gtk_tree_model_get(model, &parent, COLUMN_NAME, &parent_name, -1);
2288 }
2289
2290 if (parent_name != NULL) {
2291 title = lib_msprintf("%s settings :: %s :: %s",
2292 machine_name, parent_name, name);
2293 } else {
2294 title = lib_msprintf("%s settings :: %s", machine_name, name);
2295 }
2296 gtk_window_set_title(GTK_WINDOW(settings_window), title);
2297 lib_free(title);
2298 /* create new central widget, using settings_window (this dialog)
2299 * as its parent, this will allow for proper blocking in modal
2300 * dialogs, while ui_get_active_window() breaks that. */
2301 if (last_node_path != NULL) {
2302 gtk_tree_path_free(last_node_path);
2303 }
2304 last_node_path = gtk_tree_model_get_path(
2305 GTK_TREE_MODEL(settings_model), &iter);
2306 ui_settings_set_central_widget(callback(settings_window));
2307 }
2308 if (name != NULL) {
2309 g_free(name);
2310 }
2311 if (parent_name != NULL) {
2312 g_free(parent_name);
2313 }
2314 }
2315 }
2316
2317
2318 /** \brief Create the 'Save on exit' checkbox
2319 *
2320 * The current position/display of the checkbox is a little lame at the moment
2321 *
2322 * \return GtkCheckButton
2323 */
create_save_on_exit_checkbox(void)2324 static GtkWidget *create_save_on_exit_checkbox(void)
2325 {
2326 return vice_gtk3_resource_check_button_new("SaveResourcesOnExit",
2327 "Save settings on exit");
2328 }
2329
2330
2331 /** \brief Create the 'Confirm on exit' checkbox
2332 *
2333 * The current position/display of the checkbox is a little lame at the moment
2334 *
2335 * \return GtkCheckButton
2336 */
create_confirm_on_exit_checkbox(void)2337 static GtkWidget *create_confirm_on_exit_checkbox(void)
2338 {
2339 return vice_gtk3_resource_check_button_new("ConfirmOnExit",
2340 "Confirm on exit");
2341 }
2342
2343
2344 /** \brief Create the 'Pause on settings dialog' checkbox
2345 *
2346 * \return GtkCheckButton
2347 */
create_pause_on_settings_checkbox(void)2348 static GtkWidget *create_pause_on_settings_checkbox(void)
2349 {
2350 return vice_gtk3_resource_check_button_new(
2351 "PauseOnSettings",
2352 "Pause when showing settings");
2353 }
2354
2355
2356 /** \brief Create empty tree model for the settings tree
2357 */
create_tree_model(void)2358 static void create_tree_model(void)
2359 {
2360 settings_model = gtk_tree_store_new(NUM_COLUMNS,
2361 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
2362 }
2363
2364
2365 /** \brief Create tree store containing settings items and children
2366 *
2367 * \return GtkTreeStore
2368 */
populate_tree_model(void)2369 static GtkTreeStore *populate_tree_model(void)
2370 {
2371 GtkTreeStore *model;
2372 GtkTreeIter iter;
2373 GtkTreeIter child;
2374 ui_settings_tree_node_t *nodes = NULL;
2375 int i;
2376
2377 model = settings_model;
2378
2379 switch (machine_class) {
2380 case VICE_MACHINE_C64: /* fall through */
2381 case VICE_MACHINE_C64SC:
2382 nodes = main_nodes_c64;
2383 break;
2384 case VICE_MACHINE_C64DTV:
2385 nodes = main_nodes_c64dtv;
2386 break;
2387 case VICE_MACHINE_C128:
2388 nodes = main_nodes_c128;
2389 break;
2390 case VICE_MACHINE_SCPU64:
2391 nodes = main_nodes_scpu64;
2392 break;
2393 case VICE_MACHINE_VIC20:
2394 nodes = main_nodes_vic20;
2395 break;
2396 case VICE_MACHINE_PLUS4:
2397 nodes = main_nodes_plus4;
2398 break;
2399 case VICE_MACHINE_PET:
2400 nodes = main_nodes_pet;
2401 break;
2402 case VICE_MACHINE_CBM5x0:
2403 nodes = main_nodes_cbm5x0;
2404 break;
2405 case VICE_MACHINE_CBM6x0:
2406 nodes = main_nodes_cbm6x0;
2407 break;
2408 case VICE_MACHINE_VSID:
2409 nodes = main_nodes_vsid;
2410 break;
2411 default:
2412 fprintf(stderr,
2413 "Error: %s:%d:%s(): unsupported machine_class %d\n",
2414 __FILE__, __LINE__, __func__, machine_class);
2415 archdep_vice_exit(1);
2416 break;
2417 }
2418
2419 for (i = 0; nodes[i].name != NULL; i++) {
2420 gtk_tree_store_append(model, &iter, NULL);
2421 gtk_tree_store_set(model, &iter,
2422 COLUMN_NAME, nodes[i].name,
2423 COLUMN_ID, nodes[i].id,
2424 COLUMN_CALLBACK, nodes[i].callback,
2425 -1);
2426
2427 /* this bit will need proper recursion if we need more than two
2428 * levels of subitems */
2429 if (nodes[i].children != NULL) {
2430 int c;
2431 ui_settings_tree_node_t *list = nodes[i].children;
2432
2433 for (c = 0; list[c].name != NULL; c++) {
2434 char buffer[256];
2435
2436 /* mark items without callback with 'TODO' */
2437 if (list[c].callback != NULL) {
2438 g_snprintf(buffer, 256, "%s", list[c].name);
2439 } else {
2440 g_snprintf(buffer, 256, "TODO: %s", list[c].name);
2441 }
2442
2443 gtk_tree_store_append(model, &child, &iter);
2444 gtk_tree_store_set(model, &child,
2445 COLUMN_NAME, buffer,
2446 COLUMN_ID, list[c].id,
2447 COLUMN_CALLBACK, list[c].callback,
2448 -1);
2449 }
2450 }
2451 }
2452 return model;
2453 }
2454
2455
2456 /** \brief Create treeview for settings side-menu
2457 *
2458 * Reads items from `main_nodes` and adds them to the tree view.
2459 *
2460 * \return GtkTreeView
2461 *
2462 * TODO: Handle nested items, and write up somewhere how the hell I finally
2463 * got the callbacks working.
2464 * Split into a function creating the tree view and functions adding,
2465 * altering or removing nodes.
2466 */
create_treeview(void)2467 static GtkWidget *create_treeview(void)
2468 {
2469 GtkWidget *tree;
2470 GtkCellRenderer *text_renderer;
2471 GtkTreeViewColumn *text_column;
2472 #if 0
2473 GtkCssProvider *css_provider;
2474 GtkStyleContext *style_context;
2475 GError *err = NULL;
2476 #endif
2477
2478 create_tree_model();
2479 tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(populate_tree_model()));
2480 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
2481
2482 text_renderer = gtk_cell_renderer_text_new();
2483 text_column = gtk_tree_view_column_new_with_attributes(
2484 "item-name",
2485 text_renderer,
2486 "text", 0,
2487 NULL);
2488 /* gtk_tree_view_append_column(GTK_TREE_VIEW(tree), obj_column); */
2489 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), text_column);
2490
2491 /* apply CSS for keyboard navigation */
2492 vice_gtk3_css_add(tree, TREEVIEW_CSS);
2493 return tree;
2494 }
2495
2496
2497 /** \brief Set the 'central'/action widget for the settings dialog
2498 *
2499 * Destroys the old 'central' widget and sets the new one.
2500 *
2501 * \param[in,out] widget widget to use as the new 'central' widget
2502 */
ui_settings_set_central_widget(GtkWidget * widget)2503 static void ui_settings_set_central_widget(GtkWidget *widget)
2504 {
2505 GtkWidget *child;
2506
2507 #if 0
2508 debug_gtk3("checking for child");
2509 child = gtk_grid_get_child_at(GTK_GRID(settings_grid), 1, 0);
2510 #else
2511 child = gtk_paned_get_child2(GTK_PANED(paned_widget));
2512 #endif
2513 if (child != NULL) {
2514 gtk_widget_destroy(child);
2515 #if 0
2516 resource_manager = NULL;
2517 #endif
2518 }
2519 gtk_paned_pack2(GTK_PANED(paned_widget), widget, TRUE, FALSE);
2520 /* add a little space around the widget */
2521 g_object_set(widget, "margin", 16, NULL);
2522 }
2523
2524
2525 /** \brief Create the 'content widget' of the settings dialog
2526 *
2527 * This creates the widget in the dialog used to display the treeview and room
2528 * for the widget connected to that tree's currently selected item.
2529 *
2530 * \param[in] widget parent widget
2531 *
2532 * \return GtkGrid (as a GtkWidget)
2533 */
create_content_widget(GtkWidget * widget)2534 static GtkWidget *create_content_widget(GtkWidget *widget)
2535 {
2536 GtkTreeSelection *selection;
2537 GtkWidget *extra;
2538
2539 settings_grid = gtk_grid_new();
2540 settings_tree = create_treeview();
2541
2542 /* pack the tree in a scrolled window to allow scrolling of the tree when
2543 * it gets too large for the dialog
2544 */
2545 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
2546 gtk_container_add(GTK_CONTAINER(scrolled_window), settings_tree);
2547
2548 /* pack the tree and the settings 'page' into a GtkPaned so we can resize
2549 * the tree */
2550 paned_widget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
2551 gtk_paned_set_wide_handle(GTK_PANED(paned_widget), TRUE);
2552
2553 #if 0
2554 gtk_grid_attach(GTK_GRID(settings_grid), scrolled_window, 0, 0, 1, 1);
2555 #else
2556 gtk_paned_pack1(GTK_PANED(paned_widget), scrolled_window, FALSE, FALSE);
2557 #endif
2558 #if 0
2559 gtk_grid_attach(GTK_GRID(settings_grid), scrolled_window, 0, 0, 1, 1);
2560 #endif
2561 gtk_grid_attach(GTK_GRID(settings_grid), paned_widget, 0, 0, 1, 1);
2562
2563
2564 /* Remember the previously selected setting/widget and set it here */
2565
2566 /* do we have a previous settings "page"? */
2567 if (last_node_path == NULL) {
2568 /* nope, display the default one */
2569 ui_settings_set_central_widget(ui_settings_inital_widget(widget));
2570 } else {
2571 /* try to restore the page last shown */
2572 GtkTreeIter iter;
2573 #if 0
2574 debug_gtk3("Attempting to get previous settings page");
2575 #endif
2576 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(settings_model), &iter,
2577 last_node_path)) {
2578 debug_gtk3("Oops");
2579 } else {
2580 GtkWidget *(*callback)(GtkWidget *) = NULL;
2581 gtk_tree_model_get(
2582 GTK_TREE_MODEL(settings_model), &iter,
2583 COLUMN_CALLBACK, &callback, -1);
2584 if (callback != NULL) {
2585
2586 selection = gtk_tree_view_get_selection(
2587 GTK_TREE_VIEW(settings_tree));
2588
2589 ui_settings_set_central_widget(callback(widget));
2590 gtk_tree_view_expand_to_path(
2591 GTK_TREE_VIEW(settings_tree),
2592 last_node_path);
2593 gtk_tree_selection_select_path(selection, last_node_path);
2594
2595 }
2596 }
2597 }
2598
2599 /* create container for generic settings */
2600 extra = gtk_grid_new();
2601 gtk_grid_set_column_spacing(GTK_GRID(extra), 8);
2602 gtk_grid_set_row_spacing(GTK_GRID(extra), 8);
2603 g_object_set(extra, "margin", 16, NULL);
2604
2605 gtk_grid_attach(GTK_GRID(extra), create_save_on_exit_checkbox(),
2606 0, 0, 1, 1);
2607 gtk_grid_attach(GTK_GRID(extra), create_confirm_on_exit_checkbox(),
2608 0, 1, 1, 1);
2609 gtk_grid_attach(GTK_GRID(extra), create_pause_on_settings_checkbox(),
2610 0, 2, 1, 1);
2611
2612 /* add to main layout */
2613 gtk_grid_attach(GTK_GRID(settings_grid), extra, 0, 2, 2, 1);
2614
2615 gtk_widget_show(settings_grid);
2616 gtk_widget_show(settings_tree);
2617
2618 gtk_widget_set_size_request(scrolled_window, 250, 500);
2619 gtk_widget_set_size_request(settings_grid, DIALOG_WIDTH, DIALOG_HEIGHT);
2620
2621 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(settings_tree));
2622 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
2623 g_signal_connect_unlocked(G_OBJECT(selection), "changed",
2624 G_CALLBACK(on_tree_selection_changed), NULL);
2625
2626 /* handler for the double click event on a node */
2627 g_signal_connect(settings_tree, "row-activated",
2628 G_CALLBACK(on_row_activated), NULL);
2629
2630 return settings_grid;
2631 }
2632
2633
2634 /** \brief Handler for the "response" event of the settings dialog
2635 *
2636 * This determines what to do based on the 'reponse ID' emitted by the dialog.
2637 *
2638 * \param[in] widget widget triggering the event (the dialog)
2639 * \param[in] response_id response ID
2640 * \param[in] user_data extra data (unused)
2641 */
response_callback(GtkWidget * widget,gint response_id,gpointer user_data)2642 static void response_callback(GtkWidget *widget, gint response_id,
2643 gpointer user_data)
2644 {
2645 int pause_on_settings;
2646
2647 switch (response_id) {
2648
2649 /* close dialog */
2650 case GTK_RESPONSE_DELETE_EVENT:
2651 gtk_widget_destroy(widget);
2652 settings_window = NULL;
2653
2654 resources_get_int("PauseOnSettings", &pause_on_settings);
2655 if (pause_on_settings) {
2656 if (settings_old_pause_state) {
2657 ui_pause_enable();
2658 } else {
2659 ui_pause_disable();
2660 }
2661 }
2662
2663 break;
2664
2665 /* reset resources in current central widget to the state they were
2666 * in before entering the (sub)dialog */
2667 case RESPONSE_RESET:
2668 debug_gtk3("Resetting widgets to their dialog-entry state"
2669 " temporarily disabled.");
2670 break;
2671
2672 /* restore resources in (sub)dialog to factory settings */
2673 case RESPONSE_FACTORY:
2674 debug_gtk3("Resetting widgets to their factory value temporarily"
2675 " disabled.");
2676 default:
2677 break;
2678 }
2679 }
2680
2681
2682 /** \brief Respond to window size changes
2683 *
2684 * This allows for quickly seeing if specific dialog is getting too large. The
2685 * DIALOG_WIDTH_MAX and DIALOG_HEIGHT_MAX I sucked out of my thumb, since due
2686 * to window managers using different themes, we can't use 'proper' values, so
2687 * I had to use approximate values.
2688 *
2689 * \param[in] widget a GtkWindow
2690 * \param[in] event the GDK event
2691 * \param[in] data extra event data (unused)
2692 *
2693 * \return boolean
2694 */
on_dialog_configure_event(GtkWidget * widget,GdkEvent * event,gpointer data)2695 static gboolean on_dialog_configure_event(
2696 GtkWidget *widget,
2697 GdkEvent *event,
2698 gpointer data)
2699 {
2700 #if 0
2701 if (event->type == GDK_CONFIGURE) {
2702 GdkEventConfigure *cfg = (GdkEventConfigure *)event;
2703 int width = cfg->width;
2704 int height = cfg->height;
2705
2706 /* debug_gtk3("width %d, height %d.", width, height); */
2707 if (width > DIALOG_WIDTH_MAX || height > DIALOG_HEIGHT_MAX) {
2708 /* uncomment the following to get some 'help' while building
2709 * new dialogs: */
2710 #if 0
2711 gtk_window_set_title(GTK_WINDOW(widget),
2712 "HELP! --- DIALOG IS TOO BLOODY LARGE -- ERROR!");
2713 #endif
2714 debug_gtk3("Dialog is too large: %dx%d (max: %dx%d).",
2715 width, height, DIALOG_WIDTH_MAX, DIALOG_HEIGHT_MAX);
2716 }
2717 #if 0
2718 debug_gtk3("XPOS: %d - YPOS: %d", cfg->x, cfg->y);
2719 #endif
2720 }
2721 #endif
2722 return FALSE;
2723 }
2724
2725
2726
2727 /** \brief Dialog create helper
2728 *
2729 * \return Settings dialog
2730 */
dialog_create_helper(void)2731 static GtkWidget *dialog_create_helper(void)
2732 {
2733 GtkWidget *dialog;
2734 GtkWidget *content;
2735 char title[256];
2736
2737 vsync_suspend_speed_eval();
2738
2739 g_snprintf(title, sizeof(title), "%s Settings", machine_name);
2740
2741 dialog = gtk_dialog_new_with_buttons(
2742 title,
2743 ui_get_active_window(),
2744 GTK_DIALOG_MODAL,
2745 /*
2746 * Temp. disabled due to code freeze, will work on this again
2747 * after the code freeze -- compyx
2748 */
2749 #if 0
2750 "Revert changes", RESPONSE_RESET,
2751 "Factory reset", RESPONSE_FACTORY,
2752 #endif
2753 "Close", GTK_RESPONSE_DELETE_EVENT,
2754 NULL);
2755
2756 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
2757 g_object_set(content, "border-width", 8, NULL);
2758 gtk_container_add(GTK_CONTAINER(content), create_content_widget(dialog));
2759
2760 /* set default response to Close */
2761 gtk_dialog_set_default_response(
2762 GTK_DIALOG(dialog),
2763 GTK_RESPONSE_DELETE_EVENT);
2764
2765 gtk_window_set_resizable(GTK_WINDOW(dialog), TRUE);
2766 g_signal_connect_unlocked(dialog, "response", G_CALLBACK(response_callback), NULL);
2767 g_signal_connect_unlocked(dialog, "configure-event",
2768 G_CALLBACK(on_dialog_configure_event), NULL);
2769 g_signal_connect_unlocked(dialog, "destroy", G_CALLBACK(on_settings_dialog_destroy),
2770 NULL);
2771
2772 return dialog;
2773 }
2774
2775
2776 /** \brief Callback to create the main settings dialog from the menu
2777 *
2778 * \param[in] widget (direct) parent widget, the menu item
2779 * \param[in] user_data data for the event (unused)
2780 *
2781 * \note The appearance of minimize/maximize buttons seems to depend on
2782 * which Window Manager is active:
2783 *
2784 * On MATE (marco, a Metacity fork) both buttons are hidden.
2785 * On KDE (KWin) the maximize button is still visible but inactive
2786 * On OpenBox both min/max are visible with only minimize working
2787 *
2788 * \return TRUE (avoids the key press getting passed to the emulated machine)
2789 */
ui_settings_dialog_create(GtkWidget * widget,gpointer user_data)2790 gboolean ui_settings_dialog_create(GtkWidget *widget, gpointer user_data)
2791 {
2792
2793 ui_settings_dialog_create_and_activate_node(NULL);
2794
2795 return TRUE;
2796 }
2797
2798
2799 /** \brief Clean up resources used on emu exit
2800 *
2801 * Do NOT call this when exiting the settings UI, the event handlers will take
2802 * care of cleaning up resources used by the UI. This function cleans up the
2803 * data used to present the user with the last used settings page.
2804 */
ui_settings_shutdown(void)2805 void ui_settings_shutdown(void)
2806 {
2807 if (last_node_path != NULL) {
2808 gtk_tree_path_free(last_node_path);
2809 last_node_path = NULL;
2810 }
2811 }
2812
2813
2814 /** \brief Find and activate node in the tree view via \a path
2815 *
2816 * The \a path argument is expected to be in the form 'foo/bar/bah', each
2817 * path item indicates a node in the tree view/model. For example:
2818 * "display/vdc" would select the VDC settings dialog on x128, but would fail
2819 * on any other machine.
2820 *
2821 * \param[in] path path to the node
2822 *
2823 * \return bool
2824 */
ui_settings_dialog_activate_node(const char * path)2825 gboolean ui_settings_dialog_activate_node(const char *path)
2826 {
2827 GtkTreeIter iter;
2828 gchar **parts;
2829 const gchar *part;
2830 int column = 0;
2831
2832 if (settings_window == NULL) {
2833 log_error(LOG_ERR, "settings dialog node activation requested without"
2834 " the dialog active.");
2835 return FALSE;
2836 }
2837 if (path == NULL || *path == '\0') {
2838 log_error(LOG_ERR, "NULL or empty path pased.");
2839 return FALSE;
2840 }
2841
2842 /* split path into parts */
2843 parts = g_strsplit(path, "/", 0);
2844 part = parts[0];
2845
2846 /* get first item in model */
2847 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(settings_model), &iter);
2848
2849 /* iterate the parts of the path, trying to find to requested node */
2850 while (part != NULL) {
2851
2852 const gchar *node_id = NULL;
2853 #if 0
2854 debug_gtk3("checking column %d for '%s'.", column, part);
2855 #endif
2856
2857 /* iterate nodes until either 'part' is found or the nodes in the
2858 * current 'column' run out */
2859 while (TRUE) {
2860 gtk_tree_model_get(GTK_TREE_MODEL(settings_model), &iter,
2861 COLUMN_ID, &node_id, -1);
2862 #if 0
2863 debug_gtk3("got id '%s'.", node_id);
2864 #endif
2865
2866 /* check node ID against currently sought part of the path */
2867 if (strcmp(node_id, part) == 0) {
2868 /* got the requested node */
2869 #if 0
2870 debug_gtk3("FOUND SOMETHING!");
2871 #endif
2872 if (parts[column + 1] == NULL) {
2873 /* got final item */
2874
2875 GtkTreeSelection *selection;
2876 GtkTreePath *tree_path;
2877 #if 0
2878 debug_gtk3("GOT THE ITEM!");
2879 #endif
2880 selection = gtk_tree_view_get_selection(
2881 GTK_TREE_VIEW(settings_tree));
2882 tree_path = gtk_tree_model_get_path(
2883 GTK_TREE_MODEL(settings_model), &iter);
2884 gtk_tree_view_expand_to_path(
2885 GTK_TREE_VIEW(settings_tree), tree_path);
2886 gtk_tree_selection_select_path(selection, tree_path);
2887
2888 gtk_tree_path_free(tree_path);
2889 g_strfreev(parts);
2890 return TRUE;
2891 } else {
2892 /* continue searching, dive into the children of the
2893 * current node, if there are any */
2894 #if 0
2895 debug_gtk3("diving into child nodes of %s.", node_id);
2896 #endif
2897 if (gtk_tree_model_iter_has_child(
2898 GTK_TREE_MODEL(settings_model), &iter)) {
2899 /* node has children, iterate those now */
2900 GtkTreeIter child;
2901
2902 if (!gtk_tree_model_iter_nth_child(
2903 GTK_TREE_MODEL(settings_model),
2904 &child, &iter, 0)) {
2905 debug_gtk3("failed to get first child node.");
2906 g_strfreev(parts);
2907 return FALSE;
2908 }
2909 /* set iterator to first child node, update the index
2910 * in the path parts */
2911 iter = child;
2912 part = parts[++column];
2913 continue;
2914 } else {
2915 /* oops */
2916 debug_gtk3("error: path '%s' continues into '%s' but"
2917 " there are no child nodes.", path, part);
2918 g_strfreev(parts);
2919 return FALSE;
2920 }
2921 }
2922 } else {
2923 /* is there another node to inspect? */
2924 if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(settings_model),
2925 &iter)) {
2926 /* couldn't find the requested node, exit */
2927 debug_gtk3("failed to find node at path '%s'.", path);
2928 g_strfreev(parts);
2929 return FALSE;
2930 }
2931 }
2932 }
2933 }
2934
2935 debug_gtk3("warning: should never get here.");
2936 g_strfreev(parts);
2937 return FALSE;
2938 }
2939
2940
2941 /** \brief Threaded UI handler for the settings dialog constructor
2942 *
2943 * \param[in] user_data path to active node in the treeview
2944 *
2945 * \return FALSE
2946 */
ui_settings_dialog_create_and_activate_node_impl(gpointer user_data)2947 gboolean ui_settings_dialog_create_and_activate_node_impl(gpointer user_data)
2948 {
2949 const char *path = (const char *)user_data;
2950 GtkWidget *dialog;
2951
2952 dialog = dialog_create_helper();
2953 settings_window = dialog;
2954
2955 /* find and activate the node */
2956 if (path && !ui_settings_dialog_activate_node(path)) {
2957 debug_gtk3("failed to locate node, showing dialog anyway for now.");
2958 }
2959
2960 gtk_widget_show_all(dialog);
2961
2962 return FALSE;
2963 }
2964
2965
2966 /** \brief Show settings main dialog and activate a node
2967 *
2968 * \param[in] path NULL or path to name ("foo/bar/blah")
2969 *
2970 * \return TRUE which means nothing.
2971 */
ui_settings_dialog_create_and_activate_node(const char * path)2972 gboolean ui_settings_dialog_create_and_activate_node(const char *path)
2973 {
2974 /* call from ui thread without locking - creating the settings dialog is heavy */
2975 gdk_threads_add_timeout(0, ui_settings_dialog_create_and_activate_node_impl, (gpointer)path);
2976
2977 return TRUE;
2978 }
2979
2980
2981 /** \brief Menu callback for the settings dialog
2982 *
2983 * Opens the main settings dialog and activates the previously activate node,
2984 * if any.
2985 *
2986 * \param[in] widget unused
2987 * \param[in] user_data path to previously active node
2988 *
2989 * \return TRUE
2990 */
ui_settings_dialog_create_and_activate_node_callback(GtkWidget * widget,gpointer user_data)2991 gboolean ui_settings_dialog_create_and_activate_node_callback(
2992 GtkWidget *widget,
2993 gpointer user_data)
2994 {
2995 int pause_on_settings;
2996
2997 settings_old_pause_state = ui_pause_active();
2998
2999 resources_get_int("PauseOnSettings", &pause_on_settings);
3000 if (pause_on_settings) {
3001 ui_pause_enable();
3002 }
3003 ui_settings_dialog_create_and_activate_node((const char *)user_data);
3004
3005 return TRUE;
3006 }
3007