seopardy/windows.py

271 lines
8.9 KiB
Python
Raw Normal View History

2013-11-06 20:42:00 +01:00
from PySide import QtGui, QtCore
2013-11-18 17:47:03 +01:00
import copy
2013-11-11 00:52:37 +01:00
from gamestate import QuestionAnswers
2013-11-21 15:38:21 +01:00
from player import Player, ButtonEvent
2013-11-07 22:59:18 +01:00
2013-11-06 20:42:00 +01:00
class QuestionWindow(QtGui.QDialog):
2013-11-13 21:16:50 +01:00
def __init__(self, players, section, qnumber, question, answers=None, parent=None):
2013-11-06 20:42:00 +01:00
super(QuestionWindow, self).__init__(parent)
2013-11-07 22:59:18 +01:00
self.players = players
2013-11-06 20:42:00 +01:00
self.section = section
2013-11-07 22:59:18 +01:00
self.qnumber = qnumber
2013-11-06 20:42:00 +01:00
self.question = question
2013-11-13 21:16:50 +01:00
if answers is not None:
self.answers = answers
else:
self.answers = QuestionAnswers(self.section, self.qnumber)
2013-11-06 20:42:00 +01:00
self._setupGui()
2013-11-11 00:52:37 +01:00
self.setWindowTitle("Seopardy - %s - %d" % (section, qnumber*100))
2013-11-21 15:38:21 +01:00
self._inWindow = False
2013-11-06 20:42:00 +01:00
2013-11-11 00:52:37 +01:00
def get_answers(self):
return self.answers
2013-11-06 20:42:00 +01:00
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":
2013-11-07 01:20:34 +01:00
qlabel = self._mkQuestionLabel(self.question["Question"])
2013-11-06 20:42:00 +01:00
elif self.question["Type"] == "Music":
2013-11-07 01:20:34 +01:00
qlabel = self._mkQuestionLabel("Listen...")
2013-11-06 20:42:00 +01:00
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"]))
2013-11-07 01:20:47 +01:00
self.layout.addWidget(qlabel)
2013-11-06 20:42:00 +01:00
self.layout.addStretch()
self.setLayout(self.layout)
2013-11-21 15:38:21 +01:00
def event(self, e):
if e.type() == ButtonEvent.eventType:
if e.get_playerno() <= len(self.players) and not self._inWindow:
print("Button", e.get_playerno())
self._inWindow = True
player = self.players[e.get_playerno()-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)
self._inWindow = False
return True
else:
return super(QuestionWindow, self).event(e)
2013-11-07 01:19:50 +01:00
def keyPressEvent(self, e):
if e.key() == QtCore.Qt.Key_Escape:
2013-11-11 00:52:37 +01:00
if not self.answers.is_answered():
self.answers.nobody_knew()
2013-11-07 01:19:50 +01:00
self.close()
2013-11-11 00:52:37 +01:00
elif not self.answers.is_answered() and e.key() >= ord('1') and e.key() <= ord(str(len(self.players))):
2013-11-21 15:38:21 +01:00
QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(chr(e.key()))))
2013-11-07 22:59:18 +01:00
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)
2013-11-18 17:47:03 +01:00
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
2013-11-21 15:24:42 +01:00
#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())
2013-11-18 17:47:03 +01:00
self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().setFocus(QtCore.Qt.FocusReason.NoFocusReason)
2013-11-21 15:24:42 +01:00
#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())
2013-11-18 17:47:03 +01:00
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)