def coro(): altpath = getEngineDataPrefix() if pgn.scoutfish_path is None and conf.get("download_scoutfish", False): binary = "https://github.com/pychess/scoutfish/releases/download/20170627/%s" % pgn.scoutfish filename = yield from download_file_async(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, pgn.scoutfish)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) pgn.scoutfish_path = dest if pgn.chess_db_path is None and conf.get("download_chess_db", False): binary = "https://github.com/pychess/chess_db/releases/download/20170627/%s" % pgn.parser filename = yield from download_file_async(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, pgn.parser)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) pgn.chess_db_path = dest if TimeSeal.timestamp_path is None and conf.get("download_timestamp", False): binary = "https://www.chessclub.com/user/resources/icc/timestamp/%s" % TimeSeal.timestamp filename = yield from download_file_async(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, TimeSeal.timestamp)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) TimeSeal.timestamp_path = dest
async def initEngine(self, engine, color, lowPriority): name = engine['name'] protocol = engine["protocol"] protover = 2 if engine.get("protover") is None else engine.get( "protover") path = engine['command'] args = [] if engine.get('args') is None else [ a for a in engine['args'] ] if engine.get('vm_command') is not None: vmpath = engine['vm_command'] vmargs = [] if engine.get('vm_args') is None else [ a for a in engine['vm_args'] ] args = vmargs + [path] + args path = vmpath md5_engine = engine['md5'] working_directory = engine.get("workingDirectory") if working_directory: workdir = working_directory else: workdir = getEngineDataPrefix() warnwords = ("illegal", "error", "exception") try: subprocess = SubProcess(path, args=args, warnwords=warnwords, cwd=workdir, lowPriority=lowPriority) await subprocess.start() except OSError: raise PlayerIsDead except asyncio.TimeoutError: raise PlayerIsDead except GLib.GError: raise PlayerIsDead except Exception: raise PlayerIsDead engine_proc = attrToProtocol[protocol](subprocess, color, protover, md5_engine) engine_proc.setName(name) # If the user has configured special options for this engine, here is # where they should be set. def optionsCallback(set_option): if engine.get("options"): for option in engine["options"]: key = option["name"] value = option.get("value") if (value is not None) and option["default"] != value: if protocol == "xboard" and option["type"] == "check": value = int(bool(value)) set_option.setOption(key, value) engine_proc.connect("readyForOptions", optionsCallback) return engine_proc
def coro(): altpath = getEngineDataPrefix() if pgn.scoutfish_path is None and conf.get("download_scoutfish", False): binary = "https://github.com/pychess/scoutfish/releases/download/20170627/%s" % pgn.scoutfish filename = yield from download_file_async(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, pgn.scoutfish)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) pgn.scoutfish_path = dest if pgn.chess_db_path is None and conf.get("download_chess_db", False): binary = "https://github.com/pychess/chess_db/releases/download/20170627/%s" % pgn.parser filename = yield from download_file_async(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, pgn.parser)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) pgn.chess_db_path = dest if TimeSeal.timestamp_path is None and conf.get("download_timestamp", False): binary = "http://download.chessclub.com.s3.amazonaws.com/timestamp/%s" % TimeSeal.timestamp filename = yield from download_file_async(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, TimeSeal.timestamp)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) TimeSeal.timestamp_path = dest
def start(self, host, port, connected_event, timeseal=True): if self.canceled: raise CanceledException() self.port = port self.host = host self.connected_event = connected_event self.timeseal = timeseal self.name = host if host == "chessclub.com": self.ICC = True self.timeseal = False # You can get ICC timestamp from # https://www.chessclub.com/user/resources/icc/timestamp/ if sys.platform == "win32": timestamp = "timestamp_win32.exe" else: timestamp = "timestamp_linux_2.6.8" altpath = getEngineDataPrefix() path = shutil.which(timestamp, os.X_OK, path=altpath) if path is None: binary = "https://www.chessclub.com/user/resources/icc/timestamp/%s" % timestamp filename = download_file(binary) if filename is not None: dest = shutil.move(filename, os.path.join(altpath, timestamp)) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) if path: self.host = "127.0.0.1" self.port = 5500 try: self.timestamp_proc = subprocess.Popen(["%s" % path, "-p", "%s" % self.port]) log.info("%s started OK" % path) except OSError as err: log.info("Can't start %s OSError: %s %s" % (path, err.errno, err.strerror)) self.port = port self.host = host else: log.info("%s not found, downloading..." % path) def cb(reader, writer): reader.stream_writer = writer reader.connected_event.set() loop = asyncio.get_event_loop() self.reader = ICSStreamReader(_DEFAULT_LIMIT, loop, self.connected_event, self.name) self.protocol = ICSStreamReaderProtocol(self.reader, cb, loop, self.name, self.timeseal) coro = loop.create_connection(lambda: self.protocol, self.host, self.port) self.transport, _protocol = yield from coro # writer = asyncio.StreamWriter(transport, protocol, reader, loop) if self.timeseal: self.write(self.get_init_string())
def initEngine(self, engine, color, lowPriority): name = engine['name'] protocol = engine["protocol"] protover = 2 if engine.get("protover") is None else engine.get( "protover") path = engine['command'] args = [] if engine.get('args') is None else [a for a in engine['args']] if engine.get('vm_command') is not None: vmpath = engine['vm_command'] vmargs = [] if engine.get('vm_args') is None else [ a for a in engine['vm_args'] ] args = vmargs + [path] + args path = vmpath md5_engine = engine['md5'] working_directory = engine.get("workingDirectory") if working_directory: workdir = working_directory else: workdir = getEngineDataPrefix() warnwords = ("illegal", "error", "exception") try: subprocess = SubProcess(path, args=args, warnwords=warnwords, cwd=workdir, lowPriority=lowPriority) yield from subprocess.start() except OSError: raise PlayerIsDead except asyncio.TimeoutError: raise PlayerIsDead except GLib.GError: raise PlayerIsDead except Exception: raise PlayerIsDead engine_proc = attrToProtocol[protocol](subprocess, color, protover, md5_engine) engine_proc.setName(name) # If the user has configured special options for this engine, here is # where they should be set. def optionsCallback(set_option): if engine.get("options"): for option in engine["options"]: key = option["name"] value = option.get("value") if (value is not None) and option["default"] != value: if protocol == "xboard" and option["type"] == "check": value = int(bool(value)) set_option.setOption(key, value) engine_proc.connect("readyForOptions", optionsCallback) return engine_proc
def initEngine(self, engine, color): name = engine['name'] protocol = engine["protocol"] protover = 2 if engine.get("protover") is None else engine.get( "protover") path = engine['command'] args = [] if engine.get('args') is None else [ a for a in engine['args'] ] if engine.get('vm_command') is not None: vmpath = engine['vm_command'] vmargs = [] if engine.get('vm_args') is None else [ a for a in engine['vm_args'] ] args = vmargs + [path] + args path = vmpath md5 = engine['md5'] working_directory = engine.get("workingDirectory") if working_directory: workdir = working_directory else: workdir = getEngineDataPrefix() warnwords = ("illegal", "error", "exception") subprocess = SubProcess(path, args, warnwords, SUBPROCESS_SUBPROCESS, workdir) engine_proc = attrToProtocol[protocol](subprocess, color, protover, md5) engine_proc.setName(name) # If the user has configured special options for this engine, here is # where they should be set. def optionsCallback(e): if engine.get("options"): for option in engine["options"]: key = option["name"] value = option.get("value") if (value is not None) and option["default"] != value: if protocol == "xboard" and option["type"] == "check": value = int(bool(value)) e.setOption(key, value) engine_proc.connect("readyForOptions", optionsCallback) return engine_proc
def initEngine(self, engine, color): name = engine["name"] protocol = engine["protocol"] protover = 2 if engine.get("protover") is None else engine.get("protover") path = engine["command"] args = [] if engine.get("args") is None else [a for a in engine["args"]] if engine.get("vm_command") is not None: vmpath = engine["vm_command"] vmargs = [] if engine.get("vm_args") is None else [a for a in engine["vm_args"]] args = vmargs + [path] + args path = vmpath md5 = engine["md5"] working_directory = engine.get("workingDirectory") if working_directory: workdir = working_directory else: workdir = getEngineDataPrefix() warnwords = ("illegal", "error", "exception") subprocess = SubProcess(path, args, warnwords, SUBPROCESS_SUBPROCESS, workdir) engine_proc = attrToProtocol[protocol](subprocess, color, protover, md5) engine_proc.setName(name) # If the user has configured special options for this engine, here is # where they should be set. def optionsCallback(e): if engine.get("options"): for option in engine["options"]: key = option["name"] value = option.get("value") if (value is not None) and option["default"] != value: if protocol == "xboard" and option["type"] == "check": value = int(bool(value)) e.setOption(key, value) engine_proc.connect("readyForOptions", optionsCallback) return engine_proc
else: mvcount = "" else: mvcount = "" return mvcount def load(handle, progressbar=None): return PGNFile(handle, progressbar) BITNESS = "64" if platform.machine().endswith('64') else "32" EXT = ".exe" if sys.platform == "win32" else "" scoutfish = "scoutfish_x%s%s" % (BITNESS, EXT) altpath = os.path.join(getEngineDataPrefix(), scoutfish) scoutfish_path = searchPath(scoutfish, access=os.X_OK, altpath=altpath) if scoutfish_path is None: binary = "https://github.com/gbtami/scoutfish/releases/download/20170627/%s" % scoutfish filename = download_file(binary) if filename is not None: dest = shutil.move(filename, altpath) os.chmod(dest, stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) parser = "parser_x%s%s" % (BITNESS, EXT) altpath = os.path.join(getEngineDataPrefix(), parser) chess_db_path = searchPath(parser, access=os.X_OK, altpath=altpath) if chess_db_path is None: binary = "https://github.com/gbtami/chess_db/releases/download/20170627/%s" % parser filename = download_file(binary)
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog, defaultSize=(600, 500)) # Put engines into tree store allstore = Gtk.ListStore(Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(allstore) self.tv.append_column( Gtk.TreeViewColumn("Flag", Gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", True) self.tv.append_column(Gtk.TreeViewColumn("Name", name_renderer, text=1)) def name_edited(renderer, path, new_name): if self.cur_engine is not None: old_name = self.cur_engine if new_name and new_name != old_name: names = [ engine["name"] for engine in discoverer.getEngines() ] if new_name not in names: engine = discoverer.getEngineByName(self.cur_engine) engine["name"] = new_name discoverer.save() self.cur_engine = new_name update_store() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") name_renderer.connect("edited", name_edited) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] cell = Gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = Gtk.ListStore(str, GObject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column( Gtk.TreeViewColumn("Option", Gtk.CellRendererText(), text=0)) optv.append_column( Gtk.TreeViewColumn("Data", KeyValueCellRenderer(self.options_store), data=1)) def update_options(*args): if self.cur_engine is not None: engines = discoverer.getEngines() names = [engine["name"] for engine in engines] # After deleting an engine we will select first if self.cur_engine not in names: self.cur_engine = engines[0]["name"] engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: self.options_store.clear() for option in options: key = option["name"] val = option if option["type"] != "button": val["default"] = option.get("default") val["value"] = option.get("value", val["default"]) self.options_store.append([key, val]) def update_store(*args): allstore.clear() newGameDialog.createPlayerUIGlobals(discoverer) # don't add the very first (Human) player to engine store for item in newGameDialog.playerItems[0][1:]: allstore.append(item) update_options() update_store() ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) engine = discoverer.getEngineByName(self.cur_engine) discoverer.removeEngine(self.cur_engine) discoverer.save() update_store(discoverer) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") ts = self.tv.get_selection() ts.select_path((0, )) self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = Gtk.FileChooserDialog( _("Select engine"), None, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter = Gtk.FileFilter() filter.set_name(_("Chess engines")) filter.add_mime_type("application/x-executable") engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == Gtk.ResponseType.OK: new_engine = engine_chooser_dialog.get_filename() if new_engine: try: uci = is_uci(new_engine) if not uci: if not is_cecp(new_engine): # restore the original engine = discoverer.getEngineByName( self.cur_engine) engine_chooser_dialog.set_filename( engine["command"]) print("Maybe not a chess engine") return path, binname = os.path.split(new_engine) for e in discoverer.getEngines(): if e["name"] == binname: binname = e["name"] + "(1)" break self.widgets["engine_command_entry"].set_text( new_engine) self.widgets["engine_protocol_combo"].set_active( 0 if uci else 1) self.widgets["engine_args_entry"].set_text("") active = self.widgets[ "engine_protocol_combo"].get_active() protocol = "uci" if active == 0 else "xboard" discoverer.addEngine(binname, new_engine, protocol) self.cur_engine = binname glock_connect_after(discoverer, "engine_discovered", update_store) self.add = False discoverer.discover() except: print("There is something wrong with this executable") else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() discoverer.save() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = Gtk.FileChooserDialog( _("Select working directory"), None, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dir_chooser_button = Gtk.FileChooserButton.new_with_dialog( dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory discoverer.save() dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active == 0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: engine_command = engine_chooser_dialog.get_filename() # is the new protocol supported by the engine? if new_protocol == "uci": ok = is_uci(engine_command) else: ok = is_cecp(engine_command) if ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True glock_connect_after(discoverer, "engine_discovered", update_options) discoverer.discover() else: # restore the original protocol widgets["engine_protocol_combo"].set_active( 0 if old_protocol == "uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, iter = self.tv.get_selection().get_selected() if iter: self.selection = True row = store.get_path(iter)[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) self.widgets['copy_engine_button'].set_sensitive(True) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text( engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") d = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(d) self.widgets["engine_protocol_combo"].set_active( 0 if engine["protocol"] == "uci" else 1) update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0, ))
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog, defaultSize=(1, 500)) # Put engines into tree store allstore = Gtk.ListStore(Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(allstore) self.tv.append_column( Gtk.TreeViewColumn("Flag", Gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", True) self.tv.append_column(Gtk.TreeViewColumn("Name", name_renderer, text=1)) def name_edited(renderer, path, new_name): if self.cur_engine is not None: old_name = self.cur_engine if new_name and new_name != old_name: names = [ engine["name"] for engine in discoverer.getEngines() ] if new_name not in names: engine = discoverer.getEngineByName(self.cur_engine) engine["name"] = new_name discoverer.save() self.cur_engine = new_name update_store() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") name_renderer.connect("edited", name_edited) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] protocol_combo.set_name("engine_protocol_combo") cell = Gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = Gtk.ListStore(str, GObject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column( Gtk.TreeViewColumn("Option", Gtk.CellRendererText(), text=0)) optv.append_column( Gtk.TreeViewColumn("Data", KeyValueCellRenderer(self.options_store), data=1)) def update_options(*args): if self.cur_engine is not None: engines = discoverer.getEngines() names = [engine["name"] for engine in engines] # After deleting an engine we will select first if self.cur_engine not in names: self.cur_engine = engines[0]["name"] engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: self.options_store.clear() for option in options: key = option["name"] val = option if option["type"] != "button": val["default"] = option.get("default") val["value"] = option.get("value", val["default"]) self.options_store.append([key, val]) def update_store(*args): newGameDialog.createPlayerUIGlobals(discoverer) engine_names = [row[1] for row in allstore] new_items = [] # don't add the very first (Human) player to engine store for item in newGameDialog.playerItems[0][1:]: if item[1] not in engine_names: new_items.append(item) ts_iter = None for item in new_items: ts_iter = allstore.append(item) if ts_iter is not None: text_select = self.tv.get_selection() text_select.select_iter(ts_iter) update_options() update_store() def do_update_store(*args): GLib.idle_add(update_store) discoverer.connect_after("engine_discovered", do_update_store) ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) # engine = discoverer.getEngineByName(self.cur_engine) discoverer.removeEngine(self.cur_engine) discoverer.save() selection = self.tv.get_selection() result = selection.get_selected() if result is not None: model, ts_iter = result model.remove(ts_iter) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = Gtk.FileChooserDialog( _("Select engine"), None, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter = Gtk.FileFilter() filter.set_name(_("Executable files")) filter.add_mime_type("application/x-executable") filter.add_mime_type("application/x-ms-dos-executable") filter.add_mime_type("application/x-msdownload") filter.add_pattern("*.exe") for vm in VM_LIST: filter.add_pattern("*%s" % vm.ext) engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == Gtk.ResponseType.OK: new_engine = engine_chooser_dialog.get_filename() vm_name = None vm_args = None vmpath = "" if new_engine.lower().endswith( ".exe") and sys.platform != "win32": vm_name = "wine" vmpath = shutil.which(vm_name, mode=os.R_OK | os.X_OK) if vmpath is None: msg_dia = Gtk.MessageDialog(type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_("wine not installed")) msg_dia.run() msg_dia.hide() new_engine = "" for vm in VM_LIST: ext = os.path.splitext(new_engine)[1] if ext == vm.ext: vm_name = vm.name vm_args = vm.args vmpath = shutil.which(vm_name, mode=os.R_OK | os.X_OK) if vmpath is None: msg_dia = Gtk.MessageDialog( type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( vm_name + _(" is not installed")) msg_dia.run() msg_dia.hide() new_engine = "" break if new_engine: vm_ext_list = [vm.ext for vm in VM_LIST] if ext not in vm_ext_list and not os.access( new_engine, os.X_OK): msg_dia = Gtk.MessageDialog(type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>%s is not marked executable in the filesystem</b></big>" % new_engine)) msg_dia.format_secondary_text( _("Try chmod a+x %s" % new_engine)) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return try: engine_command = [] if vmpath: engine_command.append(vmpath) if vm_args is not None: engine_command.append(vm_args) engine_command.append(new_engine) # Some engines support CECP and UCI, but main variant engines are CECP, # so we better to start with CECP this case variant_engines = ("fmax", "sjaakii", "sjeng") if any((True for eng in variant_engines if eng in new_engine.lower())): checkers = [is_cecp, is_uci] else: checkers = [is_uci, is_cecp] uci = False for checker in checkers: check_ok = checker(engine_command) if check_ok: uci = checker is is_uci break else: continue if not check_ok: # restore the original engine = discoverer.getEngineByName( self.cur_engine) engine_chooser_dialog.set_filename( engine["command"]) msg_dia = Gtk.MessageDialog( type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( _("There is something wrong with this executable" )) msg_dia.run() msg_dia.hide() engine_chooser_dialog.hide() self.add = False engine_chooser_dialog.hide() return binname = os.path.split(new_engine)[1] for eng in discoverer.getEngines(): if eng["name"] == binname: binname = eng["name"] + "(1)" break self.widgets["engine_command_entry"].set_text( new_engine) self.widgets["engine_protocol_combo"].set_active( 0 if uci else 1) self.widgets["engine_args_entry"].set_text("") # active = self.widgets["engine_protocol_combo"].get_active() protocol = "uci" if uci else "xboard" if vm_args is not None: vm_args = vm_args.split(",") # print(binname, new_engine, protocol, vm_name, vm_args) discoverer.addEngine(binname, new_engine, protocol, vm_name, vm_args) self.cur_engine = binname self.add = False discoverer.discover() except: msg_dia = Gtk.MessageDialog(type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( _("There is something wrong with this executable")) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ # vm args ################################################################ def vm_args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["vm_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("vm_args") if new_args != old_args: engine["vm_args"] = new_args.split() discoverer.save() self.widgets["vm_args_entry"].connect("changed", vm_args_changed) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() discoverer.save() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = Gtk.FileChooserDialog( _("Select working directory"), None, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dir_chooser_button = Gtk.FileChooserButton.new_with_dialog( dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory discoverer.save() dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active == 0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: command = engine.get("command") engine_command = [] vm_command = engine.get("vm_command") if vm_command is not None: engine_command.append(vm_command) vm_args = engine.get("vm_args") if vm_args is not None: engine_command.append(", ".join(vm_args)) engine_command.append(command) # is the new protocol supported by the engine? if new_protocol == "uci": check_ok = is_uci(engine_command) else: check_ok = is_cecp(engine_command) if check_ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True discoverer.discover() else: # restore the original protocol widgets["engine_protocol_combo"].set_active( 0 if old_protocol == "uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, tv_iter = self.tv.get_selection().get_selected() if tv_iter: self.selection = True path = store.get_path(tv_iter) indices = path.get_indices() row = indices[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) self.widgets['copy_engine_button'].set_sensitive(True) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text( engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) vm = engine.get("vm_command") self.widgets["vm_command_entry"].set_text( vm if vm is not None else "") args = [] if engine.get("vm_args") is None else engine.get( "vm_args") self.widgets["vm_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") dir_choice = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(dir_choice) self.widgets["engine_protocol_combo"].set_active( 0 if engine["protocol"] == "uci" else 1) update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0, ))
def load(handle, progressbar=None): return PGNFile(handle, progressbar) try: with open("/proc/cpuinfo") as f: cpuinfo = f.read() except OSError: cpuinfo = "" BITNESS = "64" if platform.machine().endswith('64') else "32" MODERN = "-modern" if "popcnt" in cpuinfo else "" EXT = ".exe" if sys.platform == "win32" else "" altpath = getEngineDataPrefix() scoutfish = "scoutfish_x%s%s%s" % (BITNESS, MODERN, EXT) scoutfish_path = shutil.which(scoutfish, mode=os.X_OK, path=altpath) parser = "parser_x%s%s%s" % (BITNESS, MODERN, EXT) chess_db_path = shutil.which(parser, mode=os.X_OK, path=altpath) class PGNFile(ChessFile): def __init__(self, handle, progressbar): ChessFile.__init__(self, handle) self.handle = handle self.progressbar = progressbar self.pgn_is_string = isinstance(handle, StringIO)
else: result.extend(lookahead) lookahead = [] state = 0 return bytearray(result), g_count, (state, lookahead) # You can get ICC timestamp from # https://www.chessclub.com/user/resources/icc/timestamp/ if sys.platform == "win32": timestamp = "timestamp_win32.exe" else: timestamp = "timestamp_linux_2.6.8" altpath = getEngineDataPrefix() timestamp_path = shutil.which(timestamp, os.X_OK, path=altpath) class ICSTelnet: sensitive = False def __init__(self, timeseal): self.name = "" self.connected = False self.canceled = False self.FatICS = False self.USCN = False self.ICC = False self.timeseal = timeseal self.ICC_buffer = ""
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog, defaultSize=(1, 500)) # Put engines into tree store allstore = Gtk.ListStore(Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(allstore) self.tv.append_column(Gtk.TreeViewColumn( "Flag", Gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", True) self.tv.append_column(Gtk.TreeViewColumn("Name", name_renderer, text=1)) def name_edited(renderer, path, new_name): if self.cur_engine is not None: old_name = self.cur_engine if new_name and new_name != old_name: names = [engine["name"] for engine in discoverer.getEngines()] if new_name not in names: engine = discoverer.getEngineByName(self.cur_engine) engine["name"] = new_name discoverer.save() self.cur_engine = new_name update_store() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") name_renderer.connect("edited", name_edited) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] cell = Gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = Gtk.ListStore(str, GObject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column(Gtk.TreeViewColumn( "Option", Gtk.CellRendererText(), text=0)) optv.append_column(Gtk.TreeViewColumn( "Data", KeyValueCellRenderer(self.options_store), data=1)) def update_options(*args): if self.cur_engine is not None: engines = discoverer.getEngines() names = [engine["name"] for engine in engines] # After deleting an engine we will select first if self.cur_engine not in names: self.cur_engine = engines[0]["name"] engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: self.options_store.clear() for option in options: key = option["name"] val = option if option["type"] != "button": val["default"] = option.get("default") val["value"] = option.get("value", val["default"]) self.options_store.append([key, val]) def update_store(*args): newGameDialog.createPlayerUIGlobals(discoverer) engine_names = [row[1] for row in allstore] new_items = [] # don't add the very first (Human) player to engine store for item in newGameDialog.playerItems[0][1:]: if item[1] not in engine_names: new_items.append(item) iter = None for item in new_items: iter = allstore.append(item) if iter is not None: ts = self.tv.get_selection() ts.select_iter(iter) update_options() update_store() def do_update_store(*args): GLib.idle_add(update_store) discoverer.connect_after("engine_discovered", do_update_store) ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) engine = discoverer.getEngineByName(self.cur_engine) discoverer.removeEngine(self.cur_engine) discoverer.save() selection = self.tv.get_selection() result = selection.get_selected() if result is not None: model, iter = result model.remove(iter) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = Gtk.FileChooserDialog(_("Select engine"), None, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter = Gtk.FileFilter() filter.set_name(_("Executable files")) filter.add_mime_type("application/x-executable") filter.add_mime_type("application/x-ms-dos-executable") filter.add_mime_type("application/x-msdownload") filter.add_pattern("*.exe") engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == Gtk.ResponseType.OK: new_engine = engine_chooser_dialog.get_filename() if new_engine.lower().endswith(".exe") and sys.platform != "win32": vm_name = "wine" vmpath = searchPath(vm_name, access=os.R_OK|os.X_OK) if vmpath is None: d = Gtk.MessageDialog( type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) d.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) d.format_secondary_text(_("wine not installed")) d.run() d.hide() new_engine = "" else: vmpath += " " else: vm_name = None vmpath = "" if new_engine: try: # Some engines support CECP and UCI, but variant engines are CECP, # so we better to start with CECP this case variant_engines = ("fmax", "sjaakii", "sjeng") if any((True for e in variant_engines if e in new_engine.lower())): checkers = [is_cecp, is_uci] else: checkers = [is_uci, is_cecp] uci = False for checker in checkers: ok = checker(vmpath + new_engine) if ok: uci = checker is is_uci break else: continue if not ok: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) d = Gtk.MessageDialog( type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) d.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) d.format_secondary_text(_("There is something wrong with this executable")) d.run() d.hide() engine_chooser_dialog.hide() return path, binname = os.path.split(new_engine) for e in discoverer.getEngines(): if e["name"] == binname: binname = e["name"] + "(1)" break self.widgets["engine_command_entry"].set_text(new_engine) self.widgets["engine_protocol_combo"].set_active(0 if uci else 1) self.widgets["engine_args_entry"].set_text("") active = self.widgets["engine_protocol_combo"].get_active() protocol = "uci" if uci else "xboard" discoverer.addEngine(binname, new_engine, protocol, vm_name) self.cur_engine = binname self.add = False discoverer.discover() except: d = Gtk.MessageDialog( type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) d.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) d.format_secondary_text(_("There is something wrong with this executable")) d.run() d.hide() else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() discoverer.save() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = Gtk.FileChooserDialog(_("Select working directory"), None, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dir_chooser_button = Gtk.FileChooserButton.new_with_dialog(dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory discoverer.save() dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active==0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: engine_command = engine_chooser_dialog.get_filename() # is the new protocol supported by the engine? if new_protocol == "uci": ok = is_uci(engine_command) else: ok = is_cecp(engine_command) if ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True discoverer.discover() else: # restore the original protocol widgets["engine_protocol_combo"].set_active(0 if old_protocol=="uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, iter = self.tv.get_selection().get_selected() if iter: self.selection = True path = store.get_path(iter) indices = path.get_indices() row = indices[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) self.widgets['copy_engine_button'].set_sensitive(True) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text(engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") d = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(d) self.widgets["engine_protocol_combo"].set_active(0 if engine["protocol"]=="uci" else 1) update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0,))
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog) # Put engines into tree store self.allstore = Gtk.ListStore(Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(self.allstore) self.tv.append_column(Gtk.TreeViewColumn("Flag", Gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", False) self.tv.append_column(Gtk.TreeViewColumn("Name", name_renderer, text=1)) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] protocol_combo.set_name("engine_protocol_combo") cell = Gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = Gtk.ListStore(str, str, GObject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column(Gtk.TreeViewColumn(" ", Gtk.CellRendererText(), text=0)) optv.append_column(Gtk.TreeViewColumn(_("Option"), Gtk.CellRendererText(), text=1)) optv.append_column(Gtk.TreeViewColumn(_("Value"), KeyValueCellRenderer(self.options_store), data=2)) self.update_store() def do_update_store(self, *args): GLib.idle_add(engine_dialog.update_store) discoverer.connect_after("engine_discovered", do_update_store) ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) discoverer.removeEngine(self.cur_engine) selection = self.tv.get_selection() result = selection.get_selected() if result is not None: model, ts_iter = result model.remove(ts_iter) if model.iter_n_children() == 0: clearView() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = Gtk.FileChooserDialog( _("Select engine"), mainwindow(), Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter = Gtk.FileFilter() filter.set_name(_("Executable files")) filter.add_mime_type("application/x-executable") filter.add_mime_type("application/x-sharedlib") filter.add_mime_type("application/x-ms-dos-executable") filter.add_mime_type("application/x-msdownload") filter.add_pattern("*.exe") for vm in VM_LIST: filter.add_pattern("*%s" % vm.ext) engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == Gtk.ResponseType.OK: new_engine = engine_chooser_dialog.get_filename() binname = os.path.split(new_engine)[1] ext = os.path.splitext(new_engine)[1] # Verify if the engine already exists under the same name if new_engine != "": for eng in discoverer.getEngines(): if eng["command"] == new_engine: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_("The engine is already installed under the same name")) msg_dia.run() msg_dia.hide() new_engine = "" break # Detect the host application if new_engine != "": vm_name = None vm_args = None vmpath = "" # Scripting for vm in VM_LIST: if ext == vm.ext: vm_name = vm.name vm_args = vm.args break # Wine for Windows application under Linux if vm_name is None and new_engine.lower().endswith(".exe") and sys.platform != "win32": vm_name = "wine" # Check that the interpreter is available if vm_name is not None: vmpath = shutil.which(vm_name, mode=os.R_OK | os.X_OK) if vmpath is None: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(vm_name + _(" is not installed")) msg_dia.run() msg_dia.hide() new_engine = "" # Next checks if new_engine: vm_ext_list = [vm.ext for vm in VM_LIST] if ext not in vm_ext_list and not os.access(new_engine, os.X_OK): msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>%s is not marked executable in the filesystem</b></big>" % new_engine)) msg_dia.format_secondary_text(_("Try chmod a+x %s" % new_engine)) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return try: engine_command = [] if vmpath: engine_command.append(vmpath) if vm_args is not None: engine_command.append(vm_args) engine_command.append(new_engine) # Search the engines based on the most expectable protocol refeng = discoverer.getReferencedEngine(binname) if refeng is not None and refeng["protocol"] == "xboard": checkers = [is_cecp, is_uci] else: checkers = [is_uci, is_cecp] uci = False for checker in checkers: check_ok = checker(engine_command) if check_ok: uci = checker is is_uci break else: continue if not check_ok: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_("There is something wrong with this executable")) msg_dia.run() msg_dia.hide() engine_chooser_dialog.hide() self.add = False engine_chooser_dialog.hide() return self.widgets["engine_command_entry"].set_text(new_engine) self.widgets["engine_protocol_combo"].set_active(0 if uci else 1) self.widgets["engine_args_entry"].set_text("") # active = self.widgets["engine_protocol_combo"].get_active() protocol = "uci" if uci else "xboard" if vm_args is not None: vm_args = vm_args.split(",") # print(binname, new_engine, protocol, vm_name, vm_args) discoverer.addEngine(binname, new_engine, protocol, vm_name, vm_args) self.cur_engine = binname self.add = False discoverer.discover() except Exception: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_("There is something wrong with this executable")) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ def clearView(): self.selection = True self.cur_engine = None self.widgets["vm_command_entry"].set_text("") self.widgets["vm_args_entry"].set_text("") self.widgets["engine_command_entry"].set_text("") self.widgets["engine_args_entry"].set_text("") self.widgets["engine_protocol_combo"].set_active(0) self.widgets["engine_country_combo"].set_active(0) self.widgets["engine_comment_entry"].set_text("") self.widgets["engine_level_scale"].set_value(defaultEngineLevel) self.options_store.clear() self.selection = False ################################################################ # vm args ################################################################ def vm_args_changed(widget): if self.cur_engine is not None and not self.selection: new_args = self.widgets["vm_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("vm_args") if new_args != old_args: engine["vm_args"] = new_args.split() self.widgets["vm_args_entry"].connect("changed", vm_args_changed) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None and not self.selection: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = Gtk.FileChooserDialog( _("Select working directory"), mainwindow(), Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dir_chooser_button = Gtk.FileChooserButton.new_with_dialog( dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active == 0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: command = engine.get("command") engine_command = [] vm_command = engine.get("vm_command") if vm_command is not None: engine_command.append(vm_command) vm_args = engine.get("vm_args") if vm_args is not None: engine_command.append(", ".join(vm_args)) engine_command.append(command) # is the new protocol supported by the engine? if new_protocol == "uci": check_ok = is_uci(engine_command) else: check_ok = is_cecp(engine_command) if check_ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True discoverer.discover() else: # restore the original protocol widgets["engine_protocol_combo"].set_active( 0 if old_protocol == "uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine country ################################################################ def country_changed(widget): if self.cur_engine is not None and not self.selection: engine = discoverer.getEngineByName(self.cur_engine) old_country = discoverer.getCountry(engine) new_country = ISO3166_LIST[widget.get_active()].iso2 if old_country != new_country: engine["country"] = new_country # Refresh the flag in the tree view path = addDataPrefix("flags/%s.png" % new_country) if not os.path.isfile(path): path = addDataPrefix("flags/unknown.png") item = self.tv.get_selection().get_selected() if item is not None: model, ts_iter = item model[ts_iter][0] = get_pixbuf(path) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["engine_country_combo"].connect("changed", country_changed) def country_keypressed(widget, event): idx = 0 for iso in ISO3166_LIST: if (idx != 0) and ((ord(iso.country[0].lower()) == event.keyval) or (ord(iso.country[0].upper()) == event.keyval)): widget.set_active(idx) break idx += 1 self.widgets["engine_country_combo"].connect("key-press-event", country_keypressed) ################################################################ # comment changed ################################################################ def comment_changed(widget): if self.cur_engine is not None and not self.selection: new_comment = self.widgets["engine_comment_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_comment = engine.get("comment") if new_comment != old_comment: engine["comment"] = new_comment self.widgets["engine_comment_entry"].connect("changed", comment_changed) ################################################################ # level changed ################################################################ def level_changed(widget): if self.cur_engine is not None and not self.selection: new_level = widget.get_value() engine = discoverer.getEngineByName(self.cur_engine) old_level = engine.get("level") if new_level != old_level: engine["level"] = int(new_level) self.widgets["engine_level_scale"].connect("value-changed", level_changed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, tv_iter = self.tv.get_selection().get_selected() if tv_iter: self.selection = True path = store.get_path(tv_iter) indices = path.get_indices() row = indices[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text(engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) vm = engine.get("vm_command") self.widgets["vm_command_entry"].set_text(vm if vm is not None else "") args = [] if engine.get("vm_args") is None else engine.get("vm_args") self.widgets["vm_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") dir_choice = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(dir_choice) self.widgets["engine_protocol_combo"].set_active(0 if engine["protocol"] == "uci" else 1) self.widgets["engine_country_combo"].set_active(0) country = discoverer.getCountry(engine) idx = 0 for iso in ISO3166_LIST: if iso.iso2 == country: self.widgets["engine_country_combo"].set_active(idx) break idx += 1 comment = engine.get("comment") self.widgets["engine_comment_entry"].set_text(comment if comment is not None else "") level = engine.get("level") try: level = int(level) if level else defaultEngineLevel except Exception: level = defaultEngineLevel self.widgets["engine_level_scale"].set_value(level) self.update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0, )) selection_changed(tree_selection) ################################################################ # restore the default options of the engine ################################################################ def engine_default_options(button): if self.cur_engine is not None and not self.selection: engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: dialog = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO) dialog.set_markup(_("Do you really want to restore the default options of the engine ?")) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.YES: for option in options: if "default" in option: option["value"] = option["default"] self.update_options() self.widgets["engine_default_options_button"].connect("clicked", engine_default_options)
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog) # Put engines into tree store allstore = Gtk.ListStore(Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(allstore) self.tv.append_column(Gtk.TreeViewColumn("Flag", Gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", False) self.tv.append_column(Gtk.TreeViewColumn("Name", name_renderer, text=1)) def name_edited(renderer, path, new_name): if self.cur_engine is not None: old_name = self.cur_engine if new_name and new_name != old_name: names = [engine["name"] for engine in discoverer.getEngines()] if new_name not in names: engine = discoverer.getEngineByName(self.cur_engine) engine["name"] = new_name discoverer.save() self.cur_engine = new_name update_store() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") name_renderer.connect("edited", name_edited) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] protocol_combo.set_name("engine_protocol_combo") cell = Gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = Gtk.ListStore(str, GObject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column(Gtk.TreeViewColumn("Option", Gtk.CellRendererText(), text=0)) optv.append_column(Gtk.TreeViewColumn("Data", KeyValueCellRenderer( self.options_store), data=1)) def update_options(*args): if self.cur_engine is not None: engines = discoverer.getEngines() names = [engine["name"] for engine in engines] # After deleting an engine we will select first if self.cur_engine not in names: self.cur_engine = engines[0]["name"] engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") self.options_store.clear() if options: options.sort(key=lambda obj: obj['name'].lower() if 'name' in obj else '') for option in options: key = option["name"] val = option if option["type"] != "button": val["default"] = option.get("default") val["value"] = option.get("value", val["default"]) self.options_store.append([key, val]) def update_store(*args): newGameDialog.createPlayerUIGlobals(discoverer) engine_names = [row[1] for row in allstore] new_items = [] # don't add the very first (Human) player to engine store for item in newGameDialog.allEngineItems: if item[1] not in engine_names: new_items.append(item) ts_iter = None for item in new_items: ts_iter = allstore.append(item) if ts_iter is not None: text_select = self.tv.get_selection() text_select.select_iter(ts_iter) update_options() update_store() def do_update_store(*args): GLib.idle_add(update_store) discoverer.connect_after("engine_discovered", do_update_store) ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) # engine = discoverer.getEngineByName(self.cur_engine) discoverer.removeEngine(self.cur_engine) discoverer.save() selection = self.tv.get_selection() result = selection.get_selected() if result is not None: model, ts_iter = result model.remove(ts_iter) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = Gtk.FileChooserDialog( _("Select engine"), mainwindow(), Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter = Gtk.FileFilter() filter.set_name(_("Executable files")) filter.add_mime_type("application/x-executable") filter.add_mime_type("application/x-sharedlib") filter.add_mime_type("application/x-ms-dos-executable") filter.add_mime_type("application/x-msdownload") filter.add_pattern("*.exe") for vm in VM_LIST: filter.add_pattern("*%s" % vm.ext) engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == Gtk.ResponseType.OK: new_engine = engine_chooser_dialog.get_filename() vm_name = None vm_args = None vmpath = "" if new_engine.lower().endswith(".exe") and sys.platform != "win32": vm_name = "wine" vmpath = shutil.which(vm_name, mode=os.R_OK | os.X_OK) if vmpath is None: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_("wine not installed")) msg_dia.run() msg_dia.hide() new_engine = "" for vm in VM_LIST: ext = os.path.splitext(new_engine)[1] if ext == vm.ext: vm_name = vm.name vm_args = vm.args vmpath = shutil.which(vm_name, mode=os.R_OK | os.X_OK) if vmpath is None: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(vm_name + _(" is not installed")) msg_dia.run() msg_dia.hide() new_engine = "" break if new_engine: vm_ext_list = [vm.ext for vm in VM_LIST] if ext not in vm_ext_list and not os.access(new_engine, os.X_OK): msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>%s is not marked executable in the filesystem</b></big>" % new_engine)) msg_dia.format_secondary_text(_("Try chmod a+x %s" % new_engine)) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return try: engine_command = [] if vmpath: engine_command.append(vmpath) if vm_args is not None: engine_command.append(vm_args) engine_command.append(new_engine) # Some engines support CECP and UCI, but main variant engines are CECP, # so we better to start with CECP this case variant_engines = ("fmax", "sjaakii", "sjeng") if any((True for eng in variant_engines if eng in new_engine.lower())): checkers = [is_cecp, is_uci] else: checkers = [is_uci, is_cecp] uci = False for checker in checkers: check_ok = checker(engine_command) if check_ok: uci = checker is is_uci break else: continue if not check_ok: # restore the original engine = discoverer.getEngineByName( self.cur_engine) engine_chooser_dialog.set_filename(engine[ "command"]) msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_( "There is something wrong with this executable")) msg_dia.run() msg_dia.hide() engine_chooser_dialog.hide() self.add = False engine_chooser_dialog.hide() return binname = os.path.split(new_engine)[1] for eng in discoverer.getEngines(): if eng["name"] == binname: binname = eng["name"] + "(1)" break self.widgets["engine_command_entry"].set_text(new_engine) self.widgets["engine_protocol_combo"].set_active(0 if uci else 1) self.widgets["engine_args_entry"].set_text("") # active = self.widgets["engine_protocol_combo"].get_active() protocol = "uci" if uci else "xboard" if vm_args is not None: vm_args = vm_args.split(",") # print(binname, new_engine, protocol, vm_name, vm_args) discoverer.addEngine(binname, new_engine, protocol, vm_name, vm_args, "unknown") self.cur_engine = binname self.add = False discoverer.discover() except Exception: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup(_("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text(_( "There is something wrong with this executable")) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ # vm args ################################################################ def vm_args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["vm_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("vm_args") if new_args != old_args: engine["vm_args"] = new_args.split() discoverer.save() self.widgets["vm_args_entry"].connect("changed", vm_args_changed) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() discoverer.save() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = Gtk.FileChooserDialog( _("Select working directory"), mainwindow(), Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dir_chooser_button = Gtk.FileChooserButton.new_with_dialog( dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory discoverer.save() dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active == 0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: command = engine.get("command") engine_command = [] vm_command = engine.get("vm_command") if vm_command is not None: engine_command.append(vm_command) vm_args = engine.get("vm_args") if vm_args is not None: engine_command.append(", ".join(vm_args)) engine_command.append(command) # is the new protocol supported by the engine? if new_protocol == "uci": check_ok = is_uci(engine_command) else: check_ok = is_cecp(engine_command) if check_ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True discoverer.discover() else: # restore the original protocol widgets["engine_protocol_combo"].set_active( 0 if old_protocol == "uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine country ################################################################ def country_changed(widget): if self.cur_engine is not None and not self.selection: engine = discoverer.getEngineByName(self.cur_engine) old_country = discoverer.getCountry(engine) new_country = ISO3166_LIST[widget.get_active()].iso2 if old_country != new_country: engine["country"] = new_country discoverer.save() # Refresh the flag in the tree view path = addDataPrefix("flags/%s.png" % new_country) if not os.path.isfile(path): path = addDataPrefix("flags/unknown.png") item = self.tv.get_selection().get_selected() if item is not None: model, ts_iter = item model[ts_iter][0] = get_pixbuf(path) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["engine_country_combo"].connect("changed", country_changed) def country_keypressed(widget, event): idx = 0 for iso in ISO3166_LIST: if (idx != 0) and ((ord(iso.country[0].lower()) == event.keyval) or (ord(iso.country[0].upper()) == event.keyval)): widget.set_active(idx) break idx += 1 self.widgets["engine_country_combo"].connect("key-press-event", country_keypressed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, tv_iter = self.tv.get_selection().get_selected() if tv_iter: self.selection = True path = store.get_path(tv_iter) indices = path.get_indices() row = indices[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) self.widgets['copy_engine_button'].set_sensitive(True) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text(engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) vm = engine.get("vm_command") self.widgets["vm_command_entry"].set_text(vm if vm is not None else "") args = [] if engine.get("vm_args") is None else engine.get("vm_args") self.widgets["vm_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") dir_choice = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(dir_choice) self.widgets["engine_protocol_combo"].set_active(0 if engine["protocol"] == "uci" else 1) self.widgets["engine_country_combo"].set_active(0) country = discoverer.getCountry(engine) idx = 0 for iso in ISO3166_LIST: if iso.iso2 == country: self.widgets["engine_country_combo"].set_active(idx) break idx += 1 update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0, )) selection_changed(tree_selection) ################################################################ # restore the default options of the engine ################################################################ def engine_default_options(button): if self.cur_engine is not None and not self.selection: engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: dialog = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO) dialog.set_markup(_("Do you really want to restore the default options of the engine ?")) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.YES: for option in options: if "default" in option: option["value"] = option["default"] discoverer.save() update_options() self.widgets["engine_default_options_button"].connect("clicked", engine_default_options)
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog) # Put engines into tree store self.allstore = Gtk.ListStore(Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(self.allstore) self.tv.append_column( Gtk.TreeViewColumn("Flag", Gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = Gtk.CellRendererText() name_renderer.set_property("editable", False) self.tv.append_column(Gtk.TreeViewColumn("Name", name_renderer, text=1)) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] protocol_combo.set_name("engine_protocol_combo") cell = Gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = Gtk.ListStore(str, str, GObject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column( Gtk.TreeViewColumn(" ", Gtk.CellRendererText(), text=0)) optv.append_column( Gtk.TreeViewColumn(_("Option"), Gtk.CellRendererText(), text=1)) optv.append_column( Gtk.TreeViewColumn(_("Value"), KeyValueCellRenderer(self.options_store), data=2)) self.update_store() def do_update_store(self, *args): GLib.idle_add(engine_dialog.update_store) discoverer.connect_after("engine_discovered", do_update_store) ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) discoverer.removeEngine(self.cur_engine) selection = self.tv.get_selection() result = selection.get_selected() if result is not None: model, ts_iter = result model.remove(ts_iter) if model.iter_n_children() == 0: clearView() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = Gtk.FileChooserDialog( _("Select engine"), mainwindow(), Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter = Gtk.FileFilter() filter.set_name(_("Executable files")) filter.add_mime_type("application/x-executable") filter.add_mime_type("application/x-sharedlib") filter.add_mime_type("application/x-ms-dos-executable") filter.add_mime_type("application/x-msdownload") filter.add_pattern("*.exe") for vm in VM_LIST: filter.add_pattern("*%s" % vm.ext) engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == Gtk.ResponseType.OK: new_engine = engine_chooser_dialog.get_filename() binname = os.path.split(new_engine)[1] ext = os.path.splitext(new_engine)[1] # Verify if the engine already exists under the same name if new_engine != "": for eng in discoverer.getEngines(): if eng["command"] == new_engine: msg_dia = Gtk.MessageDialog( mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( _("The engine is already installed under the same name" )) msg_dia.run() msg_dia.hide() new_engine = "" break # Detect the host application if new_engine != "": vm_name = None vm_args = None vmpath = "" # Scripting for vm in VM_LIST: if ext == vm.ext: vm_name = vm.name vm_args = vm.args break # Wine for Windows application under Linux if vm_name is None and new_engine.lower().endswith( ".exe") and sys.platform != "win32": vm_name = "wine" # Check that the interpreter is available if vm_name is not None: vmpath = shutil.which(vm_name, mode=os.R_OK | os.X_OK) if vmpath is None: msg_dia = Gtk.MessageDialog( mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( vm_name + _(" is not installed")) msg_dia.run() msg_dia.hide() new_engine = "" # Next checks if new_engine: vm_ext_list = [vm.ext for vm in VM_LIST] if ext not in vm_ext_list and not os.access( new_engine, os.X_OK): msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>%s is not marked executable in the filesystem</b></big>" % new_engine)) msg_dia.format_secondary_text( _("Try chmod a+x %s" % new_engine)) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return try: engine_command = [] if vmpath: engine_command.append(vmpath) if vm_args is not None: engine_command += vm_args engine_command.append(new_engine) # Search the engines based on the most expectable protocol refeng = discoverer.getReferencedEngine(binname) if refeng is not None and refeng[ "protocol"] == "xboard": checkers = [is_cecp, is_uci] else: checkers = [is_uci, is_cecp] uci = False for checker in checkers: check_ok = checker(engine_command) if check_ok: uci = checker is is_uci break if not check_ok: # restore the original engine = discoverer.getEngineByName( self.cur_engine) engine_chooser_dialog.set_filename( engine["command"]) msg_dia = Gtk.MessageDialog( mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( _("There is something wrong with this executable" )) msg_dia.run() msg_dia.hide() engine_chooser_dialog.hide() self.add = False engine_chooser_dialog.hide() return self.widgets["engine_command_entry"].set_text( new_engine) self.widgets["engine_protocol_combo"].set_active( 0 if uci else 1) self.widgets["engine_args_entry"].set_text("") # active = self.widgets["engine_protocol_combo"].get_active() protocol = "uci" if uci else "xboard" # print(binname, new_engine, protocol, vm_name, vm_args) discoverer.addEngine(binname, new_engine, protocol, vm_name, vm_args) self.cur_engine = binname self.add = False discoverer.discover() except Exception: msg_dia = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK) msg_dia.set_markup( _("<big><b>Unable to add %s</b></big>" % new_engine)) msg_dia.format_secondary_text( _("There is something wrong with this executable")) msg_dia.run() msg_dia.hide() self.add = False engine_chooser_dialog.hide() return else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ # add in mass button ################################################################ def addInMass(button): # Ask the user to select a folder folder_dlg = Gtk.FileChooserDialog( _("Choose a folder"), None, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) answer = folder_dlg.run() path = folder_dlg.get_filename() folder_dlg.destroy() # Search for the engines if answer != Gtk.ResponseType.OK: return False possibleFiles = listEnginesFromPath(path) # Remove the existing engines from the list def isNewEngine(path): sfn = os.path.basename(path) for engine in discoverer.getEngines(): if sfn in engine.get( "command"): # The short name must be unique return False return True possibleFiles = [fn for fn in possibleFiles if isNewEngine(fn)] if len(possibleFiles) == 0: return False # Prepare the result in a dialog mass_dialog = self.widgets["engine_list_dialog"] self.widgets["mass_path_label"].set_text(path) mass_list = self.widgets["mass_list_treeview"] if len(mass_list.get_columns()) == 0: # Not initialized yet mass_store = Gtk.ListStore(bool, str) mass_list.set_model(mass_store) def checkbox_renderer_cb(cell, path, model): model[path][0] = not model[path][0] return checkbox_renderer = Gtk.CellRendererToggle() checkbox_renderer.set_property("activatable", True) checkbox_renderer.connect("toggled", checkbox_renderer_cb, mass_store) mass_list.append_column( Gtk.TreeViewColumn(_("Import"), checkbox_renderer, active=0)) mass_list.append_column( Gtk.TreeViewColumn(_("File name"), Gtk.CellRendererText(), text=1)) else: mass_store = mass_list.get_model() mass_store.clear() for fn in possibleFiles: mass_store.append([False, fn[len(path):]]) # Show the dialog answer = mass_dialog.run() mass_dialog.hide() if answer != Gtk.ResponseType.OK.real: return False # Add the new engines self.add = True found = False for entry in mass_store: if entry[0]: newengine = discoverer.getReferencedEngine(path + entry[1]) if newengine is not None: discoverer.addEngineFromReference(newengine) found = True self.add = False if found: discoverer.discover() return True self.widgets["mass_engine_button"].connect("clicked", addInMass) ################################################################ def clearView(): self.selection = True self.cur_engine = None self.widgets["vm_command_entry"].set_text("") self.widgets["vm_args_entry"].set_text("") self.widgets["engine_command_entry"].set_text("") self.widgets["engine_args_entry"].set_text("") self.widgets["engine_protocol_combo"].set_active(0) self.widgets["engine_country_combo"].set_active(0) self.widgets["engine_comment_entry"].set_text("") self.widgets["engine_level_scale"].set_value(ENGINE_DEFAULT_LEVEL) self.options_store.clear() self.selection = False ################################################################ # vm args ################################################################ def vm_args_changed(widget): if self.cur_engine is not None and not self.selection: new_args = self.widgets["vm_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("vm_args") if new_args != old_args: engine["vm_args"] = new_args.split() self.widgets["vm_args_entry"].connect("changed", vm_args_changed) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None and not self.selection: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = Gtk.FileChooserDialog( _("Select working directory"), mainwindow(), Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dir_chooser_button = Gtk.FileChooserButton.new_with_dialog( dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active == 0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: command = engine.get("command") engine_command = [] vm_command = engine.get("vm_command") if vm_command is not None: engine_command.append(vm_command) vm_args = engine.get("vm_args") if vm_args is not None: engine_command.append(", ".join(vm_args)) engine_command.append(command) # is the new protocol supported by the engine? if new_protocol == "uci": check_ok = is_uci(engine_command) else: check_ok = is_cecp(engine_command) if check_ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True discoverer.discover() else: # restore the original protocol widgets["engine_protocol_combo"].set_active( 0 if old_protocol == "uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine country ################################################################ def country_changed(widget): if self.cur_engine is not None and not self.selection: engine = discoverer.getEngineByName(self.cur_engine) old_country = discoverer.getCountry(engine) new_country = ISO3166_LIST[widget.get_active()].iso2 if old_country != new_country: engine["country"] = new_country # Refresh the flag in the tree view path = addDataPrefix("flags/%s.png" % new_country) if not os.path.isfile(path): path = addDataPrefix("flags/unknown.png") item = self.tv.get_selection().get_selected() if item is not None: model, ts_iter = item model[ts_iter][0] = get_pixbuf(path) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") self.widgets["engine_country_combo"].connect("changed", country_changed) def country_keypressed(widget, event): idx = 0 for iso in ISO3166_LIST: if (idx != 0) and ( (ord(iso.country[0].lower()) == event.keyval) or (ord(iso.country[0].upper()) == event.keyval)): widget.set_active(idx) break idx += 1 self.widgets["engine_country_combo"].connect("key-press-event", country_keypressed) ################################################################ # comment changed ################################################################ def comment_changed(widget): if self.cur_engine is not None and not self.selection: new_comment = self.widgets["engine_comment_entry"].get_text( ).strip() engine = discoverer.getEngineByName(self.cur_engine) old_comment = engine.get("comment") if new_comment != old_comment: engine["comment"] = new_comment self.widgets["engine_comment_entry"].connect("changed", comment_changed) ################################################################ # level changed ################################################################ def level_changed(widget): if self.cur_engine is not None and not self.selection: new_level = widget.get_value() engine = discoverer.getEngineByName(self.cur_engine) old_level = engine.get("level") if new_level != old_level: engine["level"] = int(new_level) self.widgets["engine_level_scale"].connect("value-changed", level_changed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, tv_iter = self.tv.get_selection().get_selected() if tv_iter: self.selection = True path = store.get_path(tv_iter) indices = path.get_indices() row = indices[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text( engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) vm = engine.get("vm_command") self.widgets["vm_command_entry"].set_text( vm if vm is not None else "") args = [] if engine.get("vm_args") is None else engine.get( "vm_args") self.widgets["vm_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") dir_choice = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(dir_choice) self.widgets["engine_protocol_combo"].set_active( 0 if engine["protocol"] == "uci" else 1) self.widgets["engine_country_combo"].set_active(0) country = discoverer.getCountry(engine) idx = 0 for iso in ISO3166_LIST: if iso.iso2 == country: self.widgets["engine_country_combo"].set_active(idx) break idx += 1 comment = engine.get("comment") self.widgets["engine_comment_entry"].set_text( comment if comment is not None else "") level = engine.get("level") try: level = int(level) except Exception: level = ENGINE_DEFAULT_LEVEL self.widgets["engine_level_scale"].set_value(level) self.update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0, )) selection_changed(tree_selection) ################################################################ # restore the default options of the engine ################################################################ def engine_default_options(button): if self.cur_engine is not None and not self.selection: engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: dialog = Gtk.MessageDialog(mainwindow(), type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO) dialog.set_markup( _("Do you really want to restore the default options of the engine ?" )) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.YES: for option in options: if "default" in option: option["value"] = option["default"] self.update_options() self.widgets["engine_default_options_button"].connect( "clicked", engine_default_options)
def __init__(self, widgets): self.widgets = widgets self.dialog = self.widgets["manage_engines_dialog"] self.cur_engine = None self.default_workdir = getEngineDataPrefix() uistuff.keepWindowSize("engineswindow", self.dialog, defaultSize=(600, 500)) # Put engines into tree store allstore = gtk.ListStore(gtk.gdk.Pixbuf, str) self.tv = self.widgets["engines_treeview"] self.tv.set_model(allstore) self.tv.append_column(gtk.TreeViewColumn( "Flag", gtk.CellRendererPixbuf(), pixbuf=0)) name_renderer = gtk.CellRendererText() name_renderer.set_property("editable", True) self.tv.append_column(gtk.TreeViewColumn("Name", name_renderer, text=1)) def name_edited(renderer, path, new_name): if self.cur_engine is not None: old_name = self.cur_engine if new_name and new_name != old_name: names = [engine["name"] for engine in discoverer.getEngines()] if new_name not in names: engine = discoverer.getEngineByName(self.cur_engine) engine["name"] = new_name discoverer.save() self.cur_engine = new_name update_store() # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") name_renderer.connect("edited", name_edited) # Add cell renderer to protocol combo column protocol_combo = self.widgets["engine_protocol_combo"] cell = gtk.CellRendererText() protocol_combo.pack_start(cell, True) protocol_combo.add_attribute(cell, "text", 0) # Add columns and cell renderers to options treeview self.options_store = gtk.ListStore(str, gobject.TYPE_PYOBJECT) optv = self.widgets["options_treeview"] optv.set_model(self.options_store) optv.append_column(gtk.TreeViewColumn( "Option", gtk.CellRendererText(), text=0)) optv.append_column(gtk.TreeViewColumn( "Data", KeyValueCellRenderer(self.options_store), data=1)) def update_options(*args): if self.cur_engine is not None: engines = discoverer.getEngines() names = [engine["name"] for engine in engines] # After deleting an engine we will select first if self.cur_engine not in names: self.cur_engine = engines[0]["name"] engine = discoverer.getEngineByName(self.cur_engine) options = engine.get("options") if options: self.options_store.clear() for option in options: key = option["name"] val = option if option["type"] != "button": val["default"] = option.get("default") val["value"] = option.get("value", val["default"]) self.options_store.append([key, val]) def update_store(*args): allstore.clear() newGameDialog.createPlayerUIGlobals(discoverer) # don't add the very first (Human) player to engine store for item in newGameDialog.playerItems[0][1:]: allstore.append(item) update_options() update_store() ################################################################ # remove button ################################################################ def remove(button): if self.cur_engine is not None: self.widgets['remove_engine_button'].set_sensitive(False) engine = discoverer.getEngineByName(self.cur_engine) discoverer.removeEngine(self.cur_engine) discoverer.save() update_store(discoverer) # Notify playerCombos in NewGameTasker discoverer.emit("all_engines_discovered") ts = self.tv.get_selection() ts.select_path((0,)) self.widgets["remove_engine_button"].connect("clicked", remove) ################################################################ # add button ################################################################ engine_chooser_dialog = gtk.FileChooserDialog(_("Select engine"), None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) filter = gtk.FileFilter() filter.set_name(_("Chess engines")) filter.add_mime_type("application/x-executable") engine_chooser_dialog.add_filter(filter) self.add = False def add(button): self.add = True response = engine_chooser_dialog.run() if response == gtk.RESPONSE_OK: new_engine = engine_chooser_dialog.get_filename() if new_engine: try: uci = is_uci(new_engine) if not uci: if not is_cecp(new_engine): # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) print "Maybe not a chess engine" return path, binname = os.path.split(new_engine) for e in discoverer.getEngines(): if e["name"] == binname: binname = e["name"] + "(1)" break self.widgets["engine_name_entry"].set_text(binname) self.widgets["engine_command_entry"].set_text(new_engine) self.widgets["engine_protocol_combo"].set_active(0 if uci else 1) self.widgets["engine_args_entry"].set_text("") name = self.widgets["engine_name_entry"].get_text().strip() active = self.widgets["engine_protocol_combo"].get_active() protocol = "uci" if active==0 else "xboard" discoverer.addEngine(name, new_engine, protocol) self.cur_engine = name glock_connect_after(discoverer, "engine_discovered", update_store) self.add = False discoverer.start() except: print "There is something wrong with this executable" else: # restore the original engine = discoverer.getEngineByName(self.cur_engine) engine_chooser_dialog.set_filename(engine["command"]) engine_chooser_dialog.hide() self.widgets["add_engine_button"].connect("clicked", add) ################################################################ # engine args ################################################################ def args_changed(widget): if self.cur_engine is not None: new_args = self.widgets["engine_args_entry"].get_text().strip() engine = discoverer.getEngineByName(self.cur_engine) old_args = engine.get("args") if new_args != old_args: engine["args"] = new_args.split() discoverer.save() self.widgets["engine_args_entry"].connect("changed", args_changed) ################################################################ # engine working directory ################################################################ dir_chooser_dialog = gtk.FileChooserDialog(_("Select working directory"), None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dir_chooser_button = gtk.FileChooserButton(dir_chooser_dialog) self.widgets["dirChooserDock"].add(dir_chooser_button) dir_chooser_button.show() def select_dir(button): new_directory = dir_chooser_dialog.get_filename() engine = discoverer.getEngineByName(self.cur_engine) old_directory = engine.get("workingDirectory") if new_directory != old_directory and new_directory != self.default_workdir: engine["workingDirectory"] = new_directory discoverer.save() dir_chooser_button.connect("current-folder-changed", select_dir) ################################################################ # engine protocol ################################################################ def protocol_changed(widget): if self.cur_engine is not None and not self.add and not self.selection: active = self.widgets["engine_protocol_combo"].get_active() new_protocol = "uci" if active==0 else "xboard" engine = discoverer.getEngineByName(self.cur_engine) old_protocol = engine["protocol"] if new_protocol != old_protocol: engine_command = engine_chooser_dialog.get_filename() # is the new protocol supported by the engine? if new_protocol == "uci": ok = is_uci(engine_command) else: ok = is_cecp(engine_command) if ok: # discover engine options for new protocol engine["protocol"] = new_protocol engine["recheck"] = True glock_connect_after(discoverer, "engine_discovered", update_options) discoverer.start() else: # restore the original protocol widgets["engine_protocol_combo"].set_active(0 if old_protocol=="uci" else 1) self.widgets["engine_protocol_combo"].connect("changed", protocol_changed) ################################################################ # engine tree ################################################################ self.selection = False def selection_changed(treeselection): store, iter = self.tv.get_selection().get_selected() if iter: self.selection = True row = store.get_path(iter)[0] name = store[row][1] self.cur_engine = name engine = discoverer.getEngineByName(name) self.widgets['copy_engine_button'].set_sensitive(True) if "PyChess.py" in engine["command"]: self.widgets['remove_engine_button'].set_sensitive(False) else: self.widgets['remove_engine_button'].set_sensitive(True) self.widgets["engine_command_entry"].set_text(engine["command"]) engine_chooser_dialog.set_filename(engine["command"]) args = [] if engine.get("args") is None else engine.get("args") self.widgets["engine_args_entry"].set_text(' '.join(args)) directory = engine.get("workingDirectory") d = directory if directory is not None else self.default_workdir dir_chooser_dialog.set_current_folder(d) self.widgets["engine_protocol_combo"].set_active(0 if engine["protocol"]=="uci" else 1) update_options() self.selection = False tree_selection = self.tv.get_selection() tree_selection.connect('changed', selection_changed) tree_selection.select_path((0,))