Exemplo n.º 1
0
        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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
        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
Exemplo n.º 4
0
    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())
Exemplo n.º 5
0
    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
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
            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)
Exemplo n.º 9
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=(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, ))
Exemplo n.º 10
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, ))
Exemplo n.º 11
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)
Exemplo n.º 12
0
            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 = ""
Exemplo n.º 13
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"]
        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,))
Exemplo n.º 14
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)
Exemplo n.º 15
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
        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)
Exemplo n.º 16
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 += 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)
Exemplo n.º 17
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=(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,))