from PySide import QtGui, QtCore import copy from gamestate import QuestionAnswers from player import Player class QuestionWindow(QtGui.QDialog): def __init__(self, players, section, qnumber, question, answers=None, parent=None): super(QuestionWindow, self).__init__(parent) self.players = players self.section = section self.qnumber = qnumber self.question = question if answers is not None: self.answers = answers else: self.answers = QuestionAnswers(self.section, self.qnumber) self._setupGui() self.setWindowTitle("Seopardy - %s - %d" % (section, qnumber*100)) def get_answers(self): return self.answers def _mkQuestionLabel(self, text): question = QtGui.QLabel(text, alignment=QtCore.Qt.AlignCenter) question.setWordWrap(True) question.setStyleSheet("QLabel { font-size: 40px; }") return question def _setupGui(self): self.layout = QtGui.QVBoxLayout() seclabel = QtGui.QLabel(self.section) seclabel.setStyleSheet("QLabel { font-size: 30px; }") self.layout.addWidget(seclabel, alignment=QtCore.Qt.AlignCenter) self.layout.addStretch() qlabel = None if self.question["Type"] == "Text": qlabel = self._mkQuestionLabel(self.question["Question"]) elif self.question["Type"] == "Music": qlabel = self._mkQuestionLabel("Listen...") elif self.question["Type"] == "Image": qlabel = QtGui.QLabel() pixmap = QtGui.QPixmap() pixmap.loadFromData(open(self.question["Question"]).read()) qlabel.setPixmap(pixmap) else: raise ValueError("%s is an unknown type for section %s question name %s" % (self.question["Type"], self.section, self.question["Name"])) self.layout.addWidget(qlabel) self.layout.addStretch() self.setLayout(self.layout) def keyPressEvent(self, e): if e.key() == QtCore.Qt.Key_Escape: if not self.answers.is_answered(): self.answers.nobody_knew() self.close() elif not self.answers.is_answered() and e.key() >= ord('1') and e.key() <= ord(str(len(self.players))): player = self.players[e.key() - ord('1')] qawin = QuestionAnswerWindow(player, self) res = qawin.exec_() if res == QuestionAnswerWindow.CORRECT: self.answers.add_try(player, correct=True) self.accept() elif res == QuestionAnswerWindow.WRONG: self.answers.add_try(player, correct=False) class QuestionAnswerWindow(QtGui.QDialog): CORRECT = 1 WRONG = 2 OOPS = 3 def __init__(self, player, parent=None): super(QuestionAnswerWindow, self).__init__(parent) self.player = player self._setupGui() # move window to bottom right of screen g = QtGui.QApplication.desktop().screenGeometry() self.show() cPos = self.rect() self.move(g.width() - cPos.width(), g.height() - cPos.height()) def _setupGui(self): self.layout = QtGui.QVBoxLayout() self.plabel = QtGui.QLabel(self.player.name) self.plabel.setStyleSheet("QLabel { font-size: 60px; }") self.layout.addWidget(self.plabel, alignment=QtCore.Qt.AlignCenter) btnbox = QtGui.QHBoxLayout() right = QtGui.QPushButton("Correct") right.clicked.connect(lambda: self.done(self.CORRECT)) btnbox.addWidget(right) wrong = QtGui.QPushButton("Wrong") wrong.clicked.connect(lambda: self.done(self.WRONG)) btnbox.addWidget(wrong) btnbox.addStretch() oops = QtGui.QPushButton("Oops") oops.clicked.connect(lambda: self.done(self.OOPS)) btnbox.addWidget(oops) 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): 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: self._addAnswerButton(player, correct) # add 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)