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