Ejemplo n.º 1
0
    def open_chessfile(self, filename):
        if self.first_run:
            self.init_layout()
            self.first_run = False

        perspective_manager.activate_perspective("database")

        self.progress_dialog.set_title(_("Open"))
        self.spinner.show()
        self.spinner.start()

        def opening():
            if filename.endswith(".pgn"):
                GLib.idle_add(self.progressbar.show)
                GLib.idle_add(self.progressbar.set_text,
                              _("Opening chessfile..."))
                chessfile = PGNFile(protoopen(filename), self.progressbar)
                self.importer = chessfile.init_tag_database()
                if self.importer is not None and self.importer.cancel:
                    chessfile.tag_database.close()
                    if os.path.isfile(chessfile.sqlite_path):
                        os.remove(chessfile.sqlite_path)
                    chessfile = None
                else:
                    chessfile.init_scoutfish()
                    chessfile.init_chess_db()
            elif filename.endswith(".epd"):
                self.importer = None
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".olv"):
                self.importer = None
                chessfile = olv.load(protoopen(filename, encoding="utf-8"))
            elif filename.endswith(".fen"):
                self.importer = None
                chessfile = fen.load(protoopen(filename))
            else:
                self.importer = None
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.spinner.hide)
            GLib.idle_add(self.progress_dialog.hide)

            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)
            else:
                if self.chessfile is None:
                    self.close(None)

        thread = threading.Thread(target=opening)
        thread.daemon = True
        thread.start()

        response = self.progress_dialog.run()
        if response == Gtk.ResponseType.CANCEL:
            if self.importer is not None:
                self.importer.do_cancel()
        self.progress_dialog.hide()
Ejemplo n.º 2
0
    def row_activated(self, widget, path, col):
        rec, ply = self.get_record(path)
        if rec is None:
            return

        # Enable unfinished games to continue from newgamedialog
        if rec["Result"] not in UNDOABLE_STATES:
            newGameDialog.EnterNotationExtension.run()
            model = self.persp.chessfile.loadToModel(rec)
            text = pgn.save(StringIO(), model)
            newGameDialog.EnterNotationExtension.sourcebuffer.set_text(text)
            return

        self.gamemodel = GameModel()

        variant = rec["Variant"]
        if variant:
            self.gamemodel.tags["Variant"] = variant

        # Lichess exports study .pgn without White and Black tags
        wp = "" if rec["White"] is None else rec["White"]
        bp = "" if rec["Black"] is None else rec["Black"]
        p0 = (LOCAL, Human, (WHITE, wp), wp)
        p1 = (LOCAL, Human, (BLACK, bp), bp)
        self.persp.chessfile.loadToModel(rec, -1, self.gamemodel)

        self.gamemodel.endstatus = (self.gamemodel.status
                                    if self.gamemodel.status in UNDOABLE_STATES
                                    else None)
        self.gamemodel.status = WAITING_TO_START

        perspective_manager.activate_perspective("games")
        perspective = perspective_manager.get_perspective("games")
        create_task(perspective.generalStart(self.gamemodel, p0, p1))
Ejemplo n.º 3
0
    def open_chessfile(self, filename):
        if self.gamelist is None:
            self.init_layout()
        perspective_manager.activate_perspective("database")

        self.progress_dialog.set_title(_("Open"))
        self.progressbar0.hide()
        self.progressbar1.show()
        self.progressbar1.set_text("Importing game headers...")
        self.spinner.show()
        self.spinner.start()

        def opening():
            if filename.endswith(".pgn"):
                chessfile = pgn.load(protoopen(filename), self.progressbar1)
            elif filename.endswith(".epd"):
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".fen"):
                chessfile = fen.load(protoopen(filename))
            else:
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.progress_dialog.hide)
            if chessfile is not None:
                GLib.idle_add(self.emit, "chessfile_opened", chessfile)

        thread = threading.Thread(target=opening)
        thread.daemon = True
        thread.start()

        response = self.progress_dialog.run()
        if response == Gtk.ResponseType.CANCEL:
            self.importer.do_cancel()
        self.progress_dialog.hide()
Ejemplo n.º 4
0
    def open_chessfile(self, filename):
        if self.first_run:
            self.init_layout()
            self.first_run = False

        perspective_manager.activate_perspective("database")

        self.progress_dialog.set_title(_("Open"))
        self.progressbar0.hide()
        self.spinner.show()
        self.spinner.start()

        def opening():
            if filename.endswith(".pgn"):
                GLib.idle_add(self.progressbar1.show)
                GLib.idle_add(self.progressbar1.set_text, _("Opening chessfile..."))
                chessfile = PGNFile(protoopen(filename), self.progressbar1)
                self.importer = chessfile.init_tag_database()
                if self.importer is not None and self.importer.cancel:
                    chessfile.tag_database.close()
                    if os.path.isfile(chessfile.sqlite_path):
                        os.remove(chessfile.sqlite_path)
                    chessfile = None
                else:
                    chessfile.init_scoutfish()
                    chessfile.init_chess_db()
            elif filename.endswith(".epd"):
                self.importer = None
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".olv"):
                self.importer = None
                chessfile = olv.load(protoopen(filename, encoding="utf-8"))
            elif filename.endswith(".fen"):
                self.importer = None
                chessfile = fen.load(protoopen(filename))
            else:
                self.importer = None
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.progress_dialog.hide)

            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)
            else:
                if self.chessfile is None:
                    self.close(None)

        thread = threading.Thread(target=opening)
        thread.daemon = True
        thread.start()

        response = self.progress_dialog.run()
        if response == Gtk.ResponseType.CANCEL:
            if self.importer is not None:
                self.importer.do_cancel()
        self.progress_dialog.hide()
Ejemplo n.º 5
0
    def attachGameWidget(self, gmwidg):
        log.debug("attachGameWidget: %s" % gmwidg)
        if self.first_run:
            self.init_layout()
            self.first_run = False
        perspective_manager.activate_perspective("games")

        gmwidg.panels = [
            panel.Sidepanel().load(gmwidg) for panel in self.sidePanels
        ]
        self.key2gmwidg[gmwidg.notebookKey] = gmwidg
        headbook = self.getheadbook()

        headbook.append_page(gmwidg.notebookKey, gmwidg.tabcontent)
        gmwidg.notebookKey.show_all()

        if hasattr(headbook, "set_tab_reorderable"):
            headbook.set_tab_reorderable(gmwidg.notebookKey, True)

        def callback(notebook, gpointer, page_num, gmwidg):
            if notebook.get_nth_page(page_num) == gmwidg.notebookKey:
                gmwidg.infront()
                if gmwidg.gamemodel.players and gmwidg.gamemodel.isObservationGame(
                ):
                    gmwidg.light_on_off(False)
                    text = gmwidg.game_info_label.get_text()
                    gmwidg.game_info_label.set_markup(
                        '<span color="black" weight="bold">%s</span>' % text)

        self.key2cid[gmwidg.notebookKey] = headbook.connect_after(
            "switch-page", callback, gmwidg)
        gmwidg.infront()

        align = gamewidget.createAlignment(0, 0, 0, 0)
        align.show()
        align.add(gmwidg.infobar)
        self.notebooks["messageArea"].append_page(align, None)
        self.notebooks["board"].append_page(gmwidg.boardvbox, None)
        gmwidg.boardvbox.show_all()
        for panel, instance in zip(self.sidePanels, gmwidg.panels):
            self.notebooks[panel_name(panel.__name__)].append_page(
                instance, None)
            instance.show_all()
        self.notebooks["buttons"].append_page(gmwidg.stat_hbox, None)
        gmwidg.stat_hbox.show_all()

        if headbook.get_n_pages() == 1:
            self.show_tabs(not conf.get("hideTabs"))
        else:
            # We should always show tabs if more than one exists
            self.show_tabs(True)

        headbook.set_current_page(-1)

        widgets = gamewidget.getWidgets()
        if headbook.get_n_pages(
        ) == 1 and not widgets["show_sidepanels"].get_active():
            self.zoomToBoard(True)
Ejemplo n.º 6
0
    def activate(self):
        if self.first_run:
            self.init_layout()
            self.first_run = False

        learn_home = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        box = Gtk.Box()

        self.tv = Gtk.TreeView()

        color = Gdk.RGBA()
        color.parse("lightblue")

        for i, col in enumerate((_("lichess"), _("wtharvey"), _("yacpdb"), _("lessons"))):
            renderer = Gtk.CellRendererProgress()
            renderer.set_orientation(Gtk.Orientation.VERTICAL)
            renderer.props.height = 100
            renderer.props.inverted = True
            renderer.props.cell_background_rgba = color
            column = Gtk.TreeViewColumn(col, renderer, text=i * 2, value=i * 2 + 1)
            self.tv.append_column(column)

        self.store = Gtk.ListStore(str, int, str, int, str, int, str, int)

        self.update_progress(None, None, None)

        self.tv.set_model(self.store)
        self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE)

        puzzles_solving_progress.connect("progress_updated", self.update_progress)
        lessons_solving_progress.connect("progress_updated", self.update_progress)

        box.pack_start(self.tv, False, False, 6)

        label = Gtk.Label(xpad=6, xalign=0)
        label.set_markup("<b>%s</b>" % _("Progress"))
        learn_home.pack_start(label, False, False, 6)

        learn_home.pack_start(box, False, False, 0)

        learn_home.show_all()

        if not self.first_run:
            self.notebooks["learnhome"].remove_page(-1)
        self.notebooks["learnhome"].append_page(learn_home)

        self.panels = [panel.Sidepanel().load(self) for panel in self.sidePanels]

        for panel, instance in zip(self.sidePanels, self.panels):
            if not self.first_run:
                self.notebooks[panel.__name__].remove_page(-1)
            self.notebooks[panel.__name__].append_page(instance)
            instance.show()

        perspective_manager.activate_perspective("learn")
Ejemplo n.º 7
0
    def attachGameWidget(self, gmwidg):
        log.debug("attachGameWidget: %s" % gmwidg)
        if self.first_run:
            self.init_layout()
            self.first_run = False
        perspective_manager.activate_perspective("games")

        gmwidg.panels = [panel.Sidepanel().load(gmwidg) for panel in self.sidePanels]
        self.key2gmwidg[gmwidg.notebookKey] = gmwidg
        headbook = self.getheadbook()

        headbook.append_page(gmwidg.notebookKey, gmwidg.tabcontent)
        gmwidg.notebookKey.show_all()

        if hasattr(headbook, "set_tab_reorderable"):
            headbook.set_tab_reorderable(gmwidg.notebookKey, True)

        def callback(notebook, gpointer, page_num, gmwidg):
            if notebook.get_nth_page(page_num) == gmwidg.notebookKey:
                gmwidg.infront()
                if gmwidg.gamemodel.players and gmwidg.gamemodel.isObservationGame():
                    gmwidg.light_on_off(False)
                    text = gmwidg.game_info_label.get_text()
                    gmwidg.game_info_label.set_markup(
                        '<span color="black" weight="bold">%s</span>' % text)

        self.key2cid[gmwidg.notebookKey] = headbook.connect_after("switch-page", callback, gmwidg)
        gmwidg.infront()

        align = gamewidget.createAlignment(0, 0, 0, 0)
        align.show()
        align.add(gmwidg.infobar)
        self.notebooks["messageArea"].append_page(align, None)
        self.notebooks["board"].append_page(gmwidg.boardvbox, None)
        gmwidg.boardvbox.show_all()
        for panel, instance in zip(self.sidePanels, gmwidg.panels):
            self.notebooks[panel_name(panel.__name__)].append_page(instance, None)
            instance.show_all()
        self.notebooks["buttons"].append_page(gmwidg.stat_hbox, None)
        gmwidg.stat_hbox.show_all()

        if headbook.get_n_pages() == 1:
            self.show_tabs(not conf.get("hideTabs"))
        else:
            # We should always show tabs if more than one exists
            self.show_tabs(True)

        headbook.set_current_page(-1)

        widgets = gamewidget.getWidgets()
        if headbook.get_n_pages() == 1 and not widgets["show_sidepanels"].get_active():
            self.zoomToBoard(True)
    def find_in_database(self):
        persp = perspective_manager.get_perspective("database")
        if persp.chessfile is None:
            dialogue = Gtk.MessageDialog(
                pychess.widgets.mainwindow(),
                type=Gtk.MessageType.ERROR,
                buttons=Gtk.ButtonsType.OK,
                message_format=_("No database is currently opened."),
            )
            dialogue.run()
            dialogue.destroy()
            return

        view = self.board.view
        shown_board = self.gamemodel.getBoardAtPly(view.shown, view.shown_variation_idx)
        fen = shown_board.asFen()

        tool, found = persp.chessfile.has_position(fen)
        if not found:
            dialogue = Gtk.MessageDialog(
                pychess.widgets.mainwindow(),
                type=Gtk.MessageType.WARNING,
                buttons=Gtk.ButtonsType.OK,
                message_format=_("The position does not exist in the database."),
            )
            dialogue.run()
            dialogue.destroy()
        else:
            if tool == TOOL_CHESSDB:
                persp.chessfile.set_fen_filter(fen)
            elif tool == TOOL_SCOUTFISH:
                dialogue = Gtk.MessageDialog(
                    pychess.widgets.mainwindow(),
                    type=Gtk.MessageType.QUESTION,
                    buttons=Gtk.ButtonsType.YES_NO,
                    message_format=_(
                        "An approximate position has been found. Do you want to display it ?"
                    ),
                )
                response = dialogue.run()
                dialogue.destroy()
                if response != Gtk.ResponseType.YES:
                    return

                persp.chessfile.set_scout_filter({"sub-fen": fen})
            else:
                raise RuntimeError("Internal error")
            persp.gamelist.ply = view.shown
            persp.gamelist.load_games()
            perspective_manager.activate_perspective("database")
Ejemplo n.º 9
0
    def open_chessfile(self, filename):
        if filename.endswith(".pdb"):
            chessfile = database.load(filename)
        elif filename.endswith(".pgn"):
            chessfile = pgn.load(protoopen(filename))
        elif filename.endswith(".epd"):
            chessfile = epd.load(protoopen(filename))
        elif filename.endswith(".fen"):
            chessfile = fen.load(protoopen(filename))
        else:
            return

        if self.gamelist is None:
            self.init_layout()

        perspective_manager.activate_perspective("database")
        self.emit("chessfile_opened", chessfile)
Ejemplo n.º 10
0
    def row_activated(self, widget, path, col):
        gameno = self.get_gameno(path)

        self.gamemodel = GameModel()

        variant = self.chessfile.get_variant(gameno)
        if variant:
            self.gamemodel.tags["Variant"] = variant

        wp, bp = self.chessfile.get_player_names(gameno)
        p0 = (LOCAL, Human, (WHITE, wp), wp)
        p1 = (LOCAL, Human, (BLACK, bp), bp)
        self.chessfile.loadToModel(gameno, -1, self.gamemodel)

        self.gamemodel.status = WAITING_TO_START
        game_handler.generalStart(self.gamemodel, p0, p1)

        perspective_manager.activate_perspective("games")
Ejemplo n.º 11
0
    def row_activated(self, widget, path, col):
        rec, ply = self.get_record(path)

        self.gamemodel = GameModel()

        variant = rec[13]
        if variant:
            self.gamemodel.tags["Variant"] = variant

        wp, bp = rec["White"], rec["Black"]
        p0 = (LOCAL, Human, (WHITE, wp), wp)
        p1 = (LOCAL, Human, (BLACK, bp), bp)
        self.chessfile.loadToModel(rec, -1, self.gamemodel)

        self.gamemodel.endstatus = self.gamemodel.status if self.gamemodel.status in UNDOABLE_STATES else UNKNOWN_STATE
        self.gamemodel.status = WAITING_TO_START
        game_handler.generalStart(self.gamemodel, p0, p1)

        perspective_manager.activate_perspective("games")
Ejemplo n.º 12
0
    def row_activated(self, widget, path, col):
        game_id = self.liststore[self.modelsort.convert_path_to_child_path(
            path)[0]][0]
        gameno = self.id_list.index(game_id)

        self.gamemodel = GameModel()

        variant = self.chessfile.get_variant(gameno)
        if variant:
            self.gamemodel.tags["Variant"] = variant

        wp, bp = self.chessfile.get_player_names(gameno)
        p0 = (LOCAL, Human, (WHITE, wp), wp)
        p1 = (LOCAL, Human, (BLACK, bp), bp)
        self.chessfile.loadToModel(gameno, -1, self.gamemodel)

        self.gamemodel.status = WAITING_TO_START
        game_handler.generalStart(self.gamemodel, p0, p1)

        perspective_manager.activate_perspective("games")
Ejemplo n.º 13
0
    def find_in_database(self):
        persp = perspective_manager.get_perspective("database")
        if persp.chessfile is None:
            return

        view = self.board.view
        shown_board = self.gamemodel.getBoardAtPly(view.shown, view.shown_variation_idx)
        fen = shown_board.asFen()

        result = persp.chessfile.get_book_moves(fen)
        if len(result) == 0:
            dialogue = Gtk.MessageDialog(pychess.widgets.mainwindow(), type=Gtk.MessageType.WARNING,
                                         buttons=Gtk.ButtonsType.OK,
                                         message_format=_("Position not in current database"))
            dialogue.run()
            dialogue.destroy()
        else:
            persp.chessfile.set_fen_filter(fen)
            persp.gamelist.ply = view.shown
            persp.gamelist.load_games()
            perspective_manager.activate_perspective("database")
Ejemplo n.º 14
0
    def activate(self):
        if self.first_run:
            self.init_layout()
            self.first_run = False

        learn_home = Gtk.Box()
        learn_home.add(Gtk.Label("Practice! Practice! Practice!"))
        learn_home.show_all()

        if not self.first_run:
            self.notebooks["learnhome"].remove_page(-1)
        self.notebooks["learnhome"].append_page(learn_home)

        self.panels = [panel.Sidepanel().load(self) for panel in self.sidePanels]

        for panel, instance in zip(self.sidePanels, self.panels):
            if not self.first_run:
                self.notebooks[panel.__name__].remove_page(-1)
            self.notebooks[panel.__name__].append_page(instance)
            instance.show()

        perspective_manager.activate_perspective("learn")
Ejemplo n.º 15
0
    def open_chessfile(self, filename):
        if self.chessfile is None:
            self.init_layout()

        perspective_manager.activate_perspective("database")

        self.progress_dialog.set_title(_("Open"))
        self.progressbar0.hide()
        self.progressbar1.show()
        self.progressbar1.set_text("Importing game headers...")
        self.spinner.show()
        self.spinner.start()

        def opening():
            if filename.endswith(".pgn"):
                chessfile = pgn.load(protoopen(filename), self.progressbar1)
            elif filename.endswith(".epd"):
                chessfile = epd.load(protoopen(filename))
            elif filename.endswith(".fen"):
                chessfile = fen.load(protoopen(filename))
            else:
                chessfile = None

            GLib.idle_add(self.spinner.stop)
            GLib.idle_add(self.progress_dialog.hide)
            if chessfile is not None:
                self.chessfile = chessfile
                self.chessfiles.append(chessfile)
                GLib.idle_add(self.emit, "chessfile_opened0", chessfile)

        thread = threading.Thread(target=opening)
        thread.daemon = True
        thread.start()

        response = self.progress_dialog.run()
        if response == Gtk.ResponseType.CANCEL:
            self.importer.do_cancel()
        self.progress_dialog.hide()
Ejemplo n.º 16
0
    def row_activated(self, widget, path, col):
        rec, ply = self.get_record(path)
        if rec is None:
            return

        self.gamemodel = GameModel()

        variant = rec["Variant"]
        if variant:
            self.gamemodel.tags["Variant"] = variant

        # Lichess exports study .pgn without White and Black tags
        wp = "" if rec["White"] is None else rec["White"]
        bp = "" if rec["Black"] is None else rec["Black"]
        p0 = (LOCAL, Human, (WHITE, wp), wp)
        p1 = (LOCAL, Human, (BLACK, bp), bp)
        self.persp.chessfile.loadToModel(rec, -1, self.gamemodel)

        self.gamemodel.endstatus = self.gamemodel.status if self.gamemodel.status in UNDOABLE_STATES else None
        self.gamemodel.status = WAITING_TO_START

        perspective_manager.activate_perspective("games")
        perspective = perspective_manager.get_perspective("games")
        create_task(perspective.generalStart(self.gamemodel, p0, p1))
Ejemplo n.º 17
0
    def row_activated(self, widget, path, col):
        rec, ply = self.get_record(path)
        if rec is None:
            return

        self.gamemodel = GameModel()

        variant = rec["Variant"]
        if variant:
            self.gamemodel.tags["Variant"] = variant

        # Lichess exports study .pgn without White and Black tags
        wp = "" if rec["White"] is None else rec["White"]
        bp = "" if rec["Black"] is None else rec["Black"]
        p0 = (LOCAL, Human, (WHITE, wp), wp)
        p1 = (LOCAL, Human, (BLACK, bp), bp)
        self.persp.chessfile.loadToModel(rec, -1, self.gamemodel)

        self.gamemodel.endstatus = self.gamemodel.status if self.gamemodel.status in UNDOABLE_STATES else None
        self.gamemodel.status = WAITING_TO_START

        perspective_manager.activate_perspective("games")
        perspective = perspective_manager.get_perspective("games")
        asyncio.async(perspective.generalStart(self.gamemodel, p0, p1))
Ejemplo n.º 18
0
    def activate(self):
        if self.first_run:
            self.init_layout()
            self.first_run = False

        learn_home = Gtk.Box()
        learn_home.add(Gtk.Label("Practice! Practice! Practice!"))
        learn_home.show_all()

        if not self.first_run:
            self.notebooks["learnhome"].remove_page(-1)
        self.notebooks["learnhome"].append_page(learn_home)

        self.panels = [
            panel.Sidepanel().load(self) for panel in self.sidePanels
        ]

        for panel, instance in zip(self.sidePanels, self.panels):
            if not self.first_run:
                self.notebooks[panel.__name__].remove_page(-1)
            self.notebooks[panel.__name__].append_page(instance)
            instance.show()

        perspective_manager.activate_perspective("learn")
Ejemplo n.º 19
0
 def present(self):
     perspective_manager.activate_perspective("fics")
Ejemplo n.º 20
0
 def show(self):
     perspective_manager.activate_perspective("fics")
Ejemplo n.º 21
0
 def show(self):
     perspective_manager.activate_perspective("fics")
Ejemplo n.º 22
0
 def present(self):
     perspective_manager.activate_perspective("fics")
Ejemplo n.º 23
0
    def activate(self):
        if self.first_run:
            self.init_layout()
            self.first_run = False

        learn_home = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        box = Gtk.Box()

        self.tv = Gtk.TreeView()

        color = Gdk.RGBA()
        color.parse("lightblue")

        for i, col in enumerate(
            (_("lichess"), _("wtharvey"), _("yacpdb"), _("lessons"))):
            renderer = Gtk.CellRendererProgress()
            renderer.set_orientation(Gtk.Orientation.VERTICAL)
            renderer.props.height = 100
            renderer.props.inverted = True
            renderer.props.cell_background_rgba = color
            column = Gtk.TreeViewColumn(col,
                                        renderer,
                                        text=i * 2,
                                        value=i * 2 + 1)
            self.tv.append_column(column)

        self.store = Gtk.ListStore(str, int, str, int, str, int, str, int)

        self.update_progress(None, None, None)

        self.tv.set_model(self.store)
        self.tv.get_selection().set_mode(Gtk.SelectionMode.NONE)

        puzzles_solving_progress.connect("progress_updated",
                                         self.update_progress)
        lessons_solving_progress.connect("progress_updated",
                                         self.update_progress)

        box.pack_start(self.tv, False, False, 6)

        label = Gtk.Label(xpad=6, xalign=0)
        label.set_markup("<b>%s</b>" % _("Progress"))
        learn_home.pack_start(label, False, False, 6)

        learn_home.pack_start(box, False, False, 0)

        reset = Gtk.Button(_("Reset my progress"))
        learn_home.pack_start(reset, False, False, 6)

        def on_reset_clicked(button):
            dialog = Gtk.MessageDialog(
                mainwindow(), 0, Gtk.MessageType.QUESTION,
                Gtk.ButtonsType.OK_CANCEL,
                _("You will lose all your progress data!"))
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                for filename, progress in lessons_solving_progress.items():
                    lessons_solving_progress[filename] = [0] * len(progress)
                for filename, progress in puzzles_solving_progress.items():
                    puzzles_solving_progress[filename] = [0] * len(progress)
                self.update_progress(None, None, None)
            dialog.destroy()

        reset.connect("clicked", on_reset_clicked)

        learn_home.show_all()

        if not self.first_run:
            self.notebooks["learnhome"].remove_page(-1)
        self.notebooks["learnhome"].append_page(learn_home)

        self.panels = [
            panel.Sidepanel().load(self) for panel in self.sidePanels
        ]

        for panel, instance in zip(self.sidePanels, self.panels):
            if not self.first_run:
                self.notebooks[panel_name(panel.__name__)].remove_page(-1)
            self.notebooks[panel_name(panel.__name__)].append_page(instance)
            instance.show()

        perspective_manager.activate_perspective("learn")