Annotation of previous/python-ui/dialogs.py, revision 1.1

1.1     ! root        1: #!/usr/bin/env python
        !             2: #
        !             3: # Classes for the Hatari UI dialogs
        !             4: #
        !             5: # Copyright (C) 2008-2010 by Eero Tamminen <eerot at berlios>
        !             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:      table_add_radio_rows, table_set_col_offset, 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:     button = gtk.BUTTONS_OK
        !            51:     icontype = gtk.MESSAGE_INFO
        !            52:     textpattern = "\n%s"
        !            53:     def run(self, text):
        !            54:         "run(text), show message dialog with given text"
        !            55:         dialog = gtk.MessageDialog(self.parent,
        !            56:         gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !            57:         self.icontype, self.button, self.textpattern % text)
        !            58:         dialog.run()
        !            59:         dialog.destroy()
        !            60: 
        !            61: class TodoDialog(NoteDialog):
        !            62:     textpattern = "\nTODO: %s"
        !            63: 
        !            64: class ErrorDialog(NoteDialog):
        !            65:     button = gtk.BUTTONS_CLOSE
        !            66:     icontype = gtk.MESSAGE_ERROR
        !            67:     textpattern = "\nERROR: %s"
        !            68: 
        !            69: 
        !            70: class AskDialog(HatariUIDialog):
        !            71:     def run(self, text):
        !            72:         "run(text) -> bool, show question dialog and return True if user OKed it"
        !            73:         dialog = gtk.MessageDialog(self.parent,
        !            74:         gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !            75:         gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, text)
        !            76:         response = dialog.run()
        !            77:         dialog.destroy()
        !            78:         return (response == gtk.RESPONSE_YES)
        !            79: 
        !            80: 
        !            81: # ---------------------------
        !            82: # About dialog
        !            83: 
        !            84: class AboutDialog(HatariUIDialog):
        !            85:     def __init__(self, parent):
        !            86:         dialog = gtk.AboutDialog()
        !            87:         dialog.set_transient_for(parent)
        !            88:         dialog.set_name(UInfo.name)
        !            89:         dialog.set_version(UInfo.version)
        !            90:         dialog.set_website("http://hatari.berlios.de/")
        !            91:         dialog.set_website_label("Hatari emulator www-site")
        !            92:         dialog.set_authors(["Eero Tamminen"])
        !            93:         dialog.set_artists(["The logo is from Hatari"])
        !            94:         dialog.set_logo(gtk.gdk.pixbuf_new_from_file(UInfo.logo))
        !            95:         dialog.set_translator_credits("translator-credits")
        !            96:         dialog.set_copyright(UInfo.copyright)
        !            97:         dialog.set_license("""
        !            98: This software is licenced under GPL v2 or later.
        !            99: 
        !           100: You can see the whole license at:
        !           101:     http://www.gnu.org/licenses/info/GPLv2.html""")
        !           102:         self.dialog = dialog
        !           103: 
        !           104: 
        !           105: # ---------------------------
        !           106: # Input dialog
        !           107: 
        !           108: class InputDialog(HatariUIDialog):
        !           109:     def __init__(self, parent):
        !           110:         dialog = gtk.Dialog("Key/mouse input", parent,
        !           111:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           112:             ("Close", gtk.RESPONSE_CLOSE))
        !           113:         
        !           114:         tips = gtk.Tooltips()
        !           115:         entry = gtk.Entry()
        !           116:         entry.connect("activate", self._entry_cb)
        !           117:         insert = create_button("Insert", self._entry_cb)
        !           118:         tips.set_tip(insert, "Insert text to Hatari window")
        !           119: 
        !           120:         hbox1 = gtk.HBox()
        !           121:         hbox1.add(gtk.Label("Text:"))
        !           122:         hbox1.add(entry)
        !           123:         hbox1.add(insert)
        !           124:         dialog.vbox.add(hbox1)
        !           125: 
        !           126:         rclick = gtk.Button("Rightclick")
        !           127:         tips.set_tip(rclick, "Simulate Atari left button double-click")
        !           128:         rclick.connect("pressed", self._rightpress_cb)
        !           129:         rclick.connect("released", self._rightrelease_cb)
        !           130:         dclick = create_button("Doubleclick", self._doubleclick_cb)
        !           131:         tips.set_tip(dclick, "Simulate Atari rigth button click")
        !           132: 
        !           133:         hbox2 = gtk.HBox()
        !           134:         hbox2.add(rclick)
        !           135:         hbox2.add(dclick)
        !           136:         dialog.vbox.add(hbox2)
        !           137: 
        !           138:         dialog.show_all()
        !           139:         self.dialog = dialog
        !           140:         self.entry = entry
        !           141:     
        !           142:     def _entry_cb(self, widget):
        !           143:         text = self.entry.get_text()
        !           144:         if text:
        !           145:             HatariTextInsert(self.hatari, text)
        !           146:             self.entry.set_text("")
        !           147: 
        !           148:     def _doubleclick_cb(self, widget):
        !           149:         self.hatari.insert_event("doubleclick")
        !           150: 
        !           151:     def _rightpress_cb(self, widget):
        !           152:         self.hatari.insert_event("rightpress")
        !           153: 
        !           154:     def _rightrelease_cb(self, widget):
        !           155:         self.hatari.insert_event("rightrelease")
        !           156: 
        !           157:     def run(self, hatari):
        !           158:         "run(hatari), do text/mouse click input"
        !           159:         self.hatari = hatari
        !           160:         self.dialog.run()
        !           161:         self.dialog.hide()
        !           162: 
        !           163: 
        !           164: # ---------------------------
        !           165: # Quit and Save dialog
        !           166: 
        !           167: class QuitSaveDialog(HatariUIDialog):
        !           168:     def __init__(self, parent):
        !           169:         dialog = gtk.Dialog("Quit and Save?", parent,
        !           170:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           171:             ("Save changes",    gtk.RESPONSE_YES,
        !           172:              "Discard changes", gtk.RESPONSE_NO,
        !           173:              gtk.STOCK_CANCEL,  gtk.RESPONSE_CANCEL))
        !           174:         dialog.vbox.add(gtk.Label("You have unsaved configuration changes:"))
        !           175:         viewport = gtk.Viewport()
        !           176:         viewport.add(gtk.Label())
        !           177:         scrolledwindow = gtk.ScrolledWindow()
        !           178:         scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        !           179:         scrolledwindow.add(viewport)
        !           180:         dialog.vbox.add(scrolledwindow)
        !           181:         dialog.show_all()
        !           182:         self.scrolledwindow = scrolledwindow
        !           183:         self.viewport = viewport
        !           184:         self.dialog = dialog
        !           185:         
        !           186:     def run(self, config):
        !           187:         "run(config) -> False if canceled, True otherwise or if no changes"
        !           188:         changes = []
        !           189:         for key, value in config.get_changes():
        !           190:             changes.append("%s = %s" % (key, str(value)))
        !           191:         if not changes:
        !           192:             return True
        !           193:         child = self.viewport.get_child()
        !           194:         child.set_text(config.get_path() + ":\n" + "\n".join(changes))
        !           195:         width, height = child.get_size_request()
        !           196:         if height < 320:
        !           197:             self.scrolledwindow.set_size_request(width, height)
        !           198:         else:
        !           199:             self.scrolledwindow.set_size_request(-1, 320)
        !           200:         self.viewport.show_all()
        !           201:         
        !           202:         response = self.dialog.run()
        !           203:         self.dialog.hide()
        !           204:         if response == gtk.RESPONSE_CANCEL:
        !           205:             return False
        !           206:         if response == gtk.RESPONSE_YES:
        !           207:             config.save()
        !           208:         return True
        !           209: 
        !           210: 
        !           211: # ---------------------------
        !           212: # Kill Hatari dialog
        !           213: 
        !           214: class KillDialog(HatariUIDialog):
        !           215:     def __init__(self, parent):
        !           216:         self.dialog = gtk.MessageDialog(parent,
        !           217:         gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           218:         gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL,
        !           219:         """\
        !           220: Hatari emulator is already/still running and it needs to be terminated first. However, if it contains unsaved data, that will be lost.
        !           221: 
        !           222: Terminate Hatari anyway?""")
        !           223: 
        !           224:     def run(self, hatari):
        !           225:         "run(hatari) -> True if Hatari killed, False if left running"
        !           226:         if not hatari.is_running():
        !           227:             return True
        !           228:         # Hatari is running, OK to kill?
        !           229:         response = self.dialog.run()
        !           230:         self.dialog.hide()
        !           231:         if response == gtk.RESPONSE_OK:
        !           232:             hatari.kill()
        !           233:             return True
        !           234:         return False
        !           235: 
        !           236:     
        !           237: # ---------------------------
        !           238: # Reset Hatari dialog
        !           239: 
        !           240: class ResetDialog(HatariUIDialog):
        !           241:     COLD = 1
        !           242:     WARM = 2
        !           243:     def __init__(self, parent):
        !           244:         self.dialog = gtk.Dialog("Reset Atari?", parent,
        !           245:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           246:             ("Cold reset", self.COLD, "Warm reset", self.WARM,
        !           247:              gtk.STOCK_CANCEL,  gtk.RESPONSE_CANCEL))
        !           248:         label = gtk.Label("\nRebooting will lose changes in currently\nrunning Atari programs.\n\nReset anyway?\n")
        !           249:         self.dialog.vbox.add(label)
        !           250:         label.show()
        !           251: 
        !           252:     def run(self, hatari):
        !           253:         "run(hatari) -> True if Hatari rebooted, False if canceled"
        !           254:         if not hatari.is_running():
        !           255:             return False
        !           256:         # Hatari is running, how to reboot?
        !           257:         response = self.dialog.run()
        !           258:         self.dialog.hide()
        !           259:         if response == self.COLD:
        !           260:             hatari.trigger_shortcut("coldreset")
        !           261:         elif response == self.WARM:
        !           262:             hatari.trigger_shortcut("warmreset")
        !           263:         else:
        !           264:             return False
        !           265:         return True
        !           266: 
        !           267: 
        !           268: # ----------------------------------
        !           269: # Floppy image dialog
        !           270: 
        !           271: class FloppyDialog(HatariUIDialog):
        !           272:     def _create_dialog(self, config):
        !           273:         table, self.dialog = create_table_dialog(self.parent, "Floppy images", 4, 2)
        !           274: 
        !           275:         row = 0
        !           276:         self.floppy = []
        !           277:         path = config.get_floppydir()
        !           278:         for drive in ("A", "B"):
        !           279:             label = "Disk %c:" % drive
        !           280:             fsel = gtk.FileChooserButton(label)
        !           281:             # Hatari cannot access URIs
        !           282:             fsel.set_local_only(True)
        !           283:             fsel.set_width_chars(12)
        !           284:             filename = config.get_floppy(row)
        !           285:             if filename:
        !           286:                 fsel.set_filename(filename)
        !           287:             elif path:
        !           288:                 fsel.set_current_folder(path)
        !           289:             self.floppy.append(fsel)
        !           290:             
        !           291:             eject = create_button("Eject", self._eject, fsel)
        !           292:             box = gtk.HBox()
        !           293:             box.pack_start(fsel)
        !           294:             box.pack_start(eject, False, False)
        !           295:             table_add_widget_row(table, row, label, box)
        !           296:             row += 1
        !           297: 
        !           298:         tips = gtk.Tooltips()
        !           299: 
        !           300:         protect = gtk.combo_box_new_text()
        !           301:         for text in config.get_protection_types():
        !           302:             protect.append_text(text)
        !           303:         protect.set_active(config.get_floppy_protection())
        !           304:         tips.set_tip(protect, "Write protect floppy image contents")
        !           305:         table_add_widget_row(table, row, "Write protection:", protect)
        !           306: 
        !           307:         row += 1
        !           308:         slowfdc = gtk.CheckButton("Slow floppy access")
        !           309:         slowfdc.set_active(config.get_slowfdc())
        !           310:         tips.set_tip(slowfdc, "May be required by some rare game/demo")
        !           311:         table_add_widget_row(table, row, None, slowfdc)
        !           312: 
        !           313:         table.show_all()
        !           314: 
        !           315:         self.protect = protect
        !           316:         self.slowfdc = slowfdc
        !           317: 
        !           318:     def _eject(self, widget, fsel):
        !           319:         fsel.unselect_all()
        !           320:     
        !           321:     def run(self, config):
        !           322:         "run(config), show disk image dialog"
        !           323:         if not self.dialog:
        !           324:             self._create_dialog(config)
        !           325:         response = self.dialog.run()
        !           326:         self.dialog.hide()
        !           327:         
        !           328:         if response == gtk.RESPONSE_APPLY:
        !           329:             config.lock_updates()
        !           330:             for drive in range(2):
        !           331:                 config.set_floppy(drive, self.floppy[drive].get_filename())
        !           332:             config.set_hd_protection(self.protect.get_active())
        !           333:             config.set_slowfdc(self.slowfdc.get_active())
        !           334:             config.flush_updates()
        !           335: 
        !           336: 
        !           337: # ----------------------------------
        !           338: # Hard disk dialog
        !           339: 
        !           340: class HardDiskDialog(HatariUIDialog):
        !           341:     def _create_dialog(self, config):
        !           342:         table, self.dialog = create_table_dialog(self.parent, "Hard disks", 4, 4, "Set and reboot")
        !           343:         row = 0
        !           344: 
        !           345:         label = "ASCI HD image:"
        !           346:         path = config.get_acsi_image()
        !           347:         fsel, box = self._fsel_box(label, path, gtk.FILE_CHOOSER_ACTION_OPEN)
        !           348:         table_add_widget_row(table, row, label, box, True)
        !           349:         self.acsi = fsel
        !           350:         row += 1
        !           351: 
        !           352:         label = "IDE HD master image:"
        !           353:         path = config.get_idemaster_image()
        !           354:         fsel, box = self._fsel_box(label, path, gtk.FILE_CHOOSER_ACTION_OPEN)
        !           355:         table_add_widget_row(table, row, label, box, True)
        !           356:         self.idemaster = fsel
        !           357:         row += 1
        !           358: 
        !           359:         label = "IDE HD slave image:"
        !           360:         path = config.get_ideslave_image()
        !           361:         fsel, box = self._fsel_box(label, path, gtk.FILE_CHOOSER_ACTION_OPEN)
        !           362:         table_add_widget_row(table, row, label, box, True)
        !           363:         self.ideslave = fsel
        !           364:         row += 1
        !           365:         
        !           366:         label = "GEMDOS drive directory:"
        !           367:         path = config.get_gemdos_dir()
        !           368:         fsel, box = self._fsel_box(label, path, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
        !           369:         table_add_widget_row(table, row, label, box, True)
        !           370:         self.gemdos = fsel
        !           371:         row += 1
        !           372: 
        !           373:         tips = gtk.Tooltips()
        !           374: 
        !           375:         protect = gtk.combo_box_new_text()
        !           376:         for text in config.get_protection_types():
        !           377:             protect.append_text(text)
        !           378:         tips.set_tip(protect, "Write protect GEMDOS drive contents")
        !           379:         table_add_widget_row(table, row, "Write protection:", protect)
        !           380:         self.protect = protect
        !           381: 
        !           382:         table.show_all()
        !           383: 
        !           384:     def _eject(self, widget, fsel):
        !           385:         fsel.unselect_all()
        !           386: 
        !           387:     def _fsel_box(self, label, path, action):
        !           388:         fsel = gtk.FileChooserButton(label)
        !           389:         # Hatari cannot access URIs
        !           390:         fsel.set_local_only(True)
        !           391:         fsel.set_width_chars(12)
        !           392:         fsel.set_action(action)
        !           393:         if path:
        !           394:             fsel.set_filename(path)
        !           395:         eject = create_button("Eject", self._eject, fsel)
        !           396: 
        !           397:         box = gtk.HBox()
        !           398:         box.pack_start(fsel)
        !           399:         box.pack_start(eject, False, False)
        !           400:         return (fsel, box)
        !           401:     
        !           402:     def _get_config(self, config):
        !           403:         path = config.get_gemdos_dir()
        !           404:         if path:
        !           405:             self.gemdos.set_filename(path)
        !           406:         path = config.get_acsi_image()
        !           407:         if path:
        !           408:             self.acsi.set_filename(path)
        !           409:         path = config.get_idemaster_image()
        !           410:         if path:
        !           411:             self.idemaster.set_filename(path)
        !           412:         path = config.get_ideslave_image()
        !           413:         if path:
        !           414:             self.ideslave.set_filename(path)
        !           415:         self.protect.set_active(config.get_hd_protection())
        !           416:         
        !           417:     def _set_config(self, config):
        !           418:         config.lock_updates()
        !           419:         config.set_gemdos_dir(self.gemdos.get_filename())
        !           420:         config.set_acsi_image(self.acsi.get_filename())
        !           421:         config.set_idemaster_image(self.idemaster.get_filename())
        !           422:         config.set_ideslave_image(self.ideslave.get_filename())
        !           423:         config.set_hd_protection(self.protect.get_active())
        !           424:         config.flush_updates()
        !           425: 
        !           426:     def run(self, config):
        !           427:         "run(config) -> bool, whether to reboot"
        !           428:         if not self.dialog:
        !           429:             self._create_dialog(config)
        !           430: 
        !           431:         self._get_config(config)
        !           432:         response = self.dialog.run()
        !           433:         self.dialog.hide()
        !           434:         if response == gtk.RESPONSE_APPLY:
        !           435:             self._set_config(config)
        !           436:             return True
        !           437:         return False
        !           438: 
        !           439: 
        !           440: # ---------------------------
        !           441: # Display dialog
        !           442: 
        !           443: class DisplayDialog(HatariUIDialog):
        !           444: 
        !           445:     def _create_dialog(self, config):
        !           446:         tips = gtk.Tooltips()
        !           447: 
        !           448:         skip = gtk.combo_box_new_text()
        !           449:         for text in config.get_frameskip_names():
        !           450:             skip.append_text(text)
        !           451:         skip.set_active(config.get_frameskip())
        !           452:         tips.set_tip(skip, "Set how many frames are skipped")
        !           453: 
        !           454:         maxw, maxh = config.get_max_size()
        !           455:         maxadjw = gtk.Adjustment(maxw, 320, 1280, 8, 40)
        !           456:         maxadjh = gtk.Adjustment(maxh, 200,  960, 8, 40)
        !           457:         scalew = gtk.HScale(maxadjw)
        !           458:         scaleh = gtk.HScale(maxadjh)
        !           459:         scalew.set_digits(0)
        !           460:         scaleh.set_digits(0)
        !           461:         tips.set_tip(scalew, "Preferred/maximum zoomed width")
        !           462:         tips.set_tip(scaleh, "Preferred/maximum zoomed height")
        !           463: 
        !           464:         borders = gtk.CheckButton("ST/STE overscan borders")
        !           465:         borders.set_active(config.get_borders())
        !           466:         tips.set_tip(borders, "Whether to show ST/STE overscan borders in low/mid-rez. Visible border area is affected by max. zoom size")
        !           467: 
        !           468:         statusbar = gtk.CheckButton("Show statusbar")
        !           469:         statusbar.set_active(config.get_statusbar())
        !           470:         tips.set_tip(statusbar, "Whether to show statusbar with floppy leds etc")
        !           471: 
        !           472:         led = gtk.CheckButton("Show overlay led")
        !           473:         led.set_active(config.get_led())
        !           474:         tips.set_tip(led, "Whether to show overlay drive led when statusbar isn't visible")
        !           475: 
        !           476:         dialog = gtk.Dialog("Display settings", self.parent,
        !           477:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           478:             (gtk.STOCK_APPLY,  gtk.RESPONSE_APPLY,
        !           479:              gtk.STOCK_CANCEL,  gtk.RESPONSE_CANCEL))
        !           480: 
        !           481:         dialog.vbox.add(gtk.Label("Frameskip:"))
        !           482:         dialog.vbox.add(skip)
        !           483:         dialog.vbox.add(gtk.Label("Max zoomed size:"))
        !           484:         dialog.vbox.add(scalew)
        !           485:         dialog.vbox.add(scaleh)
        !           486:         dialog.vbox.add(borders)
        !           487:         dialog.vbox.add(statusbar)
        !           488:         dialog.vbox.add(led)
        !           489:         dialog.vbox.show_all()
        !           490: 
        !           491:         self.dialog = dialog
        !           492:         self.skip = skip
        !           493:         self.maxw = maxadjw
        !           494:         self.maxh = maxadjh
        !           495:         self.borders = borders
        !           496:         self.statusbar = statusbar
        !           497:         self.led = led
        !           498:  
        !           499:     def run(self, config):
        !           500:         "run(config), show display dialog"
        !           501:         if not self.dialog:
        !           502:             self._create_dialog(config)
        !           503:         response = self.dialog.run()
        !           504:         self.dialog.hide()
        !           505:         if response == gtk.RESPONSE_APPLY:
        !           506:             config.lock_updates()
        !           507:             config.set_frameskip(self.skip.get_active())
        !           508:             config.set_max_size(self.maxw.get_value(), self.maxh.get_value())
        !           509:             config.set_borders(self.borders.get_active())
        !           510:             config.set_statusbar(self.statusbar.get_active())
        !           511:             config.set_led(self.led.get_active())
        !           512:             config.flush_updates()
        !           513: 
        !           514: 
        !           515: # ----------------------------------
        !           516: # Joystick dialog
        !           517: 
        !           518: class JoystickDialog(HatariUIDialog):
        !           519:     def _create_dialog(self, config):
        !           520:         table, self.dialog = create_table_dialog(self.parent, "Joystick settings", 9, 2)
        !           521:         
        !           522:         joy = 0
        !           523:         self.joy = []
        !           524:         joytypes = config.get_joystick_types()
        !           525:         for label in config.get_joystick_names():
        !           526:             combo = gtk.combo_box_new_text()
        !           527:             for text in joytypes:
        !           528:                 combo.append_text(text)
        !           529:             combo.set_active(config.get_joystick(joy))
        !           530:             widget = table_add_widget_row(table, joy, "%s:" % label, combo)
        !           531:             self.joy.append(widget)
        !           532:             joy += 1
        !           533: 
        !           534:         table.show_all()
        !           535:     
        !           536:     def run(self, config):
        !           537:         "run(config), show joystick dialog"
        !           538:         if not self.dialog:
        !           539:             self._create_dialog(config)
        !           540:         response = self.dialog.run()
        !           541:         self.dialog.hide()
        !           542:         
        !           543:         if response == gtk.RESPONSE_APPLY:
        !           544:             config.lock_updates()
        !           545:             for joy in range(6):
        !           546:                 config.set_joystick(joy, self.joy[joy].get_active())
        !           547:             config.flush_updates()
        !           548: 
        !           549: 
        !           550: # ---------------------------------------
        !           551: # Peripherals (midi,printer,rs232) dialog
        !           552: 
        !           553: class PeripheralDialog(HatariUIDialog):
        !           554:     def _create_dialog(self, config):
        !           555:         midi = gtk.CheckButton("Enable MIDI")
        !           556:         midi.set_active(config.get_midi())
        !           557: 
        !           558:         printer = gtk.CheckButton("Enable printer output")
        !           559:         printer.set_active(config.get_printer())
        !           560: 
        !           561:         rs232 = gtk.CheckButton("Enable RS232")
        !           562:         rs232.set_active(config.get_rs232())
        !           563: 
        !           564:         dialog = gtk.Dialog("Peripherals", self.parent,
        !           565:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           566:             (gtk.STOCK_APPLY,  gtk.RESPONSE_APPLY,
        !           567:              gtk.STOCK_CANCEL,  gtk.RESPONSE_CANCEL))
        !           568:         dialog.vbox.add(midi)
        !           569:         dialog.vbox.add(printer)
        !           570:         dialog.vbox.add(rs232)
        !           571:         dialog.vbox.show_all()
        !           572: 
        !           573:         self.dialog = dialog
        !           574:         self.printer = printer
        !           575:         self.rs232 = rs232
        !           576:         self.midi = midi
        !           577:     
        !           578:     def run(self, config):
        !           579:         "run(config), show peripherals dialog"
        !           580:         if not self.dialog:
        !           581:             self._create_dialog(config)
        !           582:         response = self.dialog.run()
        !           583:         self.dialog.hide()
        !           584:         
        !           585:         if response == gtk.RESPONSE_APPLY:
        !           586:             config.lock_updates()
        !           587:             config.set_midi(self.midi.get_active())
        !           588:             config.set_printer(self.printer.get_active())
        !           589:             config.set_rs232(self.rs232.get_active())
        !           590:             config.flush_updates()
        !           591: 
        !           592: 
        !           593: # ---------------------------------------
        !           594: # Path dialog
        !           595: 
        !           596: class PathDialog(HatariUIDialog):
        !           597:     def _create_dialog(self, config):
        !           598:         paths = config.get_paths()
        !           599:         table, self.dialog = create_table_dialog(self.parent, "File path settings", len(paths), 2)
        !           600:         paths.sort()
        !           601:         row = 0
        !           602:         self.paths = []
        !           603:         for (key, path, label) in paths:
        !           604:             fsel = FselEntry(self.dialog, self._validate_fname, key)
        !           605:             fsel.set_filename(path)
        !           606:             self.paths.append((key, fsel))
        !           607:             table_add_widget_row(table, row, label, fsel.get_container())
        !           608:             row += 1
        !           609:         table.show_all()
        !           610:     
        !           611:     def _validate_fname(self, key, fname):
        !           612:         if key != "soundout":
        !           613:             return True
        !           614:         if fname.rsplit(".", 1)[-1].lower() in ("ym", "wav"):
        !           615:             return True
        !           616:         ErrorDialog(self.dialog).run("Sound output file name:\n\t%s\nneeds to end with '.ym' or '.wav'." % fname)
        !           617:         return False
        !           618:     
        !           619:     def run(self, config):
        !           620:         "run(config), show paths dialog"
        !           621:         if not self.dialog:
        !           622:             self._create_dialog(config)
        !           623:         response = self.dialog.run()
        !           624:         self.dialog.hide()
        !           625: 
        !           626:         if response == gtk.RESPONSE_APPLY:
        !           627:             paths = []
        !           628:             for key, fsel in self.paths:
        !           629:                 paths.append((key, fsel.get_filename()))
        !           630:             config.set_paths(paths)
        !           631: 
        !           632: 
        !           633: # ---------------------------
        !           634: # Sound dialog
        !           635: 
        !           636: class SoundDialog(HatariUIDialog):
        !           637: 
        !           638:     def _create_dialog(self, config):
        !           639:         combo = gtk.combo_box_entry_new_text()
        !           640:         for text in config.get_sound_values():
        !           641:             combo.append_text(text)
        !           642:         enabled, hz = config.get_sound()
        !           643:         self.enabled = gtk.CheckButton("Sound enabled")
        !           644:         self.enabled.set_active(enabled)
        !           645:         combo.child.set_text(hz)
        !           646:         box = gtk.HBox()
        !           647:         box.pack_start(gtk.Label("Sound frequency:"), False, False)
        !           648:         box.add(combo)
        !           649:         self.sound = combo.child
        !           650: 
        !           651:         dialog = gtk.Dialog("Sound settings", self.parent,
        !           652:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           653:             (gtk.STOCK_APPLY,  gtk.RESPONSE_APPLY,
        !           654:              gtk.STOCK_CANCEL,  gtk.RESPONSE_CANCEL))
        !           655:         dialog.vbox.add(self.enabled)
        !           656:         dialog.vbox.add(box)
        !           657:         dialog.vbox.show_all()
        !           658:         self.dialog = dialog
        !           659: 
        !           660:     def run(self, config):
        !           661:         "run(config), show sound dialog"
        !           662:         if not self.dialog:
        !           663:             self._create_dialog(config)
        !           664:         response = self.dialog.run()
        !           665:         self.dialog.hide()
        !           666:         if response == gtk.RESPONSE_APPLY:
        !           667:             enabled = self.enabled.get_active()
        !           668:             hz1 = self.sound.get_text()
        !           669:             hz2 = config.set_sound(enabled, hz1)
        !           670:             if hz2 != hz1:
        !           671:                 self.sound.set_text(hz2)
        !           672:         
        !           673: 
        !           674: # ---------------------------
        !           675: # Trace settings dialog
        !           676: 
        !           677: class TraceDialog(HatariUIDialog):
        !           678:     # you can get this list with:
        !           679:     # hatari --trace help 2>&1|awk '/all$/{next} /^  [^-]/ {printf("\"%s\",\n", $1)}'
        !           680:     tracepoints = [
        !           681:         "video_sync",
        !           682:         "video_res",
        !           683:         "video_color",
        !           684:         "video_border_v",
        !           685:         "video_border_h",
        !           686:         "video_addr",
        !           687:         "video_hbl",
        !           688:         "video_vbl",
        !           689:         "video_ste",
        !           690:         "mfp_exception",
        !           691:         "mfp_start",
        !           692:         "mfp_read",
        !           693:         "mfp_write",
        !           694:         "psg_write_reg",
        !           695:         "psg_write_data",
        !           696:         "cpu_pairing",
        !           697:         "cpu_disasm",
        !           698:         "cpu_exception",
        !           699:         "int",
        !           700:         "fdc",
        !           701:         "ikbd_cmds",
        !           702:         "ikbd_acia",
        !           703:         "ikbd_exec",
        !           704:         "blitter",
        !           705:         "bios",
        !           706:         "xbios",
        !           707:         "gemdos",
        !           708:         "vdi",
        !           709:         "io_read",
        !           710:         "io_write",
        !           711:         "dmasound"
        !           712:     ]
        !           713:     def __init__(self, parent):
        !           714:         self.savedpoints = "none"
        !           715:         hbox1 = gtk.HBox()
        !           716:         hbox1.add(create_button("Load", self._load_traces))
        !           717:         hbox1.add(create_button("Clear", self._clear_traces))
        !           718:         hbox1.add(create_button("Save", self._save_traces))
        !           719:         hbox2 = gtk.HBox()
        !           720:         vboxes = []
        !           721:         for idx in (0,1,2):
        !           722:             vboxes.append(gtk.VBox())
        !           723:             hbox2.add(vboxes[idx])
        !           724: 
        !           725:         count = 0
        !           726:         per_side = (len(self.tracepoints)+2)/3
        !           727:         self.tracewidgets = {}
        !           728:         for trace in self.tracepoints:
        !           729:             name = trace.replace("_", "-")
        !           730:             widget = gtk.CheckButton(name)
        !           731:             self.tracewidgets[trace] = widget
        !           732:             vboxes[count/per_side].pack_start(widget, False, True)
        !           733:             count += 1
        !           734:         
        !           735:         dialog = gtk.Dialog("Trace settings", parent,
        !           736:             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        !           737:             (gtk.STOCK_APPLY,  gtk.RESPONSE_APPLY,
        !           738:              gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
        !           739:         dialog.vbox.add(hbox1)
        !           740:         dialog.vbox.add(gtk.Label("Select trace points:"))
        !           741:         dialog.vbox.add(hbox2)
        !           742:         dialog.vbox.show_all()
        !           743:         self.dialog = dialog
        !           744: 
        !           745:     def _get_traces(self):
        !           746:         traces = []
        !           747:         for trace in self.tracepoints:
        !           748:             if self.tracewidgets[trace].get_active():
        !           749:                 traces.append(trace)
        !           750:         if traces:
        !           751:             return ",".join(traces)
        !           752:         return "none"
        !           753: 
        !           754:     def _set_traces(self, tracepoints):
        !           755:         self._clear_traces()
        !           756:         for trace in tracepoints.split(","):
        !           757:             if trace in self.tracewidgets:
        !           758:                 self.tracewidgets[trace].set_active(True)
        !           759:             else:
        !           760:                 print "ERROR: unknown trace setting '%s'" % trace
        !           761: 
        !           762:     def _clear_traces(self, widget = None):
        !           763:         for trace in self.tracepoints:
        !           764:             self.tracewidgets[trace].set_active(False)
        !           765: 
        !           766:     def _load_traces(self, widget):
        !           767:         # this doesn't load traces, just sets them from internal variable
        !           768:         # that run method gets from caller and sets. It's up to caller
        !           769:         # whether the saving or loading happens actually to disk
        !           770:         self._set_traces(self.savedpoints)
        !           771:     
        !           772:     def _save_traces(self, widget):
        !           773:         self.savedpoints = self._get_traces()
        !           774: 
        !           775:     def run(self, hatari, savedpoints):
        !           776:         "run(hatari,tracepoints) -> tracepoints, caller saves tracepoints"
        !           777:         self.savedpoints = savedpoints
        !           778:         while 1:
        !           779:             response = self.dialog.run()
        !           780:             if response == gtk.RESPONSE_APPLY:
        !           781:                 hatari.change_option("--trace %s" % self._get_traces())
        !           782:             else:
        !           783:                 self.dialog.hide()
        !           784:                 return self.savedpoints
        !           785: 
        !           786: 
        !           787: # ------------------------------------------
        !           788: # Machine dialog for settings needing reboot
        !           789: 
        !           790: class MachineDialog(HatariUIDialog):
        !           791:     def _machine_cb(self, widget, data):
        !           792:         if not widget.get_active():
        !           793:             return
        !           794:         machine = data.lower()
        !           795:         if machine == "ste" or machine == "st":
        !           796:             self.clocks[0].set_active(True)
        !           797:             self.cpulevel.set_active(0)
        !           798:         elif machine == "falcon":
        !           799:             self.clocks[1].set_active(True)
        !           800:             self.cpulevel.set_active(3)
        !           801:         elif machine == "tt":
        !           802:             self.clocks[2].set_active(True)
        !           803:             self.cpulevel.set_active(3)
        !           804: 
        !           805:     def _dsp_cb(self, widget, data):
        !           806:         if not widget.get_active():
        !           807:             return
        !           808:         if not self.machines[3].get_active():
        !           809:             NoteDialog(self.dialog).run("Only Falcon has DSP.")
        !           810: 
        !           811:     def _create_dialog(self, config):
        !           812:         table, self.dialog = create_table_dialog(self.parent, "Machine configuration", 6, 4, "Set and reboot")
        !           813:         
        !           814:         row = 0
        !           815:         self.machines = table_add_radio_rows(table, row, "Machine:",
        !           816:                         config.get_machine_types(), self._machine_cb)
        !           817:         row += 1
        !           818: 
        !           819:         self.dsps = table_add_radio_rows(table, row, "DSP type:",
        !           820:                     config.get_dsp_types(), self._dsp_cb)
        !           821:         row += 1
        !           822: 
        !           823:         # start next table column
        !           824:         row = 0
        !           825:         table_set_col_offset(table, 2)
        !           826:         self.monitors = table_add_radio_rows(table, row, "Monitor:", config.get_monitor_types())
        !           827:         row += 1
        !           828: 
        !           829:         self.clocks = table_add_radio_rows(table, row, "CPU clock:", config.get_cpuclock_types())
        !           830:         row += 1
        !           831: 
        !           832:         # fullspan at bottom
        !           833:         fullspan = True
        !           834: 
        !           835:         combo = gtk.combo_box_new_text()
        !           836:         for text in config.get_cpulevel_types():
        !           837:             combo.append_text(text)
        !           838:         self.cpulevel = table_add_widget_row(table, row, "CPU type:", combo, fullspan)
        !           839:         row += 1
        !           840: 
        !           841:         combo = gtk.combo_box_new_text()
        !           842:         for text in config.get_memory_names():
        !           843:             combo.append_text(text)
        !           844:         self.memory = table_add_widget_row(table, row, "Memory:", combo, fullspan)
        !           845:         row += 1
        !           846:         
        !           847:         label = "TOS image:"
        !           848:         fsel = self._fsel(label, gtk.FILE_CHOOSER_ACTION_OPEN)
        !           849:         self.tos = table_add_widget_row(table, row, label, fsel, fullspan)
        !           850:         row += 1
        !           851: 
        !           852:         vbox = gtk.VBox()
        !           853:         self.compatible = gtk.CheckButton("Compatible CPU")
        !           854:         self.timerd = gtk.CheckButton("Patch Timer-D")
        !           855:         vbox.add(self.compatible)
        !           856:         vbox.add(self.timerd)
        !           857:         table_add_widget_row(table, row, "Misc.:", vbox, fullspan)
        !           858:         row += 1
        !           859: 
        !           860:         table.show_all()
        !           861: 
        !           862:     def _fsel(self, label, action):
        !           863:         fsel = gtk.FileChooserButton(label)
        !           864:         # Hatari cannot access URIs
        !           865:         fsel.set_local_only(True)
        !           866:         fsel.set_width_chars(12)
        !           867:         fsel.set_action(action)
        !           868:         return fsel
        !           869:     
        !           870:     def _get_config(self, config):
        !           871:         self.machines[config.get_machine()].set_active(True)
        !           872:         self.monitors[config.get_monitor()].set_active(True)
        !           873:         self.clocks[config.get_cpuclock()].set_active(True)
        !           874:         self.dsps[config.get_dsp()].set_active(True)
        !           875:         self.cpulevel.set_active(config.get_cpulevel())
        !           876:         self.memory.set_active(config.get_memory())
        !           877:         tos = config.get_tos()
        !           878:         if tos:
        !           879:             self.tos.set_filename(tos)
        !           880:         self.compatible.set_active(config.get_compatible())
        !           881:         self.timerd.set_active(config.get_timerd())
        !           882: 
        !           883:     def _get_active_radio(self, radios):
        !           884:         idx = 0
        !           885:         for radio in radios:
        !           886:             if radio.get_active():
        !           887:                 return idx
        !           888:             idx += 1
        !           889:         
        !           890:     def _set_config(self, config):
        !           891:         config.lock_updates()
        !           892:         config.set_machine(self._get_active_radio(self.machines))
        !           893:         config.set_monitor(self._get_active_radio(self.monitors))
        !           894:         config.set_cpuclock(self._get_active_radio(self.clocks))
        !           895:         config.set_dsp(self._get_active_radio(self.dsps))
        !           896:         config.set_cpulevel(self.cpulevel.get_active())
        !           897:         config.set_memory(self.memory.get_active())
        !           898:         config.set_tos(self.tos.get_filename())
        !           899:         config.set_compatible(self.compatible.get_active())
        !           900:         config.set_timerd(self.timerd.get_active())
        !           901:         config.flush_updates()
        !           902: 
        !           903:     def run(self, config):
        !           904:         "run(config) -> bool, whether to reboot"
        !           905:         if not self.dialog:
        !           906:             self._create_dialog(config)
        !           907: 
        !           908:         self._get_config(config)
        !           909:         response = self.dialog.run()
        !           910:         self.dialog.hide()
        !           911:         if response == gtk.RESPONSE_APPLY:
        !           912:             self._set_config(config)
        !           913:             return True
        !           914:         return False

unix.superglobalmegacorp.com

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