コード例 #1
0
class GuiServeur(QtGui.QMainWindow):

    def __init__(self, le2mserv):
        super(GuiServeur, self).__init__()

        self._le2mserv = le2mserv
        self._questcomp = None

        self.ui = servguimain.Ui_EcranServeur()
        self.ui.setupUi(self)
        self._create_menus()

        self.ui.label_le2m.setText(
            le2mtrans(u"LE2M\nExperimental Economics Software of Montpellier"))

        # tabs
        self.ui.onglets.setTabText(self.ui.onglets.indexOf(self.ui.tabInfos),
                                   le2mtrans(u"Informations"))
        self.ui.onglets.setTabText(self.ui.onglets.indexOf(self.ui.tabClients),
                                   le2mtrans(u"Remotes"))
        self.ui.onglets.setTabText(self.ui.onglets.indexOf(
            self.ui.tabExperience), le2mtrans(u"Experiment"))

        # picture on the first tab ---------------------------------------------
        try:
            img_labo_pix = QtGui.QPixmap(params.getp("LABLOGO"))
            self.ui.label_logo_laboratoire.setPixmap(img_labo_pix)
        except IOError:
            logger.warning(u"Error while loading LABLOGO picture")
            self.ui.label_logo_laboratoire.setText(
                le2mtrans(u"Here the logo of the lab"))
        try:
            img_leem_pix = QtGui.QPixmap(params.getp("LABPICTURE"))
            self.ui.label_image_centre.setPixmap(img_leem_pix)
        except IOError:
            logger.warning(u"Error while loading LABPICTURE picture")
            self.ui.label_image_centre.setText(
                le2mtrans(u"Here the main picture"))
        
        # icons for the waiting mode -------------------------------------------
        self._icon_rouge = QtGui.QIcon(
            os.path.join(params.getp("IMGDIR"), "red.png"))
        self._icon_vert = QtGui.QIcon(
            os.path.join(params.getp("IMGDIR"), "green.png"))
        self.ui.label_attente.setText(le2mtrans(u"Decisions"))
        self._players_wait_mode = list()
        
        # server infos ---------------------------------------------------------
        self.ui.label_infos_serveur.setText(
            u"OS: {} {} | Python version: {} | Hostname: {} | IP: {}".format(
                platform.uname()[0], platform.uname()[2],
                sys.version.split()[0], self._le2mserv.hostname,
                self._le2mserv.ip))
        
        # table on the second tab with connected remotes -----------------------
        # handle automatic and simulation modes as well as remotes' deconnection
        self.ui.label_connectedremotes.setText(
            le2mtrans(u"Connected remotes: 0"))
        self.tableJoueurs = TableModelJoueurs()
        self.ui.tv_clients_connectes.setModel(self.tableJoueurs)
        self.ui.tv_clients_connectes.horizontalHeader().\
            setResizeMode(QtGui.QHeaderView.Stretch)
        self.ui.tv_clients_connectes.horizontalHeader().setClickable(True)
        self.ui.tv_clients_connectes.horizontalHeader().sectionClicked[int]. \
            connect(self.tableJoueurs.inverse)
        self.ui.onglets.setCurrentIndex(0)
        
        self.setWindowTitle(le2mtrans(u"LE2M"))

    def _create_menus(self):
        # file -----------------------------------------------------------------
        self.menu_file = QtGui.QMenu(le2mtrans(u"File"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_file)
        self.action_loadpart = QtGui.QAction(
            le2mtrans(u"Load a part"), self.menu_file)
        self.action_loadpart.setShortcut(QtGui.QKeySequence("Ctrl+o"))
        self.action_loadpart.setToolTip(
            le2mtrans(u"Open a dialog box with a list of parts you can load"))
        self.action_loadpart.triggered.connect(self._load_parts)
        self.menu_file.addAction(self.action_loadpart)

        self.menu_file.addSeparator()

        self.action_quit = QtGui.QAction(le2mtrans(u"Quit"), self.menu_file)
        self.action_quit.setShortcut(QtGui.QKeySequence("Ctrl+q"))
        self.action_quit.setToolTip(le2mtrans(u"Quit the application"))
        self.action_quit.triggered.connect(self.close)
        self.menu_file.addAction(self.action_quit)

        # experiment -----------------------------------------------------------
        self.menu_experiment = QtGui.QMenu(
            le2mtrans(u"Experiment"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_experiment)
        self.action_welcome = QtGui.QAction(
            le2mtrans(u"Display welcome screen"), self.menu_experiment)
        self.action_welcome.setToolTip(
            le2mtrans(u"Display the welcome screen on participants' screen"))
        self.action_welcome.triggered.connect(lambda _: self._display_welcome())
        self.menu_experiment.addAction(self.action_welcome)

        self.menu_experiment.addSeparator()

        self.action_loadquestcomp = QtGui.QAction(
            le2mtrans(u"Load an understanding questionnaire"),
            self.menu_experiment)
        self.action_loadquestcomp.setToolTip(
            le2mtrans(u"Open a dialog box for selecting an understanding "
                      u"questionnaire (xml file)"))
        self.action_loadquestcomp.triggered.connect(self._load_questcomp)
        self.menu_experiment.addAction(self.action_loadquestcomp)
        self.action_startquestcomp = QtGui.QAction(
            le2mtrans(u"Start the understanding questionnaire"),
            self.menu_experiment)
        self.action_startquestcomp.setToolTip(
            le2mtrans(u"Start the loaded understanding questionnaire"))
        self.action_startquestcomp.triggered.connect(self._start_questcomp)
        self.menu_experiment.addAction(self.action_startquestcomp)

        self.menu_experiment.addSeparator()

        self.action_finalquest = QtGui.QAction(
            le2mtrans(u"Display final questionnaire"), self.menu_experiment)
        self.action_finalquest.setToolTip(
            le2mtrans(u"Display the final questionnaire on participants' "
                      u"screen"))
        self.action_finalquest.triggered.connect(self._display_finalquest)
        self.menu_experiment.addAction(self.action_finalquest)
        self.action_payoffs = QtGui.QAction(
            le2mtrans(u"Payoffs"), self.menu_experiment)
        self.action_payoffs.setToolTip(
            le2mtrans(u"Display a dialog box with the payoffs of each player"))
        self.action_payoffs.triggered.connect(
            lambda _: self._le2mserv.gestionnaire_experience.display_payoffs_onserver(
                "base"))
        self.menu_experiment.addAction(self.action_payoffs)

        # parts ----------------------------------------------------------------
        self.menu_parts = QtGui.QMenu(le2mtrans(u"Parts"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_parts)

        # edit -----------------------------------------------------------------
        self.menu_edit = QtGui.QMenu(le2mtrans(u"Edit"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_edit)
        self.action_clearsrv = QtGui.QAction(
            le2mtrans(u"Clear server list"), self.menu_edit)
        self.action_clearsrv.setToolTip(le2mtrans(u"Clear the server list"))
        self.action_clearsrv.triggered.connect(self.ui.list_server.clear)
        self.menu_edit.addAction(self.action_clearsrv)
        self.action_clearclt = QtGui.QAction(
            le2mtrans(u"Clear client list"), self.menu_edit)
        self.action_clearclt.setToolTip(le2mtrans(u"Clear the client list"))
        self.action_clearclt.triggered.connect(self.ui.list_client.clear)
        self.menu_edit.addAction(self.action_clearclt)

        # options --------------------------------------------------------------
        self.menu_options = QtGui.QMenu(le2mtrans(u"Options"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_options)
        self.action_stoprepetitions = QtGui.QAction(
            le2mtrans(u"Stop the part after this period"), self.menu_options)
        self.action_stoprepetitions.setToolTip(
            le2mtrans(u"Clic on this menu to stop the part after this period"))
        self.action_stoprepetitions.triggered.connect(self._stoprep)
        self.action_stoprepetitions.setCheckable(True)
        self.menu_options.addAction(self.action_stoprepetitions,)

        self.action_gender = QtGui.QAction(
            le2mtrans(u"Set participants gender in the application"),
            self.menu_options)
        self.action_gender.setToolTip(
            le2mtrans(u"Display a dialog box that allows to set the gender of "
                      u"each remote (participant)"))
        self.action_gender.triggered.connect(self._edit_genders)
        self.menu_options.addAction(self.action_gender)

        self.menu_experiment.addSeparator()

        self.action_drawpart = QtGui.QAction(
            le2mtrans(u"Draw a part among those played"), self.menu_experiment)
        self.action_drawpart.triggered.connect(self._draw_part)
        self.menu_options.addAction(self.action_drawpart)
        self.action_displaypartspayoffs = QtGui.QAction(
            le2mtrans(u"Display the payoffs of each part"),
            self.menu_experiment)
        self.action_displaypartspayoffs.setToolTip(
            le2mtrans(u"Display a dialog box where you can choose for which "
                      u"part you want to inform the participants about their "
                      u"payoff"))
        self.action_displaypartspayoffs.triggered.connect(
            self._display_payoffs_partsSelection)
        self.menu_options.addAction(self.action_displaypartspayoffs)

        # tools ----------------------------------------------------------------
        self.menu_tools = QtGui.QMenu(le2mtrans(u"Tools"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_tools)
        self.action_creator = QtGui.QAction(
            le2mtrans(u"Create a new part"), self.menu_tools)
        self.action_creator.setToolTip(
            le2mtrans(u"Display a dialog box in which you can configure the "
                      u"part to create"))
        self.action_creator.triggered.connect(creator.creator)
        self.menu_tools.addAction(self.action_creator)
        self.action_questcomp = QtGui.QAction(
            le2mtrans(u"Create/Edit an understanding questionnaire"),
            self.menu_tools)
        self.action_questcomp.setToolTip(
            le2mtrans(u"Open a dialog box that allows to create or edit an "
                      u"understanding questionnaire"))
        self.action_questcomp.triggered.connect(questcomp.questcomp)
        self.menu_tools.addAction(self.action_questcomp)
        self.action_extractor = QtGui.QAction(
            le2mtrans(u"Extract some experimental data"), self.menu_tools)
        self.action_extractor.setToolTip(
            le2mtrans(u"Open a dialog box for selection an sqlite file to "
                      u"extract"))
        self.action_extractor.triggered.connect(extractor.extractor)
        self.menu_tools.addAction(self.action_extractor)

        self.menu_tools.addSeparator()

        # random draws: dice, head and tail, number
        self.action_dice = QtGui.QAction(
            le2mtrans(u"Dice roller"), self.menu_tools)
        self.action_dice.setToolTip(le2mtrans(u"Roll a dice"))
        self.action_dice.triggered.connect(self._rolldice)
        self.menu_tools.addAction(self.action_dice)

        self.action_randint = QtGui.QAction(
            le2mtrans(u"Random number"), self.menu_tools)
        self.action_randint.setToolTip(le2mtrans(u"Drawn a random number"))
        self.action_randint.triggered.connect(self._randint)
        self.menu_tools.addAction(self.action_randint)

        self.action_headtail = QtGui.QAction(
            le2mtrans(u"Head and Tail"), self.menu_tools)
        self.action_headtail.setToolTip(le2mtrans(u"Play head and tail"))
        self.action_headtail.triggered.connect(self._headtail)
        self.menu_tools.addAction(self.action_headtail)

        # help -----------------------------------------------------------------
        self.menu_help = QtGui.QMenu(le2mtrans(u"Help"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_help)
        self.action_help = QtGui.QAction(le2mtrans(u"Help"), self.menu_help)
        self.action_help.setToolTip(
            le2mtrans(u"Display a window with a text of help"))
        self.action_help.triggered.connect(self._display_help)
        self.menu_help.addAction(self.action_help)
        self.action_about = QtGui.QAction(le2mtrans(u"About"), self.menu_help)
        self.action_about.triggered.connect(self._display_about)
        self.menu_help.addAction(self.action_about)

    def connect_slots(self):
        self._le2mserv.gestionnaire_joueurs.playeradded[object, int].connect(
            self._addplayer)
        self._le2mserv.gestionnaire_joueurs.playerremoved[object, int].connect(
            self._removeplayer)
        self._le2mserv.gestionnaire_experience.stoprepetitions[bool].connect(
            self._stoprepetitions)

    def _load_parts(self):
        if self._le2mserv.gestionnaire_base.is_created():
            QtGui.QMessageBox.warning(
                self, le2mtrans(u"Warning"),
                le2mtrans(u"The database is already created, you therefore "
                          u"cannot load another part. If you want to, you need "
                          u"to restart the application"))
            return
        screenparts = GuiPartLoad(self)
        if screenparts.exec_():
            expeinfos = screenparts.get_expeinfos()
            logger.info(le2mtrans(u"Experiment: {e}").format(e=expeinfos))
            self._le2mserv.gestionnaire_experience.load_experiment(expeinfos)
        else:
            return
    
    def add_serverlist(self, texte, **kwargs):
        _add_list(texte if texte else u"", self.ui.list_server, **kwargs)

    def add_clientlist(self, texte, **kwargs):
        _add_list(texte if texte else u"", self.ui.list_client, **kwargs)

    def _display_welcome(self):
        """
        Display the welcome screen on remotes
        """
        reply = QtGui.QMessageBox.question(
            self,
            le2mtrans(u'Confirmation'),
            le2mtrans(u"Display the welcome screen on remotes?"),
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
        )
        if reply != QtGui.QMessageBox.Yes:
            return
        self._le2mserv.gestionnaire_experience.display_welcome()

    def _load_questcomp(self):
        """
        Récupère le fichier xml de questionnaire de compréhension et le
        traite
        :return:
        """
        xmlfile = str(
            QtGui.QFileDialog.getOpenFileName(
                self,
                le2mtrans(u"Select the understanding questionnaire to load"),
                "", le2mtrans(u"xml file (*.xml)")))
        if not xmlfile:
            return
        else:
            self._questcomp = questcomp.get_questions(xmlfile)
            if not self._questcomp:
                return

            txt = u""
            for q in self._questcomp:
                txt += u"{}\n\n".format(q)
            QtGui.QMessageBox.information(
                self,
                le2mtrans(u"Understanding questionnaire"), txt)
            self.add_serverlist(
                le2mtrans(u"Understanding questionnaire loaded "
                          u"({} questions)").format(len(self._questcomp)))

    def _start_questcomp(self):
        """
        Start the understanding questionnaire
        """
        if not self._questcomp:
            QtGui.QMessageBox.warning(
                self,
                le2mtrans(u"Warning"),
                le2mtrans(u"Please load an understanding questionnaire"))
            return
        if not self._le2mserv.gestionnaire_base.is_created():
            QtGui.QMessageBox.warning(
                self, le2mtrans(u"Warning"),
                le2mtrans(u"The understanding questionnaire cannot be started "
                          u"before the database is created. You first has to "
                          u"load at least one part."))
            return
        reply = QtGui.QMessageBox.question(
            self,
            le2mtrans(u'Confirmation'),
            le2mtrans(u"Please confirm you want to start the understanding "
                      u"questionnaire?"),
            QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)
        if reply != QtGui.QMessageBox.Yes:
            return
        self._le2mserv.gestionnaire_experience.start_questcomp(self._questcomp)

    def closeEvent(self, event):
        """
        Parce qu'on demande confirmation avant de quitter
        """
        reply = QtGui.QMessageBox.question(
            self,
            le2mtrans(u'Confirmation'),
            le2mtrans(u"Are you sure you want to exit LE2M?"),
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.Yes:
            self._le2mserv.arreter()
            event.accept()
        else:
            event.ignore()
    
    def _edit_genders(self):
        """
        Display a dialog for setting the gender of each subject (by remote)
        """
        players = self._le2mserv.gestionnaire_joueurs.get_players()
        ecran_genres = GuiGenres(players, self)
        if ecran_genres.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                [le2mtrans(u"Genders"), le2mtrans(u"Men")])
            self._le2mserv.gestionnaire_graphique.infoserv(
                map(str, [p for p in players if p.gender == HOMME]))
            self._le2mserv.gestionnaire_graphique.infoserv(le2mtrans(u"Women"))
            self._le2mserv.gestionnaire_graphique.infoserv(
                map(str, [p for p in players if p.gender == FEMME]))

    def _display_finalquest(self):
        """
        Display the final questionnaire on remotes
        """
        if not self._le2mserv.gestionnaire_base.is_created():
            QtGui.QMessageBox.warning(
                self,
                le2mtrans(u"Warning"),
                le2mtrans(u"There is no database yet. You first need to "
                          u"load at least one part."))
            return
        confirmation = QtGui.QMessageBox.question(
            self,
            le2mtrans(u"Confirmation"),
            le2mtrans(u"Start the final questionnaire?"),
            QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Ok)
        if confirmation != QtGui.QMessageBox.Ok:
            return
        self._le2mserv.gestionnaire_experience.display_finalquestionnaire()
            
    def _display_help(self):
        """
        Display a dialog with some help on le2m
        """
        help_file = os.path.join(params.getp("HTMLDIR"),
                                    "le2m_aide.html")
        webscreen = DWebview(
            help_file, title=le2mtrans(u"Help"), parent=self)
        webscreen.show()

    def _display_about(self):
        """
        Display a dialog with some infos about the authors of le2m
        """
        fichier_auteurs = os.path.join(
            params.getp("HTMLDIR"), "le2m_auteurs.html")
        screen = GuiInformation(
            parent=self, titre=le2mtrans(u"Developers"), size=(450, 180),
            html=True, text=utiltools.get_contenu_fichier(fichier_auteurs))
        screen.show()

    def _draw_part(self):
        """
        Display a dialog with the list of played part.
        The experimenter select the parts among which he/she wants to do
        a random draw for paiements for example
        :return:
        """
        parties_jouees = self._le2mserv.gestionnaire_experience. \
            get_parts()
        ecran_parties = GuiPartsPlayed(parties_jouees, self)
        if ecran_parties.exec_():
            parties_selectionnees = ecran_parties.get_parties_selectionnees()
            if not parties_selectionnees:
                return
            self._le2mserv.gestionnaire_experience.draw_part(
                parties_selectionnees)
        else:
            return
                
    def _display_payoffs_partsSelection(self):
        """
        Open a dialog box with the list of parts that have been played.
        The experimenter chooses which part he/she wants to be displayed
        on the remotes
        :return:
        """
        parts = self._le2mserv.gestionnaire_experience.get_parts()
        screen = GuiPartsPlayed(parts, self)
        if screen.exec_():
            choices = screen.get_parties_selectionnees()
            if choices:
                confirmation = self._le2mserv.gestionnaire_graphique.question(
                    le2mtrans(u"Display the details of the selected parts "
                              u"on remotes?\n{}").format(choices))
                if not confirmation:
                    return

                self._le2mserv.gestionnaire_experience.display_payoffs_onremotes(
                    choices)
        
    def _stoprep(self):
        """
        Change the value of the stop_repetitions variable. This method is
        called by the stop_repetitions method (just above) but also by the
        server of each part, at the beginning of the part in order to reset
        the value to False
        """
        if self._le2mserv.gestionnaire_experience.stop_repetitions:
            self._le2mserv.gestionnaire_experience.stop_repetitions = False
        else:
            self._le2mserv.gestionnaire_experience.stop_repetitions = True

    def set_wait_mode(self, list_players):
        """
        Display a colored icon beside the hostname to see whether the remote
        has a decided or not yet
        :param list_players: either a list of players (or parts) or only one
         element (player or part)
        """
        self.ui.listWidget_attente.clear()
        del self._players_wait_mode[:]
        # if the argument is a list
        if isinstance(list_players, list):
            for p in list_players:
                e = QtGui.QListWidgetItem(self._icon_rouge, u"")
                if isinstance(p, Partie): 
                    self._players_wait_mode.append(p.joueur)
                    e.setText(repr(p.joueur))
                elif isinstance(p, Joueur):
                    self._players_wait_mode.append(p)
                    e.setText(repr(p))
                self.ui.listWidget_attente.addItem(e)
        # if the argument is only one object
        else:
            e = QtGui.QListWidgetItem(self._icon_rouge, u"")
            if isinstance(list_players, Partie):
                self._players_wait_mode.append(list_players.joueur)
                e.setText(repr(list_players.joueur))
            elif isinstance(list_players, Joueur):
                self._players_wait_mode.append(list_players)
                e.setText(repr(list_players))
            self.ui.listWidget_attente.addItem(e)
            
    def remove_wait_mode(self, list_players):
        """
        Change the icon color to green, meaning that the remote has taken
        his decision
        :param list_players: either a list of players (or parts) or only one
         element (player or part)
        """
        if isinstance(list_players, list):
            for p in list_players:
                try:
                    index = self._players_wait_mode.index(p)
                except ValueError as e: 
                    logger.warning(
                        le2mtrans(u"Problem with remove_waitmode: "
                                  u"{msg}").format(e.message)
                    )
                else:
                    self.ui.listWidget_attente.item(index).setIcon(
                        self._icon_vert)
        else:
            try:
                index = self._players_wait_mode.index(list_players)
            except ValueError as e: 
                logger.warning(
                    le2mtrans(u"Problem with remove_waitmode: "
                              u"{msg}").format(e.message)
                )
            else:
                self.ui.listWidget_attente.item(index).setIcon(self._icon_vert)
            
    @QtCore.pyqtSlot(object, int)
    def _addplayer(self, player, nbplayers):
        self.tableJoueurs.ajouter_joueur(player)
        self.ui.label_connectedremotes.setText(
            le2mtrans(u"Connected remotes: {num}").format(num=nbplayers))

    @QtCore.pyqtSlot(object, int)
    def _removeplayer(self, player, nbplayers):
        self.tableJoueurs.enlever_joueur(player)
        self.ui.label_connectedremotes.setText(
            le2mtrans(u"Connected remotes: {num}").format(num=nbplayers))

    @QtCore.pyqtSlot(bool)
    def _stoprepetitions(self, yes_or_no):
        if yes_or_no:
            self.action_stoprepetitions.setText(
                le2mtrans(u"The part will stop after this period"))
        else:
            self.action_stoprepetitions.setText(
                le2mtrans(u"Stop the part after this period "))

    def _rolldice(self):
        screen = DDice(self)
        if screen.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                le2mtrans(u"Dice value: {}".format(screen.get_dicevalue())))

    def _randint(self):
        screen = DRandint(self)
        if screen.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                le2mtrans(u"Random number: {}".format(screen.get_value())))

    def _headtail(self):
        screen = DHeadtail(self)
        if screen.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                le2mtrans(u"Head and tail: {}".format(
                    le2mtrans(u"Head") if screen.get_value() == FACE else
                    le2mtrans(u"Tail"))))
コード例 #2
0
class GuiServeur(QtGui.QMainWindow):
    def __init__(self, le2mserv):
        super(GuiServeur, self).__init__()

        self._le2mserv = le2mserv
        self._questcomp = None

        self.ui = servguimain.Ui_EcranServeur()
        self.ui.setupUi(self)
        self._create_menus()

        self.ui.label_le2m.setText(
            le2mtrans(u"LE2M\nExperimental Economics Software of Montpellier"))

        # tabs
        self.ui.onglets.setTabText(self.ui.onglets.indexOf(self.ui.tabInfos),
                                   le2mtrans(u"Informations"))
        self.ui.onglets.setTabText(self.ui.onglets.indexOf(self.ui.tabClients),
                                   le2mtrans(u"Remotes"))
        self.ui.onglets.setTabText(
            self.ui.onglets.indexOf(self.ui.tabExperience),
            le2mtrans(u"Experiment"))

        # picture on the first tab ---------------------------------------------
        try:
            img_labo_pix = QtGui.QPixmap(params.getp("LABLOGO"))
            self.ui.label_logo_laboratoire.setPixmap(img_labo_pix)
        except IOError:
            logger.warning(u"Error while loading LABLOGO picture")
            self.ui.label_logo_laboratoire.setText(
                le2mtrans(u"Here the logo of the lab"))
        try:
            img_leem_pix = QtGui.QPixmap(params.getp("LABPICTURE"))
            self.ui.label_image_centre.setPixmap(img_leem_pix)
        except IOError:
            logger.warning(u"Error while loading LABPICTURE picture")
            self.ui.label_image_centre.setText(
                le2mtrans(u"Here the main picture"))

        # icons for the waiting mode -------------------------------------------
        self._icon_rouge = QtGui.QIcon(
            os.path.join(params.getp("IMGDIR"), "red.png"))
        self._icon_vert = QtGui.QIcon(
            os.path.join(params.getp("IMGDIR"), "green.png"))
        self.ui.label_attente.setText(le2mtrans(u"Decisions"))
        self._players_wait_mode = list()

        # server infos ---------------------------------------------------------
        self.ui.label_infos_serveur.setText(
            u"OS: {} {} | Python version: {} | Hostname: {} | IP: {}".format(
                platform.uname()[0],
                platform.uname()[2],
                sys.version.split()[0], self._le2mserv.hostname,
                self._le2mserv.ip))

        # table on the second tab with connected remotes -----------------------
        # handle automatic and simulation modes as well as remotes' deconnection
        self.ui.label_connectedremotes.setText(
            le2mtrans(u"Connected remotes: 0"))
        self.tableJoueurs = TableModelJoueurs()
        self.ui.tv_clients_connectes.setModel(self.tableJoueurs)
        self.ui.tv_clients_connectes.horizontalHeader().\
            setResizeMode(QtGui.QHeaderView.Stretch)
        self.ui.tv_clients_connectes.horizontalHeader().setClickable(True)
        self.ui.tv_clients_connectes.horizontalHeader().sectionClicked[int]. \
            connect(self.tableJoueurs.inverse)
        self.ui.onglets.setCurrentIndex(0)

        self.setWindowTitle(le2mtrans(u"LE2M"))

    def _create_menus(self):
        # file -----------------------------------------------------------------
        self.menu_file = QtGui.QMenu(le2mtrans(u"File"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_file)
        self.action_loadpart = QtGui.QAction(le2mtrans(u"Load a part"),
                                             self.menu_file)
        self.action_loadpart.setShortcut(QtGui.QKeySequence("Ctrl+o"))
        self.action_loadpart.setToolTip(
            le2mtrans(u"Open a dialog box with a list of parts you can load"))
        self.action_loadpart.triggered.connect(self._load_parts)
        self.menu_file.addAction(self.action_loadpart)

        self.menu_file.addSeparator()

        self.action_quit = QtGui.QAction(le2mtrans(u"Quit"), self.menu_file)
        self.action_quit.setShortcut(QtGui.QKeySequence("Ctrl+q"))
        self.action_quit.setToolTip(le2mtrans(u"Quit the application"))
        self.action_quit.triggered.connect(self.close)
        self.menu_file.addAction(self.action_quit)

        # experiment -----------------------------------------------------------
        self.menu_experiment = QtGui.QMenu(le2mtrans(u"Experiment"),
                                           self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_experiment)
        self.action_welcome = QtGui.QAction(
            le2mtrans(u"Display welcome screen"), self.menu_experiment)
        self.action_welcome.setToolTip(
            le2mtrans(u"Display the welcome screen on participants' screen"))
        self.action_welcome.triggered.connect(
            lambda _: self._display_welcome())
        self.menu_experiment.addAction(self.action_welcome)

        self.menu_experiment.addSeparator()

        self.action_loadquestcomp = QtGui.QAction(
            le2mtrans(u"Load an understanding questionnaire"),
            self.menu_experiment)
        self.action_loadquestcomp.setToolTip(
            le2mtrans(u"Open a dialog box for selecting an understanding "
                      u"questionnaire (xml file)"))
        self.action_loadquestcomp.triggered.connect(self._load_questcomp)
        self.menu_experiment.addAction(self.action_loadquestcomp)
        self.action_startquestcomp = QtGui.QAction(
            le2mtrans(u"Start the understanding questionnaire"),
            self.menu_experiment)
        self.action_startquestcomp.setToolTip(
            le2mtrans(u"Start the loaded understanding questionnaire"))
        self.action_startquestcomp.triggered.connect(self._start_questcomp)
        self.menu_experiment.addAction(self.action_startquestcomp)

        self.menu_experiment.addSeparator()

        self.action_finalquest = QtGui.QAction(
            le2mtrans(u"Display final questionnaire"), self.menu_experiment)
        self.action_finalquest.setToolTip(
            le2mtrans(u"Display the final questionnaire on participants' "
                      u"screen"))
        self.action_finalquest.triggered.connect(self._display_finalquest)
        self.menu_experiment.addAction(self.action_finalquest)
        self.action_payoffs = QtGui.QAction(le2mtrans(u"Payoffs"),
                                            self.menu_experiment)
        self.action_payoffs.setToolTip(
            le2mtrans(u"Display a dialog box with the payoffs of each player"))
        self.action_payoffs.triggered.connect(
            lambda _: self._le2mserv.gestionnaire_experience.
            display_payoffs_onserver("base"))
        self.menu_experiment.addAction(self.action_payoffs)

        # parts ----------------------------------------------------------------
        self.menu_parts = QtGui.QMenu(le2mtrans(u"Parts"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_parts)

        # edit -----------------------------------------------------------------
        self.menu_edit = QtGui.QMenu(le2mtrans(u"Edit"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_edit)
        self.action_clearsrv = QtGui.QAction(le2mtrans(u"Clear server list"),
                                             self.menu_edit)
        self.action_clearsrv.setToolTip(le2mtrans(u"Clear the server list"))
        self.action_clearsrv.triggered.connect(self.ui.list_server.clear)
        self.menu_edit.addAction(self.action_clearsrv)
        self.action_clearclt = QtGui.QAction(le2mtrans(u"Clear client list"),
                                             self.menu_edit)
        self.action_clearclt.setToolTip(le2mtrans(u"Clear the client list"))
        self.action_clearclt.triggered.connect(self.ui.list_client.clear)
        self.menu_edit.addAction(self.action_clearclt)

        # options --------------------------------------------------------------
        self.menu_options = QtGui.QMenu(le2mtrans(u"Options"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_options)
        self.action_stoprepetitions = QtGui.QAction(
            le2mtrans(u"Stop the part after this period"), self.menu_options)
        self.action_stoprepetitions.setToolTip(
            le2mtrans(u"Clic on this menu to stop the part after this period"))
        self.action_stoprepetitions.triggered.connect(self._stoprep)
        self.action_stoprepetitions.setCheckable(True)
        self.menu_options.addAction(self.action_stoprepetitions, )

        self.action_gender = QtGui.QAction(
            le2mtrans(u"Set participants gender in the application"),
            self.menu_options)
        self.action_gender.setToolTip(
            le2mtrans(u"Display a dialog box that allows to set the gender of "
                      u"each remote (participant)"))
        self.action_gender.triggered.connect(self._edit_genders)
        self.menu_options.addAction(self.action_gender)

        self.menu_experiment.addSeparator()

        self.action_drawpart = QtGui.QAction(
            le2mtrans(u"Draw a part among those played"), self.menu_experiment)
        self.action_drawpart.triggered.connect(self._draw_part)
        self.menu_options.addAction(self.action_drawpart)
        self.action_displaypartspayoffs = QtGui.QAction(
            le2mtrans(u"Display the payoffs of each part"),
            self.menu_experiment)
        self.action_displaypartspayoffs.setToolTip(
            le2mtrans(u"Display a dialog box where you can choose for which "
                      u"part you want to inform the participants about their "
                      u"payoff"))
        self.action_displaypartspayoffs.triggered.connect(
            self._display_payoffs_partsSelection)
        self.menu_options.addAction(self.action_displaypartspayoffs)

        # tools ----------------------------------------------------------------
        self.menu_tools = QtGui.QMenu(le2mtrans(u"Tools"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_tools)
        self.action_creator = QtGui.QAction(le2mtrans(u"Create a new part"),
                                            self.menu_tools)
        self.action_creator.setToolTip(
            le2mtrans(u"Display a dialog box in which you can configure the "
                      u"part to create"))
        self.action_creator.triggered.connect(creator.creator)
        self.menu_tools.addAction(self.action_creator)
        self.action_questcomp = QtGui.QAction(
            le2mtrans(u"Create/Edit an understanding questionnaire"),
            self.menu_tools)
        self.action_questcomp.setToolTip(
            le2mtrans(u"Open a dialog box that allows to create or edit an "
                      u"understanding questionnaire"))
        self.action_questcomp.triggered.connect(questcomp.questcomp)
        self.menu_tools.addAction(self.action_questcomp)
        self.action_extractor = QtGui.QAction(
            le2mtrans(u"Extract some experimental data"), self.menu_tools)
        self.action_extractor.setToolTip(
            le2mtrans(u"Open a dialog box for selection an sqlite file to "
                      u"extract"))
        self.action_extractor.triggered.connect(extractor.extractor)
        self.menu_tools.addAction(self.action_extractor)

        self.menu_tools.addSeparator()

        # random draws: dice, head and tail, number
        self.action_dice = QtGui.QAction(le2mtrans(u"Dice roller"),
                                         self.menu_tools)
        self.action_dice.setToolTip(le2mtrans(u"Roll a dice"))
        self.action_dice.triggered.connect(self._rolldice)
        self.menu_tools.addAction(self.action_dice)

        self.action_randint = QtGui.QAction(le2mtrans(u"Random number"),
                                            self.menu_tools)
        self.action_randint.setToolTip(le2mtrans(u"Drawn a random number"))
        self.action_randint.triggered.connect(self._randint)
        self.menu_tools.addAction(self.action_randint)

        self.action_headtail = QtGui.QAction(le2mtrans(u"Head and Tail"),
                                             self.menu_tools)
        self.action_headtail.setToolTip(le2mtrans(u"Play head and tail"))
        self.action_headtail.triggered.connect(self._headtail)
        self.menu_tools.addAction(self.action_headtail)

        # help -----------------------------------------------------------------
        self.menu_help = QtGui.QMenu(le2mtrans(u"Help"), self.ui.menubar)
        self.ui.menubar.addMenu(self.menu_help)
        self.action_help = QtGui.QAction(le2mtrans(u"Help"), self.menu_help)
        self.action_help.setToolTip(
            le2mtrans(u"Display a window with a text of help"))
        self.action_help.triggered.connect(self._display_help)
        self.menu_help.addAction(self.action_help)
        self.action_about = QtGui.QAction(le2mtrans(u"About"), self.menu_help)
        self.action_about.triggered.connect(self._display_about)
        self.menu_help.addAction(self.action_about)

    def connect_slots(self):
        self._le2mserv.gestionnaire_joueurs.playeradded[object, int].connect(
            self._addplayer)
        self._le2mserv.gestionnaire_joueurs.playerremoved[object, int].connect(
            self._removeplayer)
        self._le2mserv.gestionnaire_experience.stoprepetitions[bool].connect(
            self._stoprepetitions)

    def _load_parts(self):
        if self._le2mserv.gestionnaire_base.is_created():
            QtGui.QMessageBox.warning(
                self, le2mtrans(u"Warning"),
                le2mtrans(
                    u"The database is already created, you therefore "
                    u"cannot load another part. If you want to, you need "
                    u"to restart the application"))
            return
        screenparts = GuiPartLoad(self)
        if screenparts.exec_():
            self._le2mserv.gestionnaire_experience.load_experiment(
                screenparts.get_expeinfos())
        else:
            return

    def add_serverlist(self, texte, **kwargs):
        _add_list(texte if texte else u"", self.ui.list_server, **kwargs)

    def add_clientlist(self, texte, **kwargs):
        _add_list(texte if texte else u"", self.ui.list_client, **kwargs)

    def _display_welcome(self):
        """
        Display the welcome screen on remotes
        """
        reply = QtGui.QMessageBox.question(
            self, le2mtrans(u'Confirmation'),
            le2mtrans(u"Display the welcome screen on remotes?"),
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if reply != QtGui.QMessageBox.Yes:
            return
        self._le2mserv.gestionnaire_experience.display_welcome()

    def _load_questcomp(self):
        """
        Récupère le fichier xml de questionnaire de compréhension et le
        traite
        :return:
        """
        xmlfile = str(
            QtGui.QFileDialog.getOpenFileName(
                self,
                le2mtrans(u"Select the understanding questionnaire to load"),
                "", le2mtrans(u"xml file (*.xml)")))
        if not xmlfile:
            return
        else:
            self._questcomp = questcomp.get_questions(xmlfile)
            if not self._questcomp:
                return

            txt = u""
            for q in self._questcomp:
                txt += u"{}\n\n".format(q)
            QtGui.QMessageBox.information(
                self, le2mtrans(u"Understanding questionnaire"), txt)
            self.add_serverlist(
                le2mtrans(u"Understanding questionnaire loaded "
                          u"({} questions)").format(len(self._questcomp)))

    def _start_questcomp(self):
        """
        Start the understanding questionnaire
        """
        if not self._questcomp:
            QtGui.QMessageBox.warning(
                self, le2mtrans(u"Warning"),
                le2mtrans(u"Please load an understanding questionnaire"))
            return
        if not self._le2mserv.gestionnaire_base.is_created():
            QtGui.QMessageBox.warning(
                self, le2mtrans(u"Warning"),
                le2mtrans(u"The understanding questionnaire cannot be started "
                          u"before the database is created. You first has to "
                          u"load at least one part."))
            return
        reply = QtGui.QMessageBox.question(
            self, le2mtrans(u'Confirmation'),
            le2mtrans(u"Please confirm you want to start the understanding "
                      u"questionnaire?"),
            QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)
        if reply != QtGui.QMessageBox.Yes:
            return
        self._le2mserv.gestionnaire_experience.start_questcomp(self._questcomp)

    def closeEvent(self, event):
        """
        Parce qu'on demande confirmation avant de quitter
        """
        reply = QtGui.QMessageBox.question(
            self, le2mtrans(u'Confirmation'),
            le2mtrans(u"Are you sure you want to exit LE2M?"),
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.Yes:
            self._le2mserv.arreter()
            event.accept()
        else:
            event.ignore()

    def _edit_genders(self):
        """
        Display a dialog for setting the gender of each subject (by remote)
        """
        players = self._le2mserv.gestionnaire_joueurs.get_players()
        ecran_genres = GuiGenres(players, self)
        if ecran_genres.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                [le2mtrans(u"Genders"),
                 le2mtrans(u"Men")])
            self._le2mserv.gestionnaire_graphique.infoserv(
                map(str, [p for p in players if p.gender == HOMME]))
            self._le2mserv.gestionnaire_graphique.infoserv(le2mtrans(u"Women"))
            self._le2mserv.gestionnaire_graphique.infoserv(
                map(str, [p for p in players if p.gender == FEMME]))

    def _display_finalquest(self):
        """
        Display the final questionnaire on remotes
        """
        if not self._le2mserv.gestionnaire_base.is_created():
            QtGui.QMessageBox.warning(
                self, le2mtrans(u"Warning"),
                le2mtrans(u"There is no database yet. You first need to "
                          u"load at least one part."))
            return
        confirmation = QtGui.QMessageBox.question(
            self, le2mtrans(u"Confirmation"),
            le2mtrans(u"Start the final questionnaire?"),
            QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Ok)
        if confirmation != QtGui.QMessageBox.Ok:
            return
        self._le2mserv.gestionnaire_experience.display_finalquestionnaire()

    def _display_help(self):
        """
        Display a dialog with some help on le2m
        """
        help_file = os.path.join(params.getp("HTMLDIR"), "le2m_aide.html")
        webscreen = DWebview(help_file, title=le2mtrans(u"Help"), parent=self)
        webscreen.show()

    def _display_about(self):
        """
        Display a dialog with some infos about the authors of le2m
        """
        fichier_auteurs = os.path.join(params.getp("HTMLDIR"),
                                       "le2m_auteurs.html")
        screen = GuiInformation(
            parent=self,
            titre=le2mtrans(u"Developers"),
            size=(450, 180),
            html=True,
            text=utiltools.get_contenu_fichier(fichier_auteurs))
        screen.show()

    def _draw_part(self):
        """
        Display a dialog with the list of played part.
        The experimenter select the parts among which he/she wants to do
        a random draw for paiements for example
        :return:
        """
        parties_jouees = self._le2mserv.gestionnaire_experience. \
            get_parts()
        ecran_parties = GuiPartsPlayed(parties_jouees, self)
        if ecran_parties.exec_():
            parties_selectionnees = ecran_parties.get_parties_selectionnees()
            if not parties_selectionnees:
                return
            self._le2mserv.gestionnaire_experience.draw_part(
                parties_selectionnees)
        else:
            return

    def _display_payoffs_partsSelection(self):
        """
        Open a dialog box with the list of parts that have been played.
        The experimenter chooses which part he/she wants to be displayed
        on the remotes
        :return:
        """
        parts = self._le2mserv.gestionnaire_experience.get_parts()
        screen = GuiPartsPlayed(parts, self)
        if screen.exec_():
            choices = screen.get_parties_selectionnees()
            if choices:
                confirmation = self._le2mserv.gestionnaire_graphique.question(
                    le2mtrans(u"Display the details of the selected parts "
                              u"on remotes?\n{}").format(choices))
                if not confirmation:
                    return

                self._le2mserv.gestionnaire_experience.display_payoffs_onremotes(
                    choices)

    def _stoprep(self):
        """
        Change the value of the stop_repetitions variable. This method is
        called by the stop_repetitions method (just above) but also by the
        server of each part, at the beginning of the part in order to reset
        the value to False
        """
        if self._le2mserv.gestionnaire_experience.stop_repetitions:
            self._le2mserv.gestionnaire_experience.stop_repetitions = False
        else:
            self._le2mserv.gestionnaire_experience.stop_repetitions = True

    def set_wait_mode(self, list_players):
        """
        Display a colored icon beside the hostname to see whether the remote
        has a decided or not yet
        :param list_players: either a list of players (or parts) or only one
         element (player or part)
        """
        self.ui.listWidget_attente.clear()
        del self._players_wait_mode[:]
        # if the argument is a list
        if isinstance(list_players, list):
            for p in list_players:
                e = QtGui.QListWidgetItem(self._icon_rouge, u"")
                if isinstance(p, Partie):
                    self._players_wait_mode.append(p.joueur)
                    e.setText(repr(p.joueur))
                elif isinstance(p, Joueur):
                    self._players_wait_mode.append(p)
                    e.setText(repr(p))
                self.ui.listWidget_attente.addItem(e)
        # if the argument is only one object
        else:
            e = QtGui.QListWidgetItem(self._icon_rouge, u"")
            if isinstance(list_players, Partie):
                self._players_wait_mode.append(list_players.joueur)
                e.setText(repr(list_players.joueur))
            elif isinstance(list_players, Joueur):
                self._players_wait_mode.append(list_players)
                e.setText(repr(list_players))
            self.ui.listWidget_attente.addItem(e)

    def remove_wait_mode(self, list_players):
        """
        Change the icon color to green, meaning that the remote has taken
        his decision
        :param list_players: either a list of players (or parts) or only one
         element (player or part)
        """
        if isinstance(list_players, list):
            for p in list_players:
                try:
                    index = self._players_wait_mode.index(p)
                except ValueError as e:
                    logger.warning(
                        le2mtrans(u"Problem with remove_waitmode: "
                                  u"{msg}").format(e.message))
                else:
                    self.ui.listWidget_attente.item(index).setIcon(
                        self._icon_vert)
        else:
            try:
                index = self._players_wait_mode.index(list_players)
            except ValueError as e:
                logger.warning(
                    le2mtrans(u"Problem with remove_waitmode: "
                              u"{msg}").format(e.message))
            else:
                self.ui.listWidget_attente.item(index).setIcon(self._icon_vert)

    @QtCore.pyqtSlot(object, int)
    def _addplayer(self, player, nbplayers):
        self.tableJoueurs.ajouter_joueur(player)
        self.ui.label_connectedremotes.setText(
            le2mtrans(u"Connected remotes: {num}").format(num=nbplayers))

    @QtCore.pyqtSlot(object, int)
    def _removeplayer(self, player, nbplayers):
        self.tableJoueurs.enlever_joueur(player)
        self.ui.label_connectedremotes.setText(
            le2mtrans(u"Connected remotes: {num}").format(num=nbplayers))

    @QtCore.pyqtSlot(bool)
    def _stoprepetitions(self, yes_or_no):
        if yes_or_no:
            self.action_stoprepetitions.setText(
                le2mtrans(u"The part will stop after this period"))
        else:
            self.action_stoprepetitions.setText(
                le2mtrans(u"Stop the part after this period "))

    def _rolldice(self):
        screen = DDice(self)
        if screen.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                le2mtrans(u"Dice value: {}".format(screen.get_dicevalue())))

    def _randint(self):
        screen = DRandint(self)
        if screen.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                le2mtrans(u"Random number: {}".format(screen.get_value())))

    def _headtail(self):
        screen = DHeadtail(self)
        if screen.exec_():
            self._le2mserv.gestionnaire_graphique.infoserv(
                le2mtrans(u"Head and tail: {}".format(
                    le2mtrans(u"Head") if screen.get_value() ==
                    FACE else le2mtrans(u"Tail"))))