Annotation of hatari/python-ui/dialogs.py, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.