def main():
    # written/taken from  https://www.codesd.com/item/how-to-create-a-pie-chart-with-pyqt-in-python.html
    app = QApplication(sys.argv)
    radius = 200
    scene = WheelScene(radius=radius)
    wheel = WheelPhoto()
    wheel.show()
    wheel.spinWheel(7)
    wheel_label = WheelLabel()
    wheel_label.show()
    view = QGraphicsView(scene)
    view.setStyleSheet("background: transparent")
    view.setSceneRect(0, 0, radius * 2, radius * 2)
    group = scene.createItemGroup(scene.items())
    print("view: sceneRect=%s" % view.sceneRect())
    #print("view: rect=%s" %view.cen)
    view.show()

    i = 0
    while True:
        transform = QTransform()
        offset = group.boundingRect().center()
        transform.translate(offset.x(), offset.y())
        transform.rotate(i)
        transform.translate(-offset.x(), -offset.y())
        group.setTransform(transform)
        view.transform()
        QtTest.QTest.qWait(50)
        i += 1
    app.exec_()
Exemple #2
0
 def drawContents(self, painter):
     self.drawn_once = True
     painter.save()
     painter.setPen(Qt.black)
     painter.setRenderHint(painter.TextAntialiasing, True)
     painter.setRenderHint(painter.Antialiasing, True)
     f = painter.font()
     f.setPixelSize(18)
     painter.setFont(f)
     t = QTransform()
     t.translate(330, 450)
     painter.setTransform(t)
     painter.rotate(-98)
     if iswindows:
         # On windows Qt cannot anti-alias rotated text
         p = QPainterPath()
         p.addText(0, 0, f, self.message())
         painter.fillPath(p, QBrush(Qt.black))
     else:
         painter.drawText(0, 0, self.message())
     painter.restore()
Exemple #3
0
 def drawContents(self, painter):
     self.drawn_once = True
     painter.save()
     painter.setPen(Qt.black)
     painter.setRenderHint(painter.TextAntialiasing, True)
     painter.setRenderHint(painter.Antialiasing, True)
     f = painter.font()
     f.setPixelSize(18)
     painter.setFont(f)
     t = QTransform()
     t.translate(330, 450)
     painter.setTransform(t)
     painter.rotate(-98)
     left_margin = 25
     if iswindows:
         # On windows Qt cannot anti-alias rotated text
         p = QPainterPath()
         p.addText(left_margin, 0, f, self.message())
         painter.fillPath(p, QBrush(Qt.black))
     else:
         painter.drawText(left_margin, 0, self.message())
     painter.restore()
class HMI(QtWidgets.QMainWindow, Ui_MainWindow):
    signal_send_message = pyqtSignal(str)
    signal_temp_select_category = pyqtSignal(str)
    signal_start_timer = pyqtSignal(int)

    def __init__(self,
                 parent=None,
                 ui_file=None,
                 loglevel=logging.INFO,
                 hmi_port=None,
                 game_port=None,
                 skip_userreg=False,
                 skip_spinanimation=False):
        super(HMI, self).__init__(parent)
        if not IMPORT_UI_ONTHEFLY:
            self.setupUi(self)
        else:
            # used for on-the-fly compilation of ui xml
            if ui_file is None:
                raise Exception("Did not specify a .ui file")
            uic.loadUi(ui_file, self)

        self.logger = logs.build_logger(__name__, loglevel)
        self.loglevel = loglevel
        self.hmi_port = hmi_port
        self.game_port = game_port
        self.logger.debug("selected hmi_port=%s" % (self.hmi_port))
        self.logger.debug("selected game_port=%s" % (self.game_port))
        self.skip_spinanimation = skip_spinanimation

        self.setWindowTitle("Wheel of Jeopardy")
        self.setStyleSheet("background-color: gray;")
        self.sounds = {
            "Correct": QSound("Correct.wav"),
            "Incorrect": QSound("Incorrect.wav"),
            "Bankrupt": QSound("Bankrupt.wav"),
            "Double": QSound("Double.wav")
        }
        self.stack = QStackedWidget()
        for i in reversed(range(self.baseLayout.count())):
            self.baseLayout.takeAt(0)
        for i in reversed(range(self.verticalLayout.count())):
            self.verticalLayout.takeAt(0)
        self.verticalLayout.addWidget(self.stack)
        self.setCentralWidget(self.stack)
        self.mw = QVBoxLayout()
        self.mw.addLayout(self.contextLayout)
        self.mw.addLayout(self.bodyLayout)
        self.mw.addLayout(self.controlLayout)
        self.qw = QWidget()
        self.qw.setLayout(self.mw)

        self.mw.setStretchFactor(self.contextLayout, 1)
        self.mw.setStretchFactor(self.bodyLayout, 5)
        self.mw.setStretchFactor(self.controlLayout, 1)

        self.stack.raise_()
        self.stack.addWidget(self.qw)

        self.MSG_controller = messaging.HMIMessageController(
            loglevel=loglevel,
            msg_controller_name="HMILogic",
            listen_port=self.hmi_port,
            target_port=self.game_port)

        self.registration_wizard = wizard.MyWizard(
            ui_file="register_user_wizard.ui", loglevel=self.loglevel)
        self.stack.addWidget(self.registration_wizard)

        self.logic_controller = HMILogicController(loglevel=loglevel)
        self.logic_controller_thread = QThread(self)

        self.buttonSpin = HoverButton(self)
        self.buttonSpin.setText("Spin")
        self.buttonSpin.setAlignment(Qt.AlignCenter)
        self.buttonSpin.clicked.connect(self.logic_controller.askToSpin)
        self.controlLayout.addWidget(self.buttonSpin)

        # Pass messages received to the logic controller
        self.MSG_controller.signal_recieve_message.connect(
            self.logic_controller.processMessage)

        # Pass responses from the logic controller into the output of the message controller
        self.logic_controller.signal_send_message.connect(
            self.MSG_controller.send_message)
        self.signal_send_message.connect(self.MSG_controller.send_message)

        # Pass requests from the logic controller to update game stats to the HMI engine
        self.logic_controller.signal_update_game_stats.connect(
            self.updateGameStats)

        # Pass requests from the logic controller to update player stats to the HMI engine
        self.logic_controller.signal_update_player_data.connect(
            self.updatePlayer)

        # Pass requests from the logic controller to spin the wheel to the HMI engine
        self.logic_controller.signal_spin_wheel.connect(self.spinWheel)

        # Pass requests from the logic controller to alter UI to indicate the name of winner
        self.logic_controller.signal_display_winner.connect(self.displayWinner)

        # Pass requests from the logic controller to prompt a user to select a category
        self.logic_controller.signal_playerselect_category.connect(
            partial(self.selectCategory, target="player"))
        self.logic_controller.signal_opponentselect_category.connect(
            partial(self.selectCategory, target="opponents"))

        # temporarily, connect category stuff up
        self.signal_temp_select_category.connect(
            self.logic_controller.returnCategory)

        # Pass requests form the logic controller to ask HMI to update the board
        self.logic_controller.signal_update_board.connect(self.updateBoard)

        # Pass requests from the logic controller to ask HMI to update the wheel
        self.logic_controller.signal_update_wheel.connect(self.updateWheel)

        # Pass requests from the logic controller to ask HMI to diplay a question
        self.logic_controller.signal_display_question.connect(
            self.displayQuestion)

        # Pass requests from the logic controller to prompt the user to indicate the outcome of the question
        self.logic_controller.signal_determine_correctness.connect(
            self.selectOutcome)

        # Pass requests from the logic controller to ask HMI to display the answer to a question
        self.logic_controller.signal_display_answer.connect(self.displayAnswer)

        # Pass requests from the logic controller to ask HMI to adjust various items
        self.logic_controller.signal_lock_unlock.connect(self.setUIState)

        self.logic_controller.moveToThread(self.logic_controller_thread)

        #connect logic controller to wizard success/fail
        self.logic_controller.signal_feedback_registration_fail.connect(
            self.registration_wizard.pageUserEntry.
            signal_validation_response_failure)
        self.logic_controller.signal_feedback_registration_failmsg.connect(
            self.registration_wizard.setFeedback)
        self.logic_controller.signal_feedback_registration_success.connect(
            self.registration_wizard.pageUserEntry.
            signal_validation_response_success)
        self.registration_wizard.signal_submit_players.connect(
            self.logic_controller.notifyUserRegistration)

        #connect sounds
        self.logic_controller.signal_play_correct_sound.connect(
            self.playCorrect)
        self.logic_controller.signal_play_incorrect_sound.connect(
            self.playIncorrect)
        self.logic_controller.signal_play_bankrupt_sound.connect(
            self.playBankrupt)
        self.logic_controller.signal_play_double_sound.connect(self.playDouble)

        self.logic_controller.signal_determine_freeturn_spend.connect(
            self.determineFreeTurnSpend)

        #help from https://stackoverflow.com/questions/46174073/open-a-new-window-after-finish-button-has-been-clicked-on-qwizard-pyqt5?rq=1
        self.registration_wizard.button(
            QtWidgets.QWizard.FinishButton).clicked.connect(
                self.shiftToComboWheelBoardScore)
        #self.logic_controller.signal_scene_change_to_wheel.connect(self.shiftToWheelScene)
        self.logic_controller.signal_scene_change_to_main.connect(
            self.shiftToComboWheelBoardScore)

        self.main_scorebar = ScoreBar(self)
        self.contextLayout.addWidget(self.main_scorebar)

        self.round_spin_frame = RoundSpinFrame(self)
        self.main_scorebar.resized.connect(self.round_spin_frame.setMaxHeight)
        self.contextLayout.addWidget(self.round_spin_frame)
        self.contextLayout.setStretchFactor(self.main_scorebar, 15)
        self.contextLayout.setStretchFactor(self.round_spin_frame, 2)

        self.use_textwheel = False
        self.use_qgraphics_wheel = False
        self.wheelinfo = dict()
        for each in range(0, 13):
            setattr(self, "label_wheel_%s" % str(each), QLabel())
            getattr(self, "label_wheel_%s" % str(each)).setDisabled(True)
        if self.use_qgraphics_wheel:
            self.wheel_radius = 125
            self.wheel_scene = WheelScene(parent=self,
                                          radius=self.wheel_radius)

            self.wheel_view = QtWidgets.QGraphicsView(parent=self)
            self.wheel_view.setScene(self.wheel_scene)
            self.wheel_view.setStyleSheet("background: transparent")
            self.wheel_view.setSceneRect(0, 0, self.wheel_radius * 2,
                                         self.wheel_radius * 2)
            self.wheel_view.rotate((360 / 12) / 2)
            self.wheel_group = self.wheel_scene.createItemGroup(
                self.wheel_scene.items())
            self.wheel_view.show()
            self.bodyLayout.addWidget(self.wheel_view)
            self.bodyLayout.setStretchFactor(self.wheel_view, 6)
        else:
            self.wheel_gui = WheelPhoto(self)
            self.bodyLayout.addWidget(self.wheel_gui)
            self.bodyLayout.setContentsMargins(0, 0, 0, 0)
            self.bodyLayout.setStretchFactor(self.wheel_gui, 6)
            self.selectionTitle = QLabel(self.wheel_gui)
            self.selectionTitle.setText("")
            self.selectionTitle.setAlignment(Qt.AlignRight)
            self.selectionTitle.setSizePolicy(QSizePolicy.Expanding,
                                              QSizePolicy.Expanding)
            self.selectionTitle.move(
                self.wheel_gui.frameRect().width() / 2 -
                self.selectionTitle.width() * 1.5,
                self.wheel_gui.geometry().height() / 2.1)
            self.selectionTitle.setFixedWidth(self.wheel_gui.rect().width() /
                                              2.5)

        #self.bodyLayout.addWidget(self.tempButton)
        self.arrowPointer = ArrowPointer(self)
        self.bodyLayout.addWidget(self.arrowPointer)
        self.bodyLayout.setStretchFactor(self.arrowPointer, 1)
        self.board = Board(self)
        self.bodyLayout.addWidget(self.board)
        self.bodyLayout.setStretchFactor(self.board, 16)

        self.buttonFreeTurnSpend = HoverButton(self)
        self.buttonFreeTurnSpend.setText("Spend FreeTurn Token")
        self.buttonFreeTurnSpend.setAlignment(Qt.AlignCenter)
        self.buttonFreeTurnSpend.clicked.connect(self.renderSpinButton)
        self.controlLayout.addWidget(self.buttonFreeTurnSpend)
        self.buttonFreeTurnSpend.hide()

        self.buttonFreeTurnSkip = HoverButton(self)
        self.buttonFreeTurnSkip.setText("Skip")
        self.buttonFreeTurnSkip.setAlignment(Qt.AlignCenter)
        self.buttonFreeTurnSkip.clicked.connect(self.renderSpinButton)
        self.controlLayout.addWidget(self.buttonFreeTurnSkip)
        self.buttonFreeTurnSkip.hide()

        self.scene_question = questionanswer.MyQuestionScene(
            parent=self,
            ui_file="scene_question.ui",
            loglevel=self.loglevel,
        )
        self.scene_question.signal_reveal.connect(
            self.logic_controller.notifyNeedAnswer)
        self.scene_question.signal_incorrect.connect(
            self.logic_controller.notifyUnsuccesfullOutcome)
        self.scene_question.signal_correct.connect(
            self.logic_controller.notifySuccesfullOutcome)
        self.scene_question.signal_skipfreeturn.connect(
            self.logic_controller.notifyFreeTurnSkip)
        self.buttonFreeTurnSkip.clicked.connect(
            self.logic_controller.notifyFreeTurnSkip)
        self.scene_question.signal_spendfreeturn.connect(
            self.logic_controller.notifyFreeTurnSpend)
        self.buttonFreeTurnSpend.clicked.connect(
            self.logic_controller.notifyFreeTurnSpend)
        self.scene_question.show()
        self.stack.addWidget(self.scene_question)

        self.timer_obj = MyTimer(loglevel=self.loglevel)

        self.timer_thread = QThread()
        self.timer_thread.start()
        self.timer_obj.moveToThread(self.timer_thread)
        self.signal_start_timer.connect(self.timer_obj.count_down)
        self.timer_obj.signal_update_timer.connect(
            self.scene_question.updateTimer)

        self.logger.debug("building connection to start timer")
        self.logic_controller.signal_start_timer.connect(self.startTimer)
        self.logger.debug("building connection to stop timer")
        self.logic_controller.signal_stop_timer.connect(self.stopTimer)

        self.logic_controller.signal_update_main_score_bar_player.connect(
            self.main_scorebar.updatePlayers)
        self.logic_controller.signal_retain_player_data.connect(
            self.retainPlayerData)

        self.logic_controller_thread.start()
        self.MSG_controller.start()

        self.wheel_resting_place = None

        self.registration_wizard.signal_close.connect(self.close)

        self.logic_controller_thread.start()
        self.MSG_controller.start()
        #self.main = self.takeCentralWidget()
        if not skip_userreg:
            self.stack.setCurrentWidget(self.registration_wizard)
            #self.setCentralWidget(self.registration_wizard)
        else:
            self.stack.setCurrentWidget(self.qw)
            #self.setCentralWidget(self.main)

    @pyqtSlot()
    def shiftToComboWheelBoardScore(self):
        self.logger.debug("Shifting focus to combo-wheel-board-score panel")
        self.stack.setCurrentWidget(self.qw)
        #self.setCentralWidget(self.main)
        self.setStyleSheet("background-color: gray;")

    @pyqtSlot(list)
    def selectCategory(self, categories, target="player"):
        """Prompt user or opponents to select a category"""
        if isinstance(categories, list):
            if len(categories) <= 0:
                raise Exception("Category List does not include a sane value")
            else:
                self.cat_select = catselect.MyCatSelect(
                    ui_file="select_category.ui",
                    loglevel=self.loglevel,
                    categories=categories,
                    audience=target)
                self.stack.addWidget(self.cat_select)
                self.stack.setCurrentWidget(self.cat_select)
                self.cat_select.signal_submit_category.connect(
                    self.logic_controller.returnCategory)
                self.cat_select.signal_shift_scene.connect(
                    self.shiftToComboWheelBoardScore)
                #self.main = self.takeCentralWidget()
                #self.setCentralWidget(self.cat_select)
                #self.cat_select.show()

    @pyqtSlot()
    def selectOutcome(self):
        """Prompt players to indicate whether a response was correct or incorrect"""
        pass

    @pyqtSlot(dict)
    def displayQuestion(self, question_dict):
        """Render provided question to display"""

        self.stack.setCurrentWidget(self.scene_question)
        self.scene_question.set_context(self.playerData)
        self.scene_question.set_category(question_dict['category'])
        self.scene_question.set_value(question_dict['score'])

        self.scene_question.set_question(question_dict['question'])
        self.scene_question.render_controls_reveal()

        #self.main = self.takeCentralWidget()
        #self.setCentralWidget(self.scene_question)
        self.logger.debug("shift scene to question/answer")
        self.logic_controller.issueAck("displayQuestion")

    @pyqtSlot(dict)
    def displayAnswer(self, question_dict):
        """Render provided question to display"""
        self.scene_question.set_answer(question_dict['answer'])
        self.scene_question.render_controls_correct_incorrect()

    @pyqtSlot(int)
    def spinWheel(self, destination):
        """ Make the Wheel Spin. Ensure it lands on Destination"""
        if self.use_qgraphics_wheel:
            i = 0
            self.wheel_transform = QTransform()
            self.wheel_offset = self.wheel_group.boundingRect().center()
            self.wheel_transform.translate(self.wheel_offset.x(),
                                           self.wheel_offset.y())
            self.wheel_transform.setRotateCropHalve(i)
            self.wheel_transform.translate(-self.wheel_offset.x(),
                                           -self.wheel_offset.y())
            self.wheel_group.setTransform(self.wheel_transform)
            self.wheel_view.transform()
            QtTest.QTest.qWait(50)
            i += 1

        else:
            data = None

            num_sectors = 0
            if self.use_textwheel:
                for each in range(0, 12):
                    if getattr(self, "label_wheel_" + str(each)).isEnabled():
                        num_sectors += 1
            else:
                num_sectors = 12

            if self.wheel_resting_place is None:
                self.wheel_resting_place = 0
            last = self.wheel_resting_place

            def cycle(start_number: int,
                      delay_ms: int,
                      num_switches: int,
                      sectors: int,
                      target: int = None) -> None:

                number = start_number
                delay_ms = delay_ms / 5
                if start_number > 0:
                    last = start_number - 1
                else:
                    last = sectors - 1
                for each in range(number, num_switches):
                    each = each % sectors
                    # betterspin.wav from
                    # https://freesound.org/people/door15studio/sounds/244774/
                    QSound.play("betterspin.wav")
                    rot_angle = 360 / 12
                    self.wheel_gui.setRotateCropHalve(rot_angle)
                    self.selectionTitle.setText(
                        getattr(self, "label_wheel_%s" % each).text())

                    if self.use_textwheel:
                        if last is not None:
                            getattr(self, "label_wheel_" +
                                    str(last)).setAlignment(Qt.AlignLeft)
                        getattr(self, "label_wheel_" + str(each)).setAlignment(
                            Qt.AlignRight)
                    number = each
                    last = each
                    if number == target and target is not None:
                        return number
                    QtTest.QTest.qWait(delay_ms)
                return number

            if self.skip_spinanimation:
                if self.use_textwheel:
                    for each in range(0, num_sectors):
                        if each != int(destination):
                            getattr(self, "label_wheel_" +
                                    str(each)).setAlignment(Qt.AlignLeft)
                        else:
                            getattr(self, "label_wheel_" +
                                    str(each)).setAlignment(Qt.AlignRight)
                else:
                    pass
            else:
                self.wheel_resting_place = cycle(last, 170, num_sectors * 2,
                                                 num_sectors)
                self.wheel_resting_place = cycle(self.wheel_resting_place, 190,
                                                 num_sectors, num_sectors)
                self.wheel_resting_place = cycle(self.wheel_resting_place, 210,
                                                 num_sectors, num_sectors)
                self.wheel_resting_place = cycle(self.wheel_resting_place, 250,
                                                 num_sectors * 2, num_sectors)
                self.wheel_resting_place = cycle(self.wheel_resting_place,
                                                 350,
                                                 num_sectors * 2,
                                                 num_sectors,
                                                 target=int(destination))
        self.logic_controller.issueAck("spinWheel")

    @pyqtSlot(str, str, str, str)
    def updateGameStats(self, spinsExecuted, maxSpins, currentRound,
                        totalRounds):
        self.logger.debug("enter updateGameStats")
        self.round_spin_frame.setSpinsOccurred(spinsExecuted)
        self.round_spin_frame.setSpinsMax(maxSpins)
        self.round_spin_frame.setRound(currentRound)
        self.round_spin_frame.setRoundTotal(totalRounds)

    @pyqtSlot(str, str, str, str, str)
    def updatePlayer(self, playerid, name, score, tokens, currentPlayer):
        # help with font: https://stackoverflow.com/questions/34398797/bold-font-in-label-with-setbold-method

        getattr(self, "player" + playerid + "Name").setText(name)
        highlight_font = QtGui.QFont()
        if currentPlayer == name:

            highlight_font.setBold(True)
            getattr(self, "player" + playerid + "Name").setFont(highlight_font)
        else:
            highlight_font.setBold(False)
            getattr(self, "player" + playerid + "Name").setFont(highlight_font)
        getattr(self, "player" + playerid + "Score").setText(score)
        getattr(self, "player" + playerid + "FT").setText(tokens)

    @pyqtSlot(list)
    def updateWheel(self, sector_list):
        for i, each in enumerate(sector_list):
            sector_alias = getattr(self, "label_wheel_" + str(i))
            # TODO: This breaks the rules. hmi shouldn't know anything about the protocol
            if each == "bankrupt":
                sector_alias.setStyleSheet(
                    'background-color: black; color: white')
            elif each == "loseturn":
                sector_alias.setStyleSheet("")
            elif each == "accumulatefreeturn":
                sector_alias.setStyleSheet("")
            elif each == 'playerschoice':
                sector_alias.setStyleSheet("")
            elif each == "opponentschoice":
                sector_alias.setStyleSheet("")
            elif each == "doublescore":
                sector_alias.setStyleSheet("")
                #sector_alias.setStylesheet("background-color:#ff0000;")
            sector_alias.setText(each)
        num_sectors = len(sector_list)

        if num_sectors != 12:
            for each in range(num_sectors, 12):
                getattr(self, "label_wheel_" + str(each)).setDisabled(True)

    @pyqtSlot(list)
    def updateBoard(self, category_list):
        for xpos, each in enumerate(category_list, 1):
            valid_prices = each['valid_prices']
            getattr(self.board,
                    "label_board_col" + str(xpos) + "_row1").setText(
                        str(each['name']))
            #self.logger.debug("category_list=%s" % (category_list))
            for ypos, score in enumerate(valid_prices, 2):
                #ypos == enumerate starts at 0 + (row1 is category row), so it starts at 2. therefore ypos + 2. ugly.
                row_alias = getattr(
                    self.board,
                    "label_board_col" + str(xpos) + "_row" + str(ypos))
                if str(score) in each['questions']:
                    getattr(self.board, "label_board_col" + str(xpos) +
                            "_row" + str(ypos)).setText(str(score))
                else:
                    getattr(self.board, "label_board_col" + str(xpos) +
                            "_row" + str(ypos)).setText("")

    @pyqtSlot(str)
    def displayWinner(self, playername):
        for i in reversed(range(self.bodyLayout.count())):
            self.bodyLayout.itemAt(i).widget().hide()
        self.winnerLayout = QtWidgets.QVBoxLayout()
        self.winnerLayout.setObjectName("winnerLayout")
        self.bodyLayout.addLayout(self.winnerLayout)
        self.winnerTitle = QLabel(self)
        self.winnerTitle.setAlignment(Qt.AlignCenter)
        self.winnerTitle.setText("WINNER IS")
        self.winnerTitle.setStyleSheet('''
                            font-family: Arial, Helvetica, sans-serif;
                            background-color: rgb(6,12,233);
                            font-size: 45px;
                            color: #FFFFFF;
                            font-weight: 700;
                            text-decoration: none;
                            font-style: normal;
                            font-variant: normal;
                            text-transform: uppercase;
                            ''')
        self.winnerLabel = QLabel(self)
        self.winnerLabel.setAlignment(Qt.AlignCenter)
        self.winnerLabel.setText(playername)
        self.winnerLabel.setWordWrap(True)
        self.winnerLabel.setStyleSheet('''
                            font-family: Arial, Helvetica, sans-serif;
                            background-color: rgb(6,12,233);
                            font-size: 120px;
                            color: #FFFFFF;
                            font-weight: 700;
                            text-decoration: none;
                            font-style: normal;
                            font-variant: normal;
                            text-transform: uppercase;
                            ''')
        self.winnerLayout.setStretchFactor(self.winnerTitle, 1)
        self.winnerLayout.setStretchFactor(self.winnerLabel, 5)
        self.winnerLayout.addWidget(self.winnerTitle)
        self.winnerLayout.addWidget(self.winnerLabel)

        for i in reversed(range(self.controlLayout.count())):
            self.controlLayout.itemAt(i).widget().hide()
        self.exitButton = HoverButton(self)
        self.exitButton.setText("Quit")
        self.exitButton.setAlignment(Qt.AlignCenter)
        self.exitButton.clicked.connect(self.close)
        self.controlLayout.addWidget(self.exitButton)

    @pyqtSlot(dict)
    def setUIState(self, state):
        if not isinstance(state, dict):
            raise Exception("was expecting state of type dict, received %s" %
                            (str(type(state))))
        if "lock" in state.keys():
            lock = state['lock']
            for each in lock:
                getattr(self, each).setDisabled(True)
        if "unlock" in state.keys():
            unlock = state['unlock']
            for each in unlock:
                getattr(self, each).setEnabled(True)
        if "clear_lcd" in state.keys():
            clear = state['clear_lcd']
            for each in clear:
                getattr(self, each).display("")
        if "clear_textbox" in state.keys():
            clear = state['clear_textbox']
            for each in clear:
                getattr(self, each).setText("")
                pass

    @pyqtSlot(int)
    def startTimer(self, i):
        self.logger.debug("Start")
        self.signal_start_timer.emit(i)

    @pyqtSlot()
    def stopTimer(self):
        self.timer_obj.stop()

    @pyqtSlot()
    def playSpin(self):
        self.sounds["Spin"].play()

    @pyqtSlot()
    def playCorrect(self):
        self.sounds["Correct"].play()

    @pyqtSlot()
    def playIncorrect(self):
        self.sounds["Incorrect"].play()

    @pyqtSlot()
    def playBankrupt(self):
        self.sounds["Bankrupt"].play()

    @pyqtSlot()
    def playDouble(self):
        self.sounds["Double"].play()

    @pyqtSlot()
    def determineFreeTurnSpend(self):
        self.scene_question.render_controls_freeturn()
        for i in reversed(range(self.controlLayout.count())):
            self.controlLayout.itemAt(i).widget().hide()
        self.buttonSpin.hide()
        self.buttonFreeTurnSkip.show()
        self.buttonFreeTurnSpend.show()

    def close(self):
        self.logger.debug("closing")
        self.MSG_controller.quit()
        super(HMI, self).close()

    @pyqtSlot(list)
    def retainPlayerData(self, playerData):
        self.playerData = playerData

    @pyqtSlot()
    def renderSpinButton(self):
        for i in reversed(range(self.controlLayout.count())):
            self.controlLayout.itemAt(i).widget().hide()
        self.buttonSpin.show()