diff --git a/game.py b/game.py index 4347c0a..e51e17e 100644 --- a/game.py +++ b/game.py @@ -3,7 +3,8 @@ from __future__ import print_function from PySide import QtCore, QtGui from player import Player -from windows import QuestionWindow +from windows import QuestionWindow, EditAnswersWindow +from gamestate import QuestionAnswers class SeopardyGame(QtGui.QWidget): def __init__(self, questions, gamestate, parent=None): @@ -11,7 +12,7 @@ class SeopardyGame(QtGui.QWidget): self.questions = questions self.gamestate = gamestate - self.players = [Player.gen_player(i) for i in range(1, 4)] + self.players = [Player.gen_player(i, parent=self) for i in range(1, 4)] self._inOtherWindow = False self._createGui() @@ -57,28 +58,59 @@ class SeopardyGame(QtGui.QWidget): self.setLayout(layout) - #def event(self, e): - # print("Event", e) - # super(SeopardyGame, self).event(e) + def event(self, e): + if e.type() == QtCore.QEvent.KeyPress and e.key() == QtCore.Qt.Key_Left: + print("Key!!!", e.key()) + return super(SeopardyGame, self).event(e) def keyPressEvent(self, e): - print("Mainwindow", e) - print("current widget", e.key(), self.focusWidget()) if e.key() == QtCore.Qt.Key_Escape: self.close() 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 - #editResultsWin = EditResultsWindow() - #editResultsWin.exec_() + + 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 go_to_question(self, section, number): if self._inOtherWindow: return self._inOtherWindow = True - print("question window", section, number) answers = self.gamestate.get_answers(section, number) qwin = QuestionWindow(self.players, section, number, self.questions.get_question(section, number), answers, self) @@ -104,15 +136,20 @@ class SeopardyGame(QtGui.QWidget): prefix *= -1 if not correct: prefix *= -1 - player.add_points(answers.points()*prefix) + player.add_points(answers.points()*prefix, commit=not rollback) def _restyle_button(self, sec, qno, answers): + secno = self.questions.get_number_from_section(sec) btn = self.board.itemAtPosition(qno, secno-1).widget() - print("btn", btn, type(btn)) 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() diff --git a/player.py b/player.py index 4d729c4..0aba7d9 100644 --- a/player.py +++ b/player.py @@ -17,15 +17,15 @@ class Player(QtGui.QWidget): self.color = color self.points = points - self.setup_gui() + self._setup_gui() - def setup_gui(self): + def _setup_gui(self): self.layout = QtGui.QVBoxLayout() - self.name_label = QtGui.QLabel(self.name) + self.name_label = QtGui.QLabel(self.name, self) self.name_label.setStyleSheet("QLabel { font-size: 40px; background-color: %s; color: white; }" % (self.color.name(),)) self.layout.addWidget(self.name_label) - self.points_label = QtGui.QLabel(str(self.points)) + self.points_label = QtGui.QLabel(str(self.points), self) self.points_label.setStyleSheet("QLabel { font-size: 40px;}") self.layout.addWidget(self.points_label, alignment=QtCore.Qt.AlignRight) @@ -35,14 +35,15 @@ class Player(QtGui.QWidget): self.name = new_name self.name_label.set_text(new_name) - def add_points(self, amount): + def add_points(self, amount, commit=True): self.points += amount - self.points_label.setText(str(self.points)) + if commit: + self.points_label.setText(str(self.points)) @classmethod - def gen_player(clazz, num): + def gen_player(clazz, num, parent=None): if num > len(clazz.DEFAULT_PLAYERS): raise ValueError("You tried to generate too many players") - return clazz(*clazz.DEFAULT_PLAYERS[num-1]) + return clazz(*clazz.DEFAULT_PLAYERS[num-1], parent=parent) diff --git a/windows.py b/windows.py index 9cf2dae..bcc80d5 100644 --- a/windows.py +++ b/windows.py @@ -1,8 +1,10 @@ from PySide import QtGui, QtCore +import copy + from gamestate import QuestionAnswers +from player import Player -#class QuestionWindow(QtGui.QWidget): class QuestionWindow(QtGui.QDialog): def __init__(self, players, section, qnumber, question, answers=None, parent=None): super(QuestionWindow, self).__init__(parent) @@ -40,7 +42,6 @@ class QuestionWindow(QtGui.QDialog): qlabel = None if self.question["Type"] == "Text": qlabel = self._mkQuestionLabel(self.question["Question"]) - print(self.question["Question"]) elif self.question["Type"] == "Music": qlabel = self._mkQuestionLabel("Listen...") elif self.question["Type"] == "Image": @@ -57,7 +58,6 @@ class QuestionWindow(QtGui.QDialog): self.setLayout(self.layout) def keyPressEvent(self, e): - print("question", e, e.key()) if e.key() == QtCore.Qt.Key_Escape: if not self.answers.is_answered(): self.answers.nobody_knew() @@ -67,7 +67,6 @@ class QuestionWindow(QtGui.QDialog): qawin = QuestionAnswerWindow(player, self) res = qawin.exec_() if res == QuestionAnswerWindow.CORRECT: - print("Done!") self.answers.add_try(player, correct=True) self.accept() elif res == QuestionAnswerWindow.WRONG: @@ -111,3 +110,151 @@ class QuestionAnswerWindow(QtGui.QDialog): self.layout.addLayout(btnbox) self.setLayout(self.layout) + + +class EditAnswersWindow(QtGui.QDialog): + def __init__(self, players, answers, parent=None): + super(EditAnswersWindow, self).__init__(parent) + self._players = players + self._answers = answers + self._nobody = not answers.got_answered() + if self._answers: + self._tries = copy.copy(self._answers.get_tries()) + else: + self._tries = [] + + self._setupGui() + + self.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self)) + + def get_new_answers(self): + qa = QuestionAnswers(self._answers.section, self._answers.qnumber) + rightPlayer = None + for player, correct in self._tries: + if correct: + rightPlayer = player + else: + qa.add_try(player, correct) + + if rightPlayer: + qa.add_try(rightPlayer, True) + elif self._nobody: + qa.nobody_knew() + + return qa + + def _setupGui(self): + self.layout = QtGui.QVBoxLayout() + + self.qlabel = QtGui.QLabel("Questions") + self.qlabel.setStyleSheet("QLabel { font-size: 30px; }") + self.layout.addWidget(self.qlabel, alignment=QtCore.Qt.AlignCenter) + + self.answerlayout = QtGui.QVBoxLayout() + self._resetAllButtons() + self.layout.addLayout(self.answerlayout) + + self.xlabel = QtGui.QLabel("+/- right/wrong, d delete, a add, arrows change player") + self.xlabel.setStyleSheet("QLabel { font-size: 15px; }") + self.layout.addWidget(self.xlabel) + + self.setLayout(self.layout) + + def keyPressEvent(self, e): + if e.key() == QtCore.Qt.Key_Escape: + self.close() + else: + currFocus = self._getCurrFocus() + if currFocus is None and e.key() != QtCore.Qt.Key_A: + return + + nothingDone = False + if e.key() == QtCore.Qt.Key_Plus: + self._nobody = False + for i, (player, correct) in enumerate(self._tries): + self._tries[i] = (player, i==currFocus) + if currFocus == len(self._tries): + self._nobody = True + elif e.key() == QtCore.Qt.Key_Minus: + if currFocus == len(self._tries): + if len(self._tries) == 0: + self._nobody = False + else: + self._tries[currFocus] = (self._tries[currFocus][0], False) + elif e.key() == QtCore.Qt.Key_A: + self._tries.append((self._players[0], False)) + self._makeNobodyConsistent() + currFocus = len(self._tries) - 1 + elif e.key() == QtCore.Qt.Key_D and currFocus < len(self._tries): + del self._tries[currFocus] + elif e.key() == QtCore.Qt.Key_Left and currFocus < len(self._players): + playlen = len(self._players) + prevPlayer = self._players[(self._players.index(self._tries[currFocus][0])-1+playlen)%playlen] + self._tries[currFocus] = (prevPlayer, self._tries[currFocus][1]) + elif e.key() == QtCore.Qt.Key_Right and currFocus < len(self._tries): + playlen = len(self._players) + nextPlayer = self._players[(self._players.index(self._tries[currFocus][0])+1+playlen)%playlen] + self._tries[currFocus] = (nextPlayer, self._tries[currFocus][1]) + else: + super(EditAnswersWindow, self).keyPressEvent(e) + nothingDone = True + + if not nothingDone: + self._resetAllButtons() + self.updateGeometry() + + # reset focus + print("setting focus to", min(currFocus, self.answerlayout.count()), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().text(), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().hasFocus()) + self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().setFocus(QtCore.Qt.FocusReason.NoFocusReason) + print("setting focus to", min(currFocus, self.answerlayout.count()), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().text(), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().hasFocus()) + print(self.focusWidget()) + if self.focusWidget(): + print("widget", self.focusWidget().text()) + + def _makeNobodyConsistent(self): + if len(self._tries) > 0: + someoneKnew = any([c for p, c in self._tries]) + self._nobody = not someoneKnew + + def _getCurrFocus(self): + if self.focusWidget() is not None: + for i in range(self.answerlayout.count()): + if self.answerlayout.itemAt(i).widget() == self.focusWidget(): + return i + return None + + def _resetAllButtons(self): + print("resetting all buttons") + f = self.answerlayout.takeAt(0) + while f is not None: + f.widget().deleteLater() + f = self.answerlayout.takeAt(0) + + # add buttons + for player, correct in self._tries: + print("building button for", player) + self._addAnswerButton(player, correct) + + # add the nobody button + print("adding the nobody button") + self._addAnswerButton(Player("nobody", QtGui.QColor(128, 128, 128)), self._nobody) + + def _addAnswerButton(self, player, correct=False): + prefix = "+" if correct else "-" + btn = QtGui.QPushButton("\n%s%s\n" % (prefix, player.name), self) + btn.setStyleSheet("QPushButton { background-color: %s; color: white; font-size: 20px; border: none; }" % (player.color.name(),)) + btn.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self)) + self.answerlayout.addWidget(btn) + +class KeyGrabber(QtCore.QObject): + def __init__(self, keys, parent, *args, **kwargs): + super(KeyGrabber, self).__init__(parent, *args, **kwargs) + self._keys = keys + self._parent = parent + + def eventFilter(self, obj, e): + if e.type() == QtCore.QEvent.KeyPress: + if e.key() in self._keys: + self._parent.keyPressEvent(e) + return True + return QtCore.QObject.eventFilter(self, obj, e)