from __future__ import print_function from PySide import QtCore, QtGui from player import Player from windows import QuestionWindow, EditAnswersWindow, PlayerStartWindow, VictoryWindow from gamestate import QuestionAnswers class SeopardyGame(QtGui.QWidget): def __init__(self, questions, gamestate, parent=None): super(SeopardyGame, self).__init__(parent) self.questions = questions self.gamestate = gamestate #self.players = [Player.gen_player(i, parent=self) for i in range(1, 4)] self.players = [] for i in range(3): self.add_player() self._inOtherWindow = False self._createGui() self.showFullScreen() # initiate starting the game! QtCore.QCoreApplication.postEvent(self, GameStartEvent()) def add_player(self): self.players.append(Player.gen_player(len(self.players)+1, self)) def _createGui(self): """ Create the board from questions. """ layout = QtGui.QVBoxLayout() headerLayout = QtGui.QHBoxLayout() header = QtGui.QLabel("Header") headerLayout.addWidget(header) headerLayout.setSizeConstraint(QtGui.QLayout.SetMinimumSize) layout.addWidget(header, alignment=QtCore.Qt.AlignCenter) # create board #board = QtGui.QGridLayout(6, len(self.questions.get_sections())) board = QtGui.QGridLayout() board.setSizeConstraint(QtGui.QLayout.SetMaximumSize) for i, sec in enumerate(self.questions.get_sections()): seclabel = QtGui.QLabel(sec, alignment=QtCore.Qt.AlignCenter) seclabel.setStyleSheet("QLabel { font-size: 30px; }") board.addWidget(seclabel, 0, i) for j in range(5): b = QtGui.QPushButton(str((j+1)*100)) b.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) b.setAutoDefault(False) b.setStyleSheet("QPushButton { font-size: 60px; }") b.installEventFilter(FocusKeyGrabber(i+1, j+1, self)) b.clicked.connect(lambda sec=sec, j=j: self.go_to_question(sec, j+1)) board.addWidget(b, j+1, i) layout.addLayout(board) self.board = board # create player bar self.playerBar = QtGui.QHBoxLayout() for i, player in enumerate(self.players): self.playerBar.addWidget(player) if i != len(self.players)-1: self.playerBar.addStretch() layout.addLayout(self.playerBar) self.setLayout(layout) def setFocusToQuestion(self, secno, number): if secno < 1 or secno > len(self.questions.get_sections()) or number > 5 or number < 1: return self.board.itemAtPosition(number, secno-1).widget().setFocus() def event(self, e): if e.type() == GameStartEvent.eventType: # start window if not self._inOtherWindow: self._inOtherWindow = True x = PlayerStartWindow(self.players, self) x.exec_() self._inOtherWindow = False return True else: return super(SeopardyGame, self).event(e) def keyPressEvent(self, e): if e.key() == QtCore.Qt.Key_Escape: self.close() elif e.key() == QtCore.Qt.Key_R: x = PlayerStartWindow(self.players, self) self._inOtherWindow = True x.exec_() self._inOtherWindow = False elif e.key() == QtCore.Qt.Key_V: self.show_victory_window() elif e.key() == QtCore.Qt.Key_E: if self._inOtherWindow: return # find current question section = None qno = None found = False for secno, section in enumerate(self.questions.get_sections(), 0): for qno in range(1, 6): btn = self.board.itemAtPosition(qno, secno).widget() if btn == self.focusWidget(): found = True break if found: break if not found: return self.edit_question_answers(section, qno) def edit_question_answers(self, section, number): self._inOtherWindow = True answers = self.gamestate.get_answers(section, number) if answers is None: answers = QuestionAnswers(section, number) editAnswersWin = EditAnswersWindow(self.players, answers, self) editAnswersWin.exec_() self._inOtherWindow = False oldAnswers = self.gamestate.get_answers(section, number) newAnswers = editAnswersWin.get_new_answers() if oldAnswers: self._set_player_points(oldAnswers, rollback=True) self._set_player_points(newAnswers) self.gamestate.set_answers(section, number, newAnswers) self._restyle_button(section, number, newAnswers) def show_victory_window(self): self._inOtherWindow = True victoryWindow = VictoryWindow(self.players, self) victoryWindow.exec_() self._inOtherWindow = False def go_to_question(self, section, number): if self._inOtherWindow: return self._inOtherWindow = True answers = self.gamestate.get_answers(section, number) qwin = QuestionWindow(self.players, section, number, self.questions.get_question(section, number), answers, self) qwin.showFullScreen() qwin.exec_() self._inOtherWindow = False answers = qwin.get_answers() self.gamestate.set_answers(section, number, answers) # add points to players # FIXME: Note that we cannot add points when revisiting a question self._set_player_points(answers) # restyle the button self._restyle_button(section, number, answers) def _set_player_points(self, answers, rollback=False): for player, correct in answers.get_tries(): prefix = 1 if rollback: prefix *= -1 if not correct: prefix *= -1 player.add_points(answers.points()*prefix) def _restyle_button(self, sec, qno, answers): secno = self.questions.get_number_from_section(sec) btn = self.board.itemAtPosition(qno, secno-1).widget() btnstr = "" btncolor = None if not answers.is_answered(): btn.setText(str(answers.points())) btn.setStyleSheet("QPushButton { font-size: 60px; }") return # restrict number of tries shown numTries = 4 if answers.got_answered() else 3 tries = answers.get_tries() if len(tries) > numTries: btnstr = "...\n" for player, correct in answers.get_tries()[-numTries:]: if correct: btncolor = player.color prefix = "+" else: prefix = "-" btnstr += "%s%s\n" % (prefix, player.name) if not answers.got_answered(): btnstr += "+nobody" btncolor = QtGui.QColor(128, 128, 128) btn.setStyleSheet("QPushButton { background-color: %s; color: white; font-size: 20px; border: none; }" % (btncolor.name(),)) btn.setText(btnstr.strip()) class FocusKeyGrabber(QtCore.QObject): def __init__(self, secno, number, parent, *args, **kwargs): super(FocusKeyGrabber, self).__init__(parent, *args, **kwargs) self._secno = secno self._number = number self._parent = parent def eventFilter(self, obj, e): if e.type() == QtCore.QEvent.KeyPress: if e.key() == QtCore.Qt.Key.Key_Left: self._parent.setFocusToQuestion(self._secno-1, self._number) return True elif e.key() == QtCore.Qt.Key.Key_Right: self._parent.setFocusToQuestion(self._secno+1, self._number) return True elif e.key() == QtCore.Qt.Key.Key_Up: self._parent.setFocusToQuestion(self._secno, self._number-1) return True elif e.key() == QtCore.Qt.Key.Key_Down: self._parent.setFocusToQuestion(self._secno, self._number+1) return True return QtCore.QObject.eventFilter(self, obj, e) class GameStartEvent(QtCore.QEvent): eventType = QtCore.QEvent.Type(QtCore.QEvent.registerEventType()) def __init__(self): super(GameStartEvent, self).__init__(self.eventType)