2015-08-19 11:20:51 +02:00
|
|
|
# Licensed under GPLv3
|
|
|
|
# Written by Sebastian Lohff (seba@someserver.de)
|
|
|
|
# http://seba-geek.de/projects/seopardy/
|
|
|
|
|
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-12-02 00:23:05 +01:00
|
|
|
from music import MusicBox
|
2014-12-17 01:36:14 +01:00
|
|
|
from video import VideoPlayer
|
2013-11-25 19:27:31 +01:00
|
|
|
from player import Player, ButtonEvent, nobodyColor
|
2013-11-07 22:59:18 +01:00
|
|
|
|
2013-11-06 20:42:00 +01:00
|
|
|
class QuestionWindow(QtGui.QDialog):
|
2013-12-18 01:44:52 +01:00
|
|
|
buzzersOpen = QtCore.Signal(bool)
|
|
|
|
playerGotQuestion = QtCore.Signal(int)
|
|
|
|
|
2013-11-28 20:13:30 +01:00
|
|
|
def __init__(self, players, section, qnumber, question, answers=None, dj=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-12-02 00:23:05 +01:00
|
|
|
self.dj = dj
|
2013-12-18 01:44:52 +01:00
|
|
|
|
|
|
|
self._windowSetup = False
|
2014-12-17 01:36:14 +01:00
|
|
|
self._videoPlayer = None
|
2013-12-18 01:44:52 +01:00
|
|
|
|
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
|
|
|
|
2013-12-02 00:23:05 +01:00
|
|
|
if not self.answers.is_answered():
|
2014-12-17 01:36:14 +01:00
|
|
|
if not self._question_has_audio():
|
2013-12-02 02:46:33 +01:00
|
|
|
MusicBox.play_music("questionSong")
|
|
|
|
|
2013-12-02 00:23:05 +01:00
|
|
|
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))
|
2013-11-28 20:13:30 +01:00
|
|
|
|
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-12-02 02:46:33 +01:00
|
|
|
if self.question["Type"] == "Music":
|
|
|
|
tag = "%s-%s" % (self.section, self.qnumber)
|
|
|
|
MusicBox.add_music(tag, self.question["Question"])
|
|
|
|
MusicBox.play_music(tag)
|
2014-12-17 01:36:14 +01:00
|
|
|
elif self.question["Type"] == "Video":
|
|
|
|
self._videoPlayer.play()
|
2013-12-02 02:46:33 +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
|
|
|
|
2013-12-02 00:23:05 +01:00
|
|
|
def closeEvent(self, event):
|
|
|
|
if not self._inWindow:
|
2013-12-18 01:44:52 +01:00
|
|
|
self.buzzersOpen.emit(False)
|
2013-12-02 00:23:05 +01:00
|
|
|
MusicBox.stop_music()
|
2014-12-17 01:36:14 +01:00
|
|
|
if self._videoPlayer:
|
|
|
|
self._videoPlayer.stop()
|
2013-12-02 00:23:05 +01:00
|
|
|
event.accept()
|
|
|
|
else:
|
|
|
|
event.ignore()
|
|
|
|
|
2013-12-02 02:40:21 +01:00
|
|
|
def _mkQuestionLabel(self, text, monospaced=False):
|
2013-11-06 20:42:00 +01:00
|
|
|
question = QtGui.QLabel(text, alignment=QtCore.Qt.AlignCenter)
|
|
|
|
question.setWordWrap(True)
|
2013-12-02 02:40:21 +01:00
|
|
|
extra = ""
|
|
|
|
if monospaced:
|
|
|
|
extra += "font-family: monospace;"
|
|
|
|
question.setStyleSheet("QLabel { font-size: 40px; %s }" % (extra,))
|
2013-11-06 20:42:00 +01:00
|
|
|
|
|
|
|
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
|
2014-12-17 01:36:14 +01:00
|
|
|
stretch = 0
|
2013-11-06 20:42:00 +01:00
|
|
|
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)
|
2013-12-02 02:40:21 +01:00
|
|
|
qlabel.setAlignment(QtCore.Qt.AlignCenter)
|
|
|
|
elif self.question["Type"] == "Code":
|
|
|
|
# to have this a) aligned but b) centered we "cheat" a bit with the spaces...
|
|
|
|
code = self.question["Question"].split("\n")
|
|
|
|
code = map(lambda x: x.replace("\t", " "), code)
|
|
|
|
maxLineLen = max(map(len, code))
|
|
|
|
code = map(lambda x: x + ((maxLineLen-len(x))*" "), code)
|
|
|
|
|
|
|
|
qlabel = self._mkQuestionLabel("<pre>"+"\n".join(code)+"</pre>", monospaced=True)
|
2014-12-17 01:36:14 +01:00
|
|
|
elif self.question["Type"] == "Video":
|
|
|
|
self._videoPlayer = VideoPlayer(self.question["Question"], self.question["Audio"])
|
|
|
|
qlabel = self._videoPlayer.get_widget()
|
|
|
|
stretch = 1
|
2013-11-06 20:42:00 +01:00
|
|
|
else:
|
|
|
|
raise ValueError("%s is an unknown type for section %s question name %s" % (self.question["Type"], self.section, self.question["Name"]))
|
|
|
|
|
2014-12-17 01:36:14 +01:00
|
|
|
self.layout.addWidget(qlabel, stretch=stretch)
|
|
|
|
|
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:
|
2013-12-02 02:46:33 +01:00
|
|
|
done = False
|
|
|
|
if self.question["Type"] == "Music":
|
|
|
|
MusicBox.stop_music()
|
2014-12-17 01:36:14 +01:00
|
|
|
elif self.question["Type"] == "Video":
|
|
|
|
self._videoPlayer.pause()
|
2013-12-02 02:46:33 +01:00
|
|
|
|
2013-11-21 15:38:21 +01:00
|
|
|
self._inWindow = True
|
|
|
|
player = self.players[e.get_playerno()-1]
|
|
|
|
qawin = QuestionAnswerWindow(player, self)
|
2013-12-18 01:44:52 +01:00
|
|
|
self.playerGotQuestion.emit(e.get_playerno())
|
2013-11-21 15:38:21 +01:00
|
|
|
res = qawin.exec_()
|
|
|
|
if res == QuestionAnswerWindow.CORRECT:
|
|
|
|
self.answers.add_try(player, correct=True)
|
2013-12-02 00:23:05 +01:00
|
|
|
self._inWindow = False
|
2013-12-02 02:46:33 +01:00
|
|
|
done = True
|
2013-12-02 00:23:05 +01:00
|
|
|
self.close()
|
2013-11-21 15:38:21 +01:00
|
|
|
elif res == QuestionAnswerWindow.WRONG:
|
|
|
|
self.answers.add_try(player, correct=False)
|
|
|
|
self._inWindow = False
|
2013-12-02 02:46:33 +01:00
|
|
|
|
2013-12-18 01:44:52 +01:00
|
|
|
if not done:
|
|
|
|
self.buzzersOpen.emit(True)
|
|
|
|
if self.question["Type"] == "Music":
|
2014-12-17 01:36:14 +01:00
|
|
|
# resume music if question was not answered
|
2013-12-18 01:44:52 +01:00
|
|
|
MusicBox.play_music("%s-%s" % (self.section, self.qnumber))
|
2014-12-17 01:36:14 +01:00
|
|
|
elif self.question["Type"] == "Video":
|
|
|
|
# resume video if question was not answered
|
|
|
|
self._videoPlayer.play()
|
2013-12-02 02:46:33 +01:00
|
|
|
|
2013-12-19 18:07:29 +01:00
|
|
|
elif e.get_playerno() > len(self.players) and not self._inWindow:
|
|
|
|
# unknown player! to not confuse certain devices we send a buttons open event
|
|
|
|
self.buzzersOpen.emit(True)
|
|
|
|
print("unknown player", e.get_playerno())
|
|
|
|
|
|
|
|
|
2013-11-21 15:38:21 +01:00
|
|
|
return True
|
|
|
|
else:
|
2013-12-19 18:07:29 +01:00
|
|
|
ret = super(QuestionWindow, self).event(e)
|
|
|
|
|
|
|
|
# we want to do this after the window has focus for the first time
|
|
|
|
if not self._windowSetup and e.type() == QtCore.QEvent.FocusIn:
|
2013-12-18 01:44:52 +01:00
|
|
|
if not self.answers.is_answered():
|
|
|
|
self.buzzersOpen.emit(True)
|
|
|
|
self._windowSetup = True
|
|
|
|
|
2013-12-19 18:07:29 +01:00
|
|
|
return ret
|
|
|
|
|
2013-11-21 15:38:21 +01:00
|
|
|
|
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
|
|
|
|
2013-12-19 18:07:06 +01:00
|
|
|
@QtCore.Slot(int)
|
|
|
|
def playerButtonPress(self, no):
|
|
|
|
QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(no)))
|
|
|
|
|
2014-12-17 01:36:14 +01:00
|
|
|
def _question_has_audio(self):
|
|
|
|
return self.question["Type"] == "Music" or (self.question["Type"] == "Video" and self.question["Audio"])
|
2013-12-19 18:07:06 +01:00
|
|
|
|
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()
|
2015-01-06 20:06:33 +01:00
|
|
|
self.setWindowTitle("Seopardy - Answer by Player %s" % (self.player.name,))
|
|
|
|
|
2013-11-07 22:59:18 +01:00
|
|
|
|
|
|
|
# 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()
|
2013-11-28 20:47:24 +01:00
|
|
|
self._dj_points = answers.get_dj_points()
|
|
|
|
self._in_window = False
|
2013-11-18 17:47:03 +01:00
|
|
|
if self._answers:
|
|
|
|
self._tries = copy.copy(self._answers.get_tries())
|
|
|
|
else:
|
|
|
|
self._tries = []
|
|
|
|
|
|
|
|
self._setupGui()
|
2015-01-06 20:06:33 +01:00
|
|
|
self.setWindowTitle("Seopardy - Edit Answers")
|
2013-11-18 17:47:03 +01:00
|
|
|
|
|
|
|
self.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
|
|
|
|
|
|
|
|
def get_new_answers(self):
|
2013-11-28 20:47:24 +01:00
|
|
|
qa = QuestionAnswers(self._answers.section, self._answers.qnumber, dj_points=self._dj_points)
|
|
|
|
|
2013-11-18 17:47:03 +01:00
|
|
|
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
|
|
|
|
|
2013-12-07 21:09:17 +01:00
|
|
|
def closeEvent(self, event):
|
|
|
|
if not self._in_window:
|
|
|
|
event.accept()
|
|
|
|
else:
|
|
|
|
event.ignore()
|
|
|
|
|
2013-11-18 17:47:03 +01:00
|
|
|
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)
|
|
|
|
|
2013-11-28 20:47:24 +01:00
|
|
|
self.xlabel = QtGui.QLabel("+/- right/wrong, d delete, a add, arrows change player\ne edit double jeopardy")
|
2013-11-18 17:47:03 +01:00
|
|
|
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()
|
2013-11-28 20:47:24 +01:00
|
|
|
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
|
2013-11-18 17:47:03 +01:00
|
|
|
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:
|
2013-12-07 21:11:50 +01:00
|
|
|
if self._tries[currFocus][1]:
|
|
|
|
# give nobody the score for this one
|
|
|
|
self._nobody = True
|
2013-11-18 17:47:03 +01:00
|
|
|
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
|
2013-11-28 20:47:24 +01:00
|
|
|
first = True
|
2013-11-18 17:47:03 +01:00
|
|
|
for player, correct in self._tries:
|
2013-11-28 20:47:24 +01:00
|
|
|
self._addAnswerButton(player, correct, first)
|
|
|
|
first = False
|
2013-11-18 17:47:03 +01:00
|
|
|
|
|
|
|
# add the nobody button
|
2013-11-25 19:27:31 +01:00
|
|
|
self._addAnswerButton(Player("nobody", nobodyColor), self._nobody)
|
2013-11-18 17:47:03 +01:00
|
|
|
|
2013-11-28 20:47:24 +01:00
|
|
|
def _addAnswerButton(self, player, correct=False, first=False):
|
2013-11-18 17:47:03 +01:00
|
|
|
prefix = "+" if correct else "-"
|
2013-11-28 20:47:24 +01:00
|
|
|
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)
|
2013-11-18 17:47:03 +01:00
|
|
|
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)
|
2013-11-22 00:01:09 +01:00
|
|
|
|
|
|
|
class PlayerStartWindow(QtGui.QDialog):
|
2013-12-19 18:42:08 +01:00
|
|
|
buzzersOpen = QtCore.Signal(bool)
|
|
|
|
playerGotQuestion = QtCore.Signal(int)
|
|
|
|
|
2013-11-22 00:01:09 +01:00
|
|
|
def __init__(self, players, parent):
|
|
|
|
super(PlayerStartWindow, self).__init__(parent)
|
|
|
|
self._players = players
|
|
|
|
self._parent = parent
|
|
|
|
|
|
|
|
self._playerLineEdits = []
|
2013-12-19 18:42:08 +01:00
|
|
|
self._windowSetup = False
|
2013-11-22 00:01:09 +01:00
|
|
|
|
|
|
|
self._setupGui()
|
2015-01-06 20:06:33 +01:00
|
|
|
self.setWindowTitle("Seopardy - Start")
|
2013-11-22 00:01:09 +01:00
|
|
|
self.show()
|
2013-12-02 23:15:57 +01:00
|
|
|
MusicBox.play_music("startSong")
|
2013-11-22 00:01:09 +01:00
|
|
|
|
|
|
|
# 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:
|
2013-12-07 20:44:17 +01:00
|
|
|
if e.get_playerno() <= len(self._players)+1:
|
|
|
|
if e.get_playerno() == len(self._players)+1:
|
2013-11-22 00:01:09 +01:00
|
|
|
# add a new player
|
2013-12-07 20:44:17 +01:00
|
|
|
self._parent.add_player(addToGui=True)
|
2013-11-22 00:01:09 +01:00
|
|
|
self._guiAddPlayer(self._players[-1])
|
2013-12-07 20:44:17 +01:00
|
|
|
|
|
|
|
layoutItem = self.playerGrid.itemAtPosition(e.get_playerno(), 1)
|
|
|
|
if layoutItem:
|
|
|
|
widget = layoutItem.widget()
|
|
|
|
widget.selectAll()
|
|
|
|
widget.setFocus()
|
2013-12-19 18:42:08 +01:00
|
|
|
|
|
|
|
self.playerGotQuestion.emit(e.get_playerno())
|
2013-11-22 00:01:09 +01:00
|
|
|
return True
|
|
|
|
else:
|
2013-12-19 18:42:08 +01:00
|
|
|
ret = super(PlayerStartWindow, self).event(e)
|
|
|
|
|
|
|
|
if not self._windowSetup and e.type() == QtCore.QEvent.WindowActivate:
|
|
|
|
self.buzzersOpen.emit(True)
|
|
|
|
self._windowSetup = True
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2013-12-02 23:15:57 +01:00
|
|
|
def closeEvent(self, event):
|
|
|
|
MusicBox.stop_music()
|
2013-12-19 18:42:08 +01:00
|
|
|
self.buzzersOpen.emit(False)
|
2013-12-02 23:15:57 +01:00
|
|
|
event.accept()
|
|
|
|
|
2013-11-22 00:01:09 +01:00
|
|
|
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; }")
|
2013-12-19 18:42:08 +01:00
|
|
|
edit.editingFinished.connect(lambda widget=edit, player=player: self._playerDoneEditing(widget, player))
|
2013-11-22 00:01:09 +01:00
|
|
|
self.playerGrid.addWidget(edit, row, 1)
|
|
|
|
|
2013-12-19 18:42:08 +01:00
|
|
|
def _playerDoneEditing(self, widget, player):
|
|
|
|
player.change_name(widget.text())
|
|
|
|
self.buzzersOpen.emit(True)
|
|
|
|
|
|
|
|
@QtCore.Slot(int)
|
|
|
|
def playerButtonPress(self, no):
|
|
|
|
QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(no)))
|
|
|
|
|
2013-11-22 00:01:09 +01:00
|
|
|
|
2013-11-23 17:51:52 +01:00
|
|
|
class VictoryWindow(QtGui.QDialog):
|
|
|
|
def __init__(self, players, parent):
|
|
|
|
super(VictoryWindow, self).__init__(parent)
|
|
|
|
self._players = players
|
|
|
|
self._parent = parent
|
|
|
|
|
|
|
|
self._setupGui()
|
2015-01-06 20:06:33 +01:00
|
|
|
self.setWindowTitle("Seopardy - Victory")
|
2013-12-02 23:15:57 +01:00
|
|
|
MusicBox.play_music("closingSong")
|
2013-11-23 17:51:52 +01:00
|
|
|
|
|
|
|
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)
|
2013-11-25 05:21:11 +01:00
|
|
|
|
2013-12-02 23:15:57 +01:00
|
|
|
def keyPressEvent(self, e):
|
|
|
|
if e.key() == QtCore.Qt.Key_Escape:
|
|
|
|
self.close()
|
|
|
|
|
|
|
|
def closeEvent(self, event):
|
|
|
|
MusicBox.stop_music()
|
|
|
|
event.accept()
|
2013-11-25 05:21:11 +01:00
|
|
|
|
|
|
|
class DoubleJeopardyWindow(QtGui.QDialog):
|
2013-11-27 01:16:44 +01:00
|
|
|
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
|
2013-11-25 05:21:11 +01:00
|
|
|
|
|
|
|
self._setupGui()
|
2015-01-06 20:06:33 +01:00
|
|
|
self.setWindowTitle("Seopardy - Double Jeopardy")
|
2013-11-25 05:21:11 +01:00
|
|
|
|
|
|
|
# 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())
|
|
|
|
|
2013-11-27 01:16:44 +01:00
|
|
|
def get_chosen_points(self):
|
|
|
|
return self._currentPoints
|
|
|
|
|
|
|
|
def get_player(self):
|
|
|
|
return self._currentPlayer
|
|
|
|
|
2013-11-25 05:21:11 +01:00
|
|
|
def _setupGui(self):
|
|
|
|
self.layout = QtGui.QVBoxLayout()
|
|
|
|
|
|
|
|
header = QtGui.QLabel("Double Jeopardy", self)
|
2013-11-27 01:16:44 +01:00
|
|
|
header.setStyleSheet("QLabel { font-size: 50px; }")
|
2013-11-25 05:21:11 +01:00
|
|
|
self.layout.addWidget(header, alignment=QtCore.Qt.AlignCenter)
|
|
|
|
|
2013-11-27 01:16:44 +01:00
|
|
|
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)
|
2013-11-25 05:21:11 +01:00
|
|
|
|
2013-11-27 01:16:44 +01:00
|
|
|
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)
|
2013-11-28 20:02:56 +01:00
|
|
|
start.clicked.connect(self.closeIfNotNobody)
|
2013-11-27 01:16:44 +01:00
|
|
|
self.layout.addWidget(start)
|
2013-11-25 05:21:11 +01:00
|
|
|
|
|
|
|
self.setLayout(self.layout)
|
|
|
|
|
2013-11-28 20:02:56 +01:00
|
|
|
def closeIfNotNobody(self):
|
|
|
|
if self.get_player() is not None:
|
|
|
|
self.close()
|
|
|
|
|
2013-11-27 01:16:44 +01:00
|
|
|
def keyPressEvent(self, e):
|
|
|
|
if e.key() == QtCore.Qt.Key_Escape or e.key() == QtCore.Qt.Key_Enter:
|
2013-11-28 20:02:56 +01:00
|
|
|
self.closeIfNotNobody()
|
2013-11-27 01:16:44 +01:00
|
|
|
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(),))
|