You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

489 lines
16 KiB

from PySide import QtGui, QtCore
import copy
from gamestate import QuestionAnswers
from music import MusicBox
from player import Player, ButtonEvent, nobodyColor
class QuestionWindow(QtGui.QDialog):
def __init__(self, players, section, qnumber, question, answers=None, dj=None, parent=None):
super(QuestionWindow, self).__init__(parent)
self.players = players
self.section = section
self.qnumber = qnumber
self.question = question
self.dj = dj
if answers is not None:
self.answers = answers
else:
self.answers = QuestionAnswers(self.section, self.qnumber)
if not self.answers.is_answered():
MusicBox.play_music("questionSong")
if self.dj:
self.answers.set_dj_points(self.dj[1])
playerNo = self.players.index(self.dj[0])+1
QtCore.QCoreApplication.postEvent(self, ButtonEvent(playerNo))
self._setupGui()
self.setWindowTitle("Seopardy - %s - %d" % (section, qnumber*100))
self._inWindow = False
def get_answers(self):
return self.answers
def closeEvent(self, event):
if not self._inWindow:
MusicBox.stop_music()
event.accept()
else:
event.ignore()
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 event(self, e):
if e.type() == ButtonEvent.eventType:
if e.get_playerno() <= len(self.players) and not self._inWindow:
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._inWindow = False
self.close()
elif res == QuestionAnswerWindow.WRONG:
self.answers.add_try(player, correct=False)
self._inWindow = False
return True
else:
return super(QuestionWindow, self).event(e)
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))):
QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(chr(e.key()))))
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()
self._dj_points = answers.get_dj_points()
self._in_window = False
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, dj_points=self._dj_points)
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\ne edit double jeopardy")
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()
elif e.key() == QtCore.Qt.Key_E:
# edit double jeopardy
if self._dj_points is not None and len(self._tries) > 0 and not self._in_window:
self._in_window = True
dwin = DoubleJeopardyWindow(self._players, self._answers.qnumber*100, self._tries[0][0], current_points=self._dj_points, parent=self)
dwin.exec_()
self._dj_points = dwin.get_chosen_points()
self._tries[0] = (dwin.get_player(), self._tries[0][1])
self._in_window = False
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
first = True
for player, correct in self._tries:
self._addAnswerButton(player, correct, first)
first = False
# add the nobody button
self._addAnswerButton(Player("nobody", nobodyColor), self._nobody)
def _addAnswerButton(self, player, correct=False, first=False):
prefix = "+" if correct else "-"
dj = " (D)" if first and self._dj_points is not None else ""
btn = QtGui.QPushButton("\n%s%s%s\n" % (prefix, player.name, dj), 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)
class PlayerStartWindow(QtGui.QDialog):
def __init__(self, players, parent):
super(PlayerStartWindow, self).__init__(parent)
self._players = players
self._parent = parent
self._playerLineEdits = []
#print(self.disconnect(self, QtCore.SIGNAL("accepted()"), self, QtCore.SLOT("accept()")))
self._setupGui()
self.show()
# center window
g = QtGui.QApplication.desktop().screenGeometry()
cPos = self.rect()
self.move(g.width()/2 - cPos.width()/2, g.height()/2 - cPos.height()/2)
def event(self, e):
if e.type() == ButtonEvent.eventType:
if e.get_playerno() <= len(self.players)+1:
if e.get_playerno() == len(self.players)+1:
# add a new player
self._parent.add_player()
self._guiAddPlayer(self._players[-1])
self.playergrid.itemAtPosition(e.get_playerno()-1, 1).selectAll()
return True
else:
return super(PlayerStartWindow, self).event(e)
def keyPressEvent(self, e):
# needed to circumvent dialogclosing when enter is pressed
if e.key() == QtCore.Qt.Key_Escape:
self.close()
elif e.key() == QtCore.Qt.Key_K:
# FIXME: Remove this
QtCore.QCoreApplication.postEvent(self, ButtonEvent(1))
def _setupGui(self):
self.layout = QtGui.QVBoxLayout()
self.playerGrid = QtGui.QGridLayout()
for player in self._players:
self._guiAddPlayer(player)
self.layout.addLayout(self.playerGrid)
startbtn = QtGui.QPushButton("\nStart\n", self)
startbtn.setStyleSheet("QPushButton { font-size: 40px; }")
startbtn.clicked.connect(self.close)
self.layout.addWidget(startbtn)
self.setLayout(self.layout)
def _guiAddPlayer(self, player):
row = self.playerGrid.rowCount()
label = QtGui.QLabel("Player %d" % (row,), self)
label.setStyleSheet("QLabel { font-size: 40px; background-color: %s; color: white; }" % (player.color.name(),))
self.playerGrid.addWidget(label, row, 0)
edit = QtGui.QLineEdit(player.name, self)
edit.setStyleSheet("QLineEdit { font-size: 40px; }")
edit.editingFinished.connect(lambda widget=edit, player=player: player.change_name(edit.text()))
self.playerGrid.addWidget(edit, row, 1)
class VictoryWindow(QtGui.QDialog):
def __init__(self, players, parent):
super(VictoryWindow, self).__init__(parent)
self._players = players
self._parent = parent
self._setupGui()
def _setupGui(self):
self.layout = QtGui.QVBoxLayout()
self.playerGrid = QtGui.QGridLayout()
winPlayers = sorted(self._players, key=lambda p: p.points, reverse=True)
for i, player in enumerate(winPlayers):
label = QtGui.QLabel(player.name, self)
fsize = 60 if i == 0 else 25
label.setStyleSheet("QLabel { font-size: %dpx; background-color: %s; color: white; }" % (fsize, player.color.name(),))
self.playerGrid.addWidget(label, i, 0)
points = QtGui.QLabel(str(player.points), self)
points.setStyleSheet("QLabel { font-size: %dpx; }" % (fsize,))
self.playerGrid.addWidget(points, i, 1, alignment=QtCore.Qt.AlignRight)
self.layout.addLayout(self.playerGrid)
self.setLayout(self.layout)
class DoubleJeopardyWindow(QtGui.QDialog):
def __init__(self, player, points, current_player=None, current_points=None, parent=None):
super(DoubleJeopardyWindow, self).__init__(parent)
self._player = player
self._currentPlayer = current_player
self._points = points
if current_points:
self._currentPoints = current_points
else:
self._currentPoints = points
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 get_chosen_points(self):
return self._currentPoints
def get_player(self):
return self._currentPlayer
def _setupGui(self):
self.layout = QtGui.QVBoxLayout()
header = QtGui.QLabel("Double Jeopardy", self)
header.setStyleSheet("QLabel { font-size: 50px; }")
self.layout.addWidget(header, alignment=QtCore.Qt.AlignCenter)
self.pbtn = QtGui.QPushButton("", self)
self._stylePlayerButton()
self.pbtn.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
self.layout.addWidget(self.pbtn)
self.pointsbtn = QtGui.QPushButton("% 5s" % self._currentPoints)
self.pointsbtn.setStyleSheet("QPushButton { font-size: 50px; border: none; }")
self.pointsbtn.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
self.layout.addWidget(self.pointsbtn, alignment=QtCore.Qt.AlignCenter)
self.pointsbtn.setFocus()
start = QtGui.QPushButton("Done", self)
start.clicked.connect(self.closeIfNotNobody)
self.layout.addWidget(start)
self.setLayout(self.layout)
def closeIfNotNobody(self):
if self.get_player() is not None:
self.close()
def keyPressEvent(self, e):
if e.key() == QtCore.Qt.Key_Escape or e.key() == QtCore.Qt.Key_Enter:
self.closeIfNotNobody()
elif e.key() == QtCore.Qt.Key_Left or e.key() == QtCore.Qt.Key_Right:
if self.focusWidget() == self.pbtn:
if e.key() == QtCore.Qt.Key_Right:
if self._currentPlayer == None:
self._currentPlayer = self._player[0]
elif self._currentPlayer == self._player[-1]:
self._currentPlayer = None
else:
self._currentPlayer = self._player[self._player.index(self._currentPlayer)+1]
elif e.key() == QtCore.Qt.Key_Left:
if self._currentPlayer == None:
self._currentPlayer = self._player[-1]
elif self._currentPlayer == self._player[0]:
self._currentPlayer = None
else:
self._currentPlayer = self._player[self._player.index(self._currentPlayer)-1]
self._stylePlayerButton()
elif self.focusWidget() == self.pointsbtn:
if e.key() == QtCore.Qt.Key_Right and self._currentPoints < self._points*2:
self._currentPoints += 50
elif e.key() == QtCore.Qt.Key_Left and self._currentPoints > self._points/2:
self._currentPoints += -50
self.pointsbtn.setText("% 4s" % self._currentPoints)
def _stylePlayerButton(self):
player = None
color = None
if self._currentPlayer == None:
player = "nobody"
color = nobodyColor
else:
player = self._currentPlayer.name
color = self._currentPlayer.color
self.pbtn.setText(player)
self.pbtn.setStyleSheet("QPushButton { background-color: %s; color: white; font-size: 50px; border: none; }" % (color.name(),))