|
|
1.1 ! root 1: #!/usr/bin/env python ! 2: # ! 3: # Classes for the Hatari UI dialogs ! 4: # ! 5: # Copyright (C) 2008 by Eero Tamminen <[email protected]> ! 6: # ! 7: # This program is free software; you can redistribute it and/or modify ! 8: # it under the terms of the GNU General Public License as published by ! 9: # the Free Software Foundation; either version 2 of the License, or ! 10: # (at your option) any later version. ! 11: # ! 12: # This program is distributed in the hope that it will be useful, ! 13: # but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: # GNU General Public License for more details. ! 16: ! 17: import os ! 18: # use correct version of pygtk/gtk ! 19: import pygtk ! 20: pygtk.require('2.0') ! 21: import gtk ! 22: import pango ! 23: ! 24: from uihelpers import UInfo, HatariTextInsert, create_table_dialog, \ ! 25: table_add_entry_row, table_add_widget_row, table_add_separator, \ ! 26: create_button, FselEntry ! 27: ! 28: ! 29: # ----------------- ! 30: # Dialog base class ! 31: ! 32: class HatariUIDialog: ! 33: def __init__(self, parent): ! 34: "<any>Dialog(parent) -> object" ! 35: self.parent = parent ! 36: self.dialog = None ! 37: ! 38: def run(self): ! 39: """run() -> response. Shows dialog and returns response, ! 40: subclasses overriding run() require also an argument.""" ! 41: response = self.dialog.run() ! 42: self.dialog.hide() ! 43: return response ! 44: ! 45: ! 46: # --------------------------- ! 47: # Note/Todo/Error/Ask dialogs ! 48: ! 49: class NoteDialog(HatariUIDialog): ! 50: icontype = gtk.MESSAGE_INFO ! 51: textpattern = "\n%s" ! 52: def run(self, text): ! 53: "run(text), show message dialog with given text" ! 54: dialog = gtk.MessageDialog(self.parent, ! 55: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 56: self.icontype, gtk.BUTTONS_CLOSE, self.textpattern % text) ! 57: dialog.run() ! 58: dialog.destroy() ! 59: ! 60: class TodoDialog(NoteDialog): ! 61: textpattern = "\nTODO: %s" ! 62: ! 63: class ErrorDialog(NoteDialog): ! 64: icontype = gtk.MESSAGE_ERROR ! 65: textpattern = "\nERROR: %s" ! 66: ! 67: ! 68: class AskDialog(HatariUIDialog): ! 69: def run(self, text): ! 70: "run(text) -> bool, show question dialog and return True if user OKed it" ! 71: dialog = gtk.MessageDialog(self.parent, ! 72: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 73: gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, text) ! 74: response = dialog.run() ! 75: dialog.destroy() ! 76: return (response == gtk.RESPONSE_YES) ! 77: ! 78: ! 79: # --------------------------- ! 80: # About dialog ! 81: ! 82: class AboutDialog(HatariUIDialog): ! 83: def __init__(self, parent): ! 84: dialog = gtk.AboutDialog() ! 85: dialog.set_transient_for(parent) ! 86: dialog.set_name(UInfo.name) ! 87: dialog.set_version(UInfo.version) ! 88: dialog.set_website("http://hatari.berlios.de/") ! 89: dialog.set_website_label("Hatari emulator www-site") ! 90: dialog.set_authors(["Eero Tamminen"]) ! 91: dialog.set_artists(["The logo is from Hatari"]) ! 92: dialog.set_logo(gtk.gdk.pixbuf_new_from_file(UInfo.logo)) ! 93: dialog.set_translator_credits("translator-credits") ! 94: dialog.set_copyright("UI copyright (C) 2008 by Eero Tamminen") ! 95: dialog.set_license(""" ! 96: This software is licenced under GPL v2. ! 97: ! 98: You can see the whole license at: ! 99: http://www.gnu.org/licenses/info/GPLv2.html""") ! 100: self.dialog = dialog ! 101: ! 102: ! 103: # --------------------------- ! 104: # Input dialog ! 105: ! 106: class InputDialog(HatariUIDialog): ! 107: def __init__(self, parent): ! 108: dialog = gtk.Dialog("Key/mouse input", parent, ! 109: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 110: ("Close", gtk.RESPONSE_CLOSE)) ! 111: ! 112: tips = gtk.Tooltips() ! 113: entry = gtk.Entry() ! 114: entry.connect("activate", self._entry_cb) ! 115: insert = create_button("Insert", self._entry_cb) ! 116: tips.set_tip(insert, "Insert text to Hatari window") ! 117: ! 118: hbox1 = gtk.HBox() ! 119: hbox1.add(gtk.Label("Text:")) ! 120: hbox1.add(entry) ! 121: hbox1.add(insert) ! 122: dialog.vbox.add(hbox1) ! 123: ! 124: rclick = gtk.Button("Rightclick") ! 125: tips.set_tip(rclick, "Simulate Atari left button double-click") ! 126: rclick.connect("pressed", self._rightpress_cb) ! 127: rclick.connect("released", self._rightrelease_cb) ! 128: dclick = create_button("Doubleclick", self._doubleclick_cb) ! 129: tips.set_tip(dclick, "Simulate Atari rigth button click") ! 130: ! 131: hbox2 = gtk.HBox() ! 132: hbox2.add(rclick) ! 133: hbox2.add(dclick) ! 134: dialog.vbox.add(hbox2) ! 135: ! 136: dialog.show_all() ! 137: self.dialog = dialog ! 138: self.entry = entry ! 139: ! 140: def _entry_cb(self, widget): ! 141: text = self.entry.get_text() ! 142: if text: ! 143: HatariTextInsert(self.hatari, text) ! 144: self.entry.set_text("") ! 145: ! 146: def _doubleclick_cb(self, widget): ! 147: self.hatari.insert_event("doubleclick") ! 148: ! 149: def _rightpress_cb(self, widget): ! 150: self.hatari.insert_event("rightpress") ! 151: ! 152: def _rightrelease_cb(self, widget): ! 153: self.hatari.insert_event("rightrelease") ! 154: ! 155: def run(self, hatari): ! 156: "run(hatari), do text/mouse click input" ! 157: self.hatari = hatari ! 158: self.dialog.run() ! 159: self.dialog.hide() ! 160: ! 161: ! 162: # --------------------------- ! 163: # Quit and Save dialog ! 164: ! 165: class QuitSaveDialog(HatariUIDialog): ! 166: def __init__(self, parent): ! 167: dialog = gtk.Dialog("Quit and Save?", parent, ! 168: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 169: ("Save changes", gtk.RESPONSE_YES, ! 170: "Discard changes", gtk.RESPONSE_NO, ! 171: gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) ! 172: dialog.vbox.add(gtk.Label("You have unsaved configuration changes:")) ! 173: viewport = gtk.Viewport() ! 174: viewport.add(gtk.Label()) ! 175: scrolledwindow = gtk.ScrolledWindow() ! 176: scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) ! 177: scrolledwindow.add(viewport) ! 178: dialog.vbox.add(scrolledwindow) ! 179: dialog.show_all() ! 180: self.scrolledwindow = scrolledwindow ! 181: self.viewport = viewport ! 182: self.dialog = dialog ! 183: ! 184: def run(self, config): ! 185: "run(config) -> False if canceled, True otherwise or if no changes" ! 186: changes = [] ! 187: for key, value in config.get_changes(): ! 188: changes.append("%s = %s" % (key, str(value))) ! 189: if not changes: ! 190: return True ! 191: child = self.viewport.get_child() ! 192: child.set_text(config.get_path() + ":\n" + "\n".join(changes)) ! 193: width, height = child.get_size_request() ! 194: if height < 320: ! 195: self.scrolledwindow.set_size_request(width, height) ! 196: else: ! 197: self.scrolledwindow.set_size_request(-1, 320) ! 198: self.viewport.show_all() ! 199: ! 200: response = self.dialog.run() ! 201: self.dialog.hide() ! 202: if response == gtk.RESPONSE_CANCEL: ! 203: return False ! 204: if response == gtk.RESPONSE_YES: ! 205: config.save() ! 206: return True ! 207: ! 208: ! 209: # --------------------------- ! 210: # Kill Hatari dialog ! 211: ! 212: class KillDialog(HatariUIDialog): ! 213: def __init__(self, parent): ! 214: self.dialog = gtk.MessageDialog(parent, ! 215: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 216: gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, ! 217: """\ ! 218: Hatari emulator is already/still running and it needs to be terminated first. However, if it contains unsaved data, that will be lost. ! 219: ! 220: Terminate Hatari anyway?""") ! 221: ! 222: def run(self, hatari): ! 223: "run(hatari) -> True if Hatari killed, False if left running" ! 224: if not hatari.is_running(): ! 225: return True ! 226: # Hatari is running, OK to kill? ! 227: response = self.dialog.run() ! 228: self.dialog.hide() ! 229: if response == gtk.RESPONSE_OK: ! 230: hatari.kill() ! 231: return True ! 232: return False ! 233: ! 234: ! 235: # --------------------------- ! 236: # Reset Hatari dialog ! 237: ! 238: class ResetDialog(HatariUIDialog): ! 239: COLD = 1 ! 240: WARM = 2 ! 241: def __init__(self, parent): ! 242: self.dialog = gtk.Dialog("Reset Atari?", parent, ! 243: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 244: ("Cold reset", self.COLD, "Warm reset", self.WARM, ! 245: gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) ! 246: label = gtk.Label("\nRebooting will lose changes in currently\nrunning Atari programs.\n\nReset anyway?\n") ! 247: self.dialog.vbox.add(label) ! 248: label.show() ! 249: ! 250: def run(self, hatari): ! 251: "run(hatari) -> True if Hatari rebooted, False if canceled" ! 252: if not hatari.is_running(): ! 253: return False ! 254: # Hatari is running, how to reboot? ! 255: response = self.dialog.run() ! 256: self.dialog.hide() ! 257: if response == self.COLD: ! 258: hatari.trigger_shortcut("coldreset") ! 259: elif response == self.WARM: ! 260: hatari.trigger_shortcut("warmreset") ! 261: else: ! 262: return False ! 263: return True ! 264: ! 265: ! 266: # ---------------------------------- ! 267: # Floppy image dialog ! 268: ! 269: class DiskDialog(HatariUIDialog): ! 270: def _create_dialog(self, config): ! 271: table, self.dialog = create_table_dialog(self.parent, "Floppy images", 9) ! 272: ! 273: row = 0 ! 274: self.floppy = [] ! 275: path = config.get_floppydir() ! 276: for drive in ("A", "B"): ! 277: label = "Disk %c:" % drive ! 278: fsel = gtk.FileChooserButton(label) ! 279: # Hatari cannot access URIs ! 280: fsel.set_local_only(True) ! 281: fsel.set_width_chars(12) ! 282: filename = config.get_floppy(row) ! 283: if filename: ! 284: fsel.set_filename(filename) ! 285: elif path: ! 286: fsel.set_current_folder(path) ! 287: self.floppy.append(fsel) ! 288: ! 289: eject = create_button("Eject", self._eject, fsel) ! 290: box = gtk.HBox() ! 291: box.pack_start(fsel) ! 292: box.pack_start(eject, False, False) ! 293: table_add_widget_row(table, row, label, box) ! 294: row += 1 ! 295: ! 296: table.show_all() ! 297: ! 298: def _eject(self, widget, fsel): ! 299: fsel.unselect_all() ! 300: ! 301: def run(self, config): ! 302: "run(config), show disk image dialog" ! 303: if not self.dialog: ! 304: self._create_dialog(config) ! 305: response = self.dialog.run() ! 306: self.dialog.hide() ! 307: ! 308: if response == gtk.RESPONSE_APPLY: ! 309: config.lock_updates() ! 310: for drive in range(2): ! 311: config.set_floppy(drive, self.floppy[drive].get_filename()) ! 312: config.flush_updates() ! 313: ! 314: ! 315: # --------------------------- ! 316: # Display dialog ! 317: ! 318: class DisplayDialog(HatariUIDialog): ! 319: ! 320: def _create_dialog(self, config): ! 321: tips = gtk.Tooltips() ! 322: ! 323: skip = gtk.combo_box_new_text() ! 324: for text in config.get_frameskip_names(): ! 325: skip.append_text(text) ! 326: skip.set_active(config.get_frameskip()) ! 327: tips.set_tip(skip, "Set how many frames are skipped") ! 328: ! 329: zoom = gtk.CheckButton("Zoom ST-low") ! 330: zoom.set_active(config.get_zoom()) ! 331: tips.set_tip(zoom, "Whether to double ST-low resolution") ! 332: ! 333: borders = gtk.CheckButton("Borders") ! 334: borders.set_active(config.get_borders()) ! 335: tips.set_tip(borders, "Whether to show overscan borders in low/mid-rez") ! 336: ! 337: spec512 = gtk.CheckButton("Spec512") ! 338: spec512.set_active(config.get_spec512threshold()) ! 339: tips.set_tip(spec512, "Whether to support Spec512 (>16 colors at the same time)") ! 340: ! 341: statusbar = gtk.CheckButton("Statusbar") ! 342: statusbar.set_active(config.get_statusbar()) ! 343: tips.set_tip(statusbar, "Whether to show statusbar with floppy leds etc") ! 344: ! 345: led = gtk.CheckButton("Overlay led") ! 346: led.set_active(config.get_led()) ! 347: tips.set_tip(led, "Whether to show overlay drive led when statusbar isn't visible") ! 348: ! 349: dialog = gtk.Dialog("Display settings", self.parent, ! 350: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 351: (gtk.STOCK_APPLY, gtk.RESPONSE_APPLY, ! 352: gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) ! 353: ! 354: dialog.vbox.add(gtk.Label("Frameskip:")) ! 355: dialog.vbox.add(skip) ! 356: dialog.vbox.add(zoom) ! 357: dialog.vbox.add(borders) ! 358: dialog.vbox.add(spec512) ! 359: dialog.vbox.add(statusbar) ! 360: dialog.vbox.add(led) ! 361: dialog.vbox.show_all() ! 362: ! 363: self.dialog = dialog ! 364: self.skip = skip ! 365: self.zoom = zoom ! 366: self.borders = borders ! 367: self.spec512 = spec512 ! 368: self.statusbar = statusbar ! 369: self.led = led ! 370: ! 371: def run(self, config): ! 372: "run(config), show display dialog" ! 373: if not self.dialog: ! 374: self._create_dialog(config) ! 375: response = self.dialog.run() ! 376: self.dialog.hide() ! 377: if response == gtk.RESPONSE_APPLY: ! 378: config.lock_updates() ! 379: config.set_frameskip(self.skip.get_active()) ! 380: config.set_zoom(self.zoom.get_active()) ! 381: config.set_borders(self.borders.get_active()) ! 382: config.set_spec512threshold(self.spec512.get_active()) ! 383: config.set_statusbar(self.statusbar.get_active()) ! 384: config.set_led(self.led.get_active()) ! 385: config.flush_updates() ! 386: ! 387: ! 388: # ---------------------------------- ! 389: # Joystick dialog ! 390: ! 391: class JoystickDialog(HatariUIDialog): ! 392: def _create_dialog(self, config): ! 393: table, self.dialog = create_table_dialog(self.parent, "Joystick settings", 9) ! 394: ! 395: joy = 0 ! 396: self.joy = [] ! 397: joytypes = config.get_joystick_types() ! 398: for label in config.get_joystick_names(): ! 399: combo = gtk.combo_box_new_text() ! 400: for text in joytypes: ! 401: combo.append_text(text) ! 402: combo.set_active(config.get_joystick(joy)) ! 403: widget = table_add_widget_row(table, joy, "%s:" % label, combo) ! 404: self.joy.append(widget) ! 405: joy += 1 ! 406: ! 407: table.show_all() ! 408: ! 409: def run(self, config): ! 410: "run(config), show joystick dialog" ! 411: if not self.dialog: ! 412: self._create_dialog(config) ! 413: response = self.dialog.run() ! 414: self.dialog.hide() ! 415: ! 416: if response == gtk.RESPONSE_APPLY: ! 417: config.lock_updates() ! 418: for joy in range(6): ! 419: config.set_joystick(joy, self.joy[joy].get_active()) ! 420: config.flush_updates() ! 421: ! 422: ! 423: # --------------------------------------- ! 424: # Peripherals (midi,printer,rs232) dialog ! 425: ! 426: class PeripheralDialog(HatariUIDialog): ! 427: def _create_dialog(self, config): ! 428: midi = gtk.CheckButton("Enable MIDI") ! 429: midi.set_active(config.get_midi()) ! 430: ! 431: printer = gtk.CheckButton("Enable printer output") ! 432: printer.set_active(config.get_printer()) ! 433: ! 434: rs232 = gtk.CheckButton("Enable RS232") ! 435: rs232.set_active(config.get_rs232()) ! 436: ! 437: dialog = gtk.Dialog("Peripherals", self.parent, ! 438: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 439: (gtk.STOCK_APPLY, gtk.RESPONSE_APPLY, ! 440: gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) ! 441: dialog.vbox.add(midi) ! 442: dialog.vbox.add(printer) ! 443: dialog.vbox.add(rs232) ! 444: dialog.vbox.show_all() ! 445: ! 446: self.dialog = dialog ! 447: self.printer = printer ! 448: self.rs232 = rs232 ! 449: self.midi = midi ! 450: ! 451: def run(self, config): ! 452: "run(config), show peripherals dialog" ! 453: if not self.dialog: ! 454: self._create_dialog(config) ! 455: response = self.dialog.run() ! 456: self.dialog.hide() ! 457: ! 458: if response == gtk.RESPONSE_APPLY: ! 459: config.lock_updates() ! 460: config.set_midi(self.midi.get_active()) ! 461: config.set_printer(self.printer.get_active()) ! 462: config.set_rs232(self.rs232.get_active()) ! 463: config.flush_updates() ! 464: ! 465: ! 466: # --------------------------------------- ! 467: # Path dialog ! 468: ! 469: class PathDialog(HatariUIDialog): ! 470: def _create_dialog(self, config): ! 471: paths = config.get_paths() ! 472: table, self.dialog = create_table_dialog(self.parent, "File path settings", len(paths)) ! 473: paths.sort() ! 474: row = 0 ! 475: self.paths = [] ! 476: for (key, path, label) in paths: ! 477: fsel = FselEntry(self.dialog, self._validate_fname, key) ! 478: fsel.set_filename(path) ! 479: self.paths.append((key, fsel)) ! 480: table_add_widget_row(table, row, label, fsel.get_container()) ! 481: row += 1 ! 482: table.show_all() ! 483: ! 484: def _validate_fname(self, key, fname): ! 485: if key != "soundout": ! 486: return True ! 487: if fname.rsplit(".", 1)[-1].lower() in ("ym", "wav"): ! 488: return True ! 489: ErrorDialog(self.dialog).run("Sound output file name:\n\t%s\nneeds to end with '.ym' or '.wav'." % fname) ! 490: return False ! 491: ! 492: def run(self, config): ! 493: "run(config), show paths dialog" ! 494: if not self.dialog: ! 495: self._create_dialog(config) ! 496: response = self.dialog.run() ! 497: self.dialog.hide() ! 498: ! 499: if response == gtk.RESPONSE_APPLY: ! 500: paths = [] ! 501: for key, fsel in self.paths: ! 502: paths.append((key, fsel.get_filename())) ! 503: config.set_paths(paths) ! 504: ! 505: ! 506: # --------------------------- ! 507: # Sound dialog ! 508: ! 509: class SoundDialog(HatariUIDialog): ! 510: ! 511: def _create_dialog(self, config): ! 512: combo = gtk.combo_box_entry_new_text() ! 513: for text in config.get_sound_values(): ! 514: combo.append_text(text) ! 515: enabled, hz = config.get_sound() ! 516: self.enabled = gtk.CheckButton("Sound enabled") ! 517: self.enabled.set_active(enabled) ! 518: combo.child.set_text(hz) ! 519: box = gtk.HBox() ! 520: box.pack_start(gtk.Label("Sound frequency:"), False, False) ! 521: box.add(combo) ! 522: self.sound = combo.child ! 523: ! 524: dialog = gtk.Dialog("Sound settings", self.parent, ! 525: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 526: (gtk.STOCK_APPLY, gtk.RESPONSE_APPLY, ! 527: gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) ! 528: dialog.vbox.add(self.enabled) ! 529: dialog.vbox.add(box) ! 530: dialog.vbox.show_all() ! 531: self.dialog = dialog ! 532: ! 533: def run(self, config): ! 534: "run(config), show sound dialog" ! 535: if not self.dialog: ! 536: self._create_dialog(config) ! 537: response = self.dialog.run() ! 538: self.dialog.hide() ! 539: if response == gtk.RESPONSE_APPLY: ! 540: enabled = self.enabled.get_active() ! 541: hz1 = self.sound.get_text() ! 542: hz2 = config.set_sound(enabled, hz1) ! 543: if hz2 != hz1: ! 544: self.sound.set_text(hz2) ! 545: ! 546: ! 547: # --------------------------- ! 548: # Trace settings dialog ! 549: ! 550: class TraceDialog(HatariUIDialog): ! 551: # you can get this list with: ! 552: # hatari --trace help 2>&1|awk '/all$/{next} /^ [^-]/ {printf("\"%s\",\n", $1)}' ! 553: tracepoints = [ ! 554: "video_sync", ! 555: "video_res", ! 556: "video_color", ! 557: "video_border_v", ! 558: "video_border_h", ! 559: "video_addr", ! 560: "video_hbl", ! 561: "video_vbl", ! 562: "video_ste", ! 563: "mfp_exception", ! 564: "mfp_start", ! 565: "mfp_read", ! 566: "mfp_write", ! 567: "psg_write_reg", ! 568: "psg_write_data", ! 569: "cpu_pairing", ! 570: "cpu_disasm", ! 571: "cpu_exception", ! 572: "int", ! 573: "fdc", ! 574: "ikbd_cmds", ! 575: "ikbd_acia", ! 576: "ikbd_exec", ! 577: "blitter", ! 578: "bios", ! 579: "xbios", ! 580: "gemdos", ! 581: "vdi", ! 582: "io_read", ! 583: "io_write", ! 584: "dmasound" ! 585: ] ! 586: def __init__(self, parent): ! 587: self.savedpoints = "none" ! 588: hbox1 = gtk.HBox() ! 589: hbox1.add(create_button("Load", self._load_traces)) ! 590: hbox1.add(create_button("Clear", self._clear_traces)) ! 591: hbox1.add(create_button("Save", self._save_traces)) ! 592: hbox2 = gtk.HBox() ! 593: vboxes = [] ! 594: for idx in (0,1,2): ! 595: vboxes.append(gtk.VBox()) ! 596: hbox2.add(vboxes[idx]) ! 597: ! 598: count = 0 ! 599: per_side = (len(self.tracepoints)+2)/3 ! 600: self.tracewidgets = {} ! 601: for trace in self.tracepoints: ! 602: trace = trace.replace("_", "-") ! 603: widget = gtk.CheckButton(trace) ! 604: self.tracewidgets[trace] = widget ! 605: vboxes[count/per_side].pack_start(widget, False, True) ! 606: count += 1 ! 607: ! 608: dialog = gtk.Dialog("Trace settings", parent, ! 609: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ! 610: (gtk.STOCK_APPLY, gtk.RESPONSE_APPLY, ! 611: gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) ! 612: dialog.vbox.add(hbox1) ! 613: dialog.vbox.add(gtk.Label("Select trace points:")) ! 614: dialog.vbox.add(hbox2) ! 615: dialog.vbox.show_all() ! 616: self.dialog = dialog ! 617: ! 618: def _get_traces(self): ! 619: traces = [] ! 620: for trace in self.tracepoints: ! 621: if self.tracewidgets[trace].get_active(): ! 622: traces.append(trace) ! 623: if traces: ! 624: return ",".join(traces) ! 625: return "none" ! 626: ! 627: def _set_traces(self, tracepoints): ! 628: self._clear_traces() ! 629: for trace in tracepoints.split(","): ! 630: if trace in self.tracewidgets: ! 631: self.tracewidgets[trace].set_active(True) ! 632: else: ! 633: print "ERROR: unknown trace setting '%s'" % trace ! 634: ! 635: def _clear_traces(self, widget = None): ! 636: for trace in self.tracepoints: ! 637: self.tracewidgets[trace].set_active(False) ! 638: ! 639: def _load_traces(self, widget): ! 640: # this doesn't load traces, just sets them from internal variable ! 641: # that run method gets from caller and sets. It's up to caller ! 642: # whether the saving or loading happens actually to disk ! 643: self._set_traces(self.savedpoints) ! 644: ! 645: def _save_traces(self, widget): ! 646: self.savedpoints = self._get_traces() ! 647: ! 648: def run(self, hatari, savedpoints): ! 649: "run(hatari,tracepoints) -> tracepoints, caller saves tracepoints" ! 650: self.savedpoints = savedpoints ! 651: while 1: ! 652: response = self.dialog.run() ! 653: if response == gtk.RESPONSE_APPLY: ! 654: hatari.change_option("--trace %s" % self._get_traces()) ! 655: else: ! 656: self.dialog.hide() ! 657: return self.savedpoints ! 658: ! 659: ! 660: # ------------------------------------------ ! 661: # Machine dialog for settings needing reboot ! 662: ! 663: class MachineDialog(HatariUIDialog): ! 664: def _create_dialog(self, config): ! 665: table, self.dialog = create_table_dialog(self.parent, "Machine configuration", 9, "Set and reboot") ! 666: ! 667: row = 0 ! 668: combo = gtk.combo_box_new_text() ! 669: for text in config.get_machine_types(): ! 670: combo.append_text(text) ! 671: self.machine = table_add_widget_row(table, row, "Machine type:", combo) ! 672: row += 1 ! 673: ! 674: combo = gtk.combo_box_new_text() ! 675: for text in config.get_monitor_types(): ! 676: combo.append_text(text) ! 677: self.monitor = table_add_widget_row(table, row, "Monitor type:", combo) ! 678: row += 1 ! 679: ! 680: combo = gtk.combo_box_new_text() ! 681: for text in config.get_memory_names(): ! 682: combo.append_text(text) ! 683: self.memory = table_add_widget_row(table, row, "Memory size:", combo) ! 684: row += 1 ! 685: ! 686: label = "TOS image:" ! 687: fsel = self._fsel(label, gtk.FILE_CHOOSER_ACTION_OPEN) ! 688: self.tos = table_add_widget_row(table, row, label, fsel) ! 689: row += 1 ! 690: ! 691: label = "Harddisk:" ! 692: fsel = self._fsel(label, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) ! 693: self.harddisk = table_add_widget_row(table, row, label, fsel) ! 694: row += 1 ! 695: ! 696: widget = gtk.CheckButton("Use harddisk") ! 697: self.usehd = table_add_widget_row(table, row, None, widget) ! 698: row += 1 ! 699: ! 700: widget = gtk.CheckButton("Compatible CPU") ! 701: self.compatible = table_add_widget_row(table, row, None, widget) ! 702: row += 1 ! 703: ! 704: widget = gtk.CheckButton("Patch Timer-D") ! 705: self.timerd = table_add_widget_row(table, row, None, widget) ! 706: row += 1 ! 707: ! 708: table.show_all() ! 709: ! 710: def _fsel(self, label, action): ! 711: fsel = gtk.FileChooserButton(label) ! 712: # Hatari cannot access URIs ! 713: fsel.set_local_only(True) ! 714: fsel.set_width_chars(12) ! 715: fsel.set_action(action) ! 716: return fsel ! 717: ! 718: def _get_config(self, config): ! 719: self.machine.set_active(config.get_machine()) ! 720: self.monitor.set_active(config.get_monitor()) ! 721: self.memory.set_active(config.get_memory()) ! 722: tos = config.get_tos() ! 723: hd = config.get_harddisk() ! 724: usehd = config.get_use_harddisk() ! 725: if tos: ! 726: self.tos.set_filename(tos) ! 727: if hd: ! 728: self.harddisk.set_filename(hd) ! 729: if usehd: ! 730: self.usehd.set_active(usehd) ! 731: self.compatible.set_active(config.get_compatible()) ! 732: self.timerd.set_active(config.get_timerd()) ! 733: ! 734: def _set_config(self, config): ! 735: config.lock_updates() ! 736: config.set_machine(self.machine.get_active()) ! 737: config.set_monitor(self.monitor.get_active()) ! 738: config.set_memory(self.memory.get_active()) ! 739: config.set_tos(self.tos.get_filename()) ! 740: # usehd has to be before before harddisk ! 741: config.set_use_harddisk(self.usehd.get_active()) ! 742: config.set_harddisk(self.harddisk.get_filename()) ! 743: config.set_compatible(self.compatible.get_active()) ! 744: config.set_timerd(self.timerd.get_active()) ! 745: config.flush_updates() ! 746: ! 747: def run(self, config): ! 748: "run(config) -> bool, whether to reboot" ! 749: if not self.dialog: ! 750: self._create_dialog(config) ! 751: ! 752: self._get_config(config) ! 753: response = self.dialog.run() ! 754: self.dialog.hide() ! 755: if response == gtk.RESPONSE_APPLY: ! 756: self._set_config(config) ! 757: return True ! 758: return False
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.