Commit 94caf50c authored by Antoine Lima's avatar Antoine Lima
Browse files

Real setting menu

To customize game's duration and score, language and league parameter.
Can read/write to JSON config file
parent 62d68f63
...@@ -56,6 +56,8 @@ class MainWin(QtWidgets.QMainWindow): ...@@ -56,6 +56,8 @@ class MainWin(QtWidgets.QMainWindow):
self.ui.panels.currentWidget().load() self.ui.panels.currentWidget().load()
self.displaySystemTime() self.displaySystemTime()
self.startTimer(1000) self.startTimer(1000)
self._loadSettings()
#def eventFilter(target, event): #def eventFilter(target, event):
# return event.type()==QEvent.KeyPress and event.key() not in acceptedKeys # return event.type()==QEvent.KeyPress and event.key() not in acceptedKeys
...@@ -84,10 +86,10 @@ class MainWin(QtWidgets.QMainWindow): ...@@ -84,10 +86,10 @@ class MainWin(QtWidgets.QMainWindow):
contentFolder = join(dirname(dirname(abspath(__file__))), 'content') contentFolder = join(dirname(dirname(abspath(__file__))), 'content')
return join(contentFolder, path) return join(contentFolder, path)
def _refreshAfterSettings(self): def _loadSettings(self):
from settings import Settings from settings import Settings
if Settings.ui['fullscreen']: if Settings['ui.fullscreen']:
self.showFullScreen() self.showFullScreen()
QApplication.setOverrideCursor(Qt.BlankCursor); QApplication.setOverrideCursor(Qt.BlankCursor);
else: else:
......
...@@ -40,12 +40,11 @@ class Module(QtWidgets.QWidget): ...@@ -40,12 +40,11 @@ class Module(QtWidgets.QWidget):
self.mainwin.ui.panels.setCurrentIndex(newmod_idx) self.mainwin.ui.panels.setCurrentIndex(newmod_idx)
self.mainwin.ui.panels.setFocusProxy(self.mainwin.modules[newmod_idx]) self.mainwin.ui.panels.setFocusProxy(self.mainwin.modules[newmod_idx])
self.mainwin.modules[newmod_idx].setFocus() self.mainwin.modules[newmod_idx].setFocus()
self.mainwin.modules[newmod_idx].load()
# Select first element of the Module # Select first element of the Module
self.mainwin.modules[newmod_idx].focusNextChild() self.mainwin.modules[newmod_idx].focusNextChild()
self.mainwin.modules[newmod_idx].focusPreviousChild() self.mainwin.modules[newmod_idx].focusPreviousChild()
self.mainwin.modules[newmod_idx].focusPreviousChild() self.mainwin.modules[newmod_idx].load()
def send(self, to, **kwargs): def send(self, to, **kwargs):
mod_idx = self.mainwin.findMod(to) mod_idx = self.mainwin.findMod(to)
......
...@@ -69,7 +69,14 @@ class GameModule(Module): ...@@ -69,7 +69,14 @@ class GameModule(Module):
self.showingReplay = False self.showingReplay = False
if self.replayer: if self.replayer:
self.replayer.start_recording() self.replayer.start_recording()
self.gameoverChecker = GameOverChecker('score', 10)
gameover_type = Settings['gameover.type']
gameover_value = Settings['gameover.value']
if gameover_type=='time':
gameover_value *= 60
self.gameoverChecker = GameOverChecker(gameover_type, gameover_value)
if all([len(val)==0 for val in self.players.values()]): if all([len(val)==0 for val in self.players.values()]):
self.players[Side.Left ].append(PlayerGuest) self.players[Side.Left ].append(PlayerGuest)
......
...@@ -8,8 +8,8 @@ Created on Wed Apr 18 18:34:40 2018 ...@@ -8,8 +8,8 @@ Created on Wed Apr 18 18:34:40 2018
import logging import logging
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtWidgets import QTableWidgetItem, QComboBox, QApplication from PyQt5.QtWidgets import QRadioButton, QSlider
from settings import Settings from settings import Settings
from module import Module from module import Module
...@@ -19,39 +19,85 @@ from ui.options_ui import Ui_Form as OptionsWidget ...@@ -19,39 +19,85 @@ from ui.options_ui import Ui_Form as OptionsWidget
class OptionsModule(Module): class OptionsModule(Module):
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent, OptionsWidget()) super().__init__(parent, OptionsWidget())
self.ui.sliderGameOverValue.valueChanged.connect(self.updateGameOverLabel)
# Button connections self.ui.rbGameOver_Score.clicked.connect(self.updateGameOverLabel)
self.ui.btnSave.clicked.connect(self.handleSave) self.ui.rbGameOver_Time.clicked.connect(self.updateGameOverLabel)
self.ui.btnBack.clicked.connect(self.handleBack)
self.ui.sliderGameOverValue.installEventFilter(self)
def load(self): def load(self):
logging.debug('Loading OptionsModule') logging.debug('Loading OptionsModule')
cbb = QComboBox()
cbb.addItem('true') # Set Gameover condition from settings
cbb.addItem('false') self.ui.rbGameOver_Score.setChecked(Settings['gameover.type']=='score')
self.ui.options.insertRow(self.ui.options.rowCount()) self.ui.rbGameOver_Time.setChecked(Settings['gameover.type']=='time')
self.ui.options.setItem(self.ui.options.rowCount()-1, 0, QTableWidgetItem('FullScreen')) self.ui.sliderGameOverValue.setValue(Settings['gameover.value'])
self.ui.options.setCellWidget(self.ui.options.rowCount()-1, 1, cbb)
# Set League players from settings
self.ui.rbNumPlayerLeague_1.setChecked(Settings['league.playerPerTeam']==1)
self.ui.rbNumPlayerLeague_2.setChecked(Settings['league.playerPerTeam']==2)
# Set Language from settings
self.ui.rbLanguage_English.setChecked(Settings['ui.language']=='en')
self.ui.rbLanguage_French.setChecked(Settings['ui.language']=='fr')
self.selectIndex = 0
self.updateSelection()
self.updateGameOverLabel(0)
def unload(self): def unload(self):
logging.debug('Unloading OptionsModule') logging.debug('Unloading OptionsModule')
# Delete the table's content
self.ui.options.setRowCount(0)
def other(self, **kwargs): def other(self, **kwargs):
logging.debug('Other OptionsModule') logging.debug('Other OptionsModule')
def eventFilter(self, obj, event):
if obj==self.ui.sliderGameOverValue and event.type()==QEvent.KeyPress and (event.key()==Qt.Key_Up or event.key()==Qt.Key_Down):
self.keyPressEvent(event)
return True
return False
def keyPressEvent(self, e): def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
self.handleBack() self.handleBack()
elif e.key() == Qt.Key_Return: elif e.key() == Qt.Key_Return:
self.handleSave() self.handleSave()
elif e.key() == Qt.Key_Up:
#self.parent().focusPreviousChild()
self.selectIndex = self.selectIndex-1 if self.selectIndex!=0 else len(self.selectables)-1
self.updateSelection()
elif e.key() == Qt.Key_Down:
#self.parent().focusNextChild()
self.selectIndex = self.selectIndex+1 if self.selectIndex!=len(self.selectables)-1 else 0
self.updateSelection()
def updateSelection(self):
self.selectables = []
isSelectable = lambda widget: (isinstance(widget, QRadioButton) and widget.isChecked()) or isinstance(widget, QSlider)
for gb in [self.ui.gbGameOver, self.ui.gbLeaguePlayers, self.ui.gbLanguage]:
self.selectables.extend([child for child in gb.children() if isSelectable(child)])
self.selectables[self.selectIndex].setFocus()
def updateGameOverLabel(self, val):
sliderVal = self.ui.sliderGameOverValue.value()
strPoints = '{} point{}'.format(sliderVal, 's' if sliderVal>1 else '')
strTime = '{} minute{}'.format(sliderVal, 's' if sliderVal>1 else '')
self.ui.lblGameOverValue.setText(strPoints if self.ui.rbGameOver_Score.isChecked() else strTime)
def handleSave(self): def handleSave(self):
Settings['ui.fullscreen'] = self.ui.options.cellWidget(0, 1).currentText().lower() == 'true' Settings['ui.language'] = 'en' if self.ui.rbLanguage_English.isChecked() else 'fr'
self.mainwin._refreshAfterSettings() Settings['gameover.type'] = 'score' if self.ui.rbGameOver_Score.isChecked() else 'time'
Settings['gameover.value'] = self.ui.sliderGameOverValue.value()
Settings['league.playerPerTeam'] = 1 if self.ui.rbNumPlayerLeague_1.isChecked() else 2
Settings.saveSettingsToJSON()
self.mainwin._loadSettings()
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
def handleBack(self): def handleBack(self):
# ToDo: Maybe add a warning
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
...@@ -9,10 +9,20 @@ Created on Wed Apr 18 18:34:40 2018 ...@@ -9,10 +9,20 @@ Created on Wed Apr 18 18:34:40 2018
import json import json
import main import main
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Setting):
return obj.__dict__
elif isinstance(obj, String) and obj=='settingsPath':
return None
else:
return json.JSONEncoder.default(self, obj)
class Setting(object): class Setting(object):
TypeName = '' TypeName = ''
def __init__(self, value): def __init__(self, value):
self.type = type(self).TypeName
self.value = value self.value = value
class SettingBoolean(Setting): class SettingBoolean(Setting):
...@@ -36,10 +46,9 @@ class SettingRange(Setting): ...@@ -36,10 +46,9 @@ class SettingRange(Setting):
def __init__(self, value, limits): def __init__(self, value, limits):
Setting.__init__(self, value) Setting.__init__(self, value)
self.lower_limit = min(limits) self.range = [min(limits), max(limits)]
self.upper_limit = max(limits)
if self.value<self.lower_limit or self.value>self.upper_limit: if self.value<self.range[0] or self.value>self.range[1]:
raise ValueError('Setting value {} not in range {}'.format(self.value, (self.lower_limit, self.upper_limit))) raise ValueError('Setting value {} not in range {}'.format(self.value, (self.lower_limit, self.upper_limit)))
class SettingsHolder(object): class SettingsHolder(object):
...@@ -73,13 +82,8 @@ class SettingsHolder(object): ...@@ -73,13 +82,8 @@ class SettingsHolder(object):
@staticmethod @staticmethod
def _parseKey(key): def _parseKey(key):
return [k for k in key.split('.') if k] return [k for k in key.split('.') if k]
def _init_ui(self):
self.ui.append(Setting())
def loadSettingsFromJSON(self): def loadSettingsFromJSON(self):
settings = list()
with open(self.settingsPath, 'r') as f: with open(self.settingsPath, 'r') as f:
content = json.load(f) content = json.load(f)
...@@ -106,4 +110,14 @@ class SettingsHolder(object): ...@@ -106,4 +110,14 @@ class SettingsHolder(object):
getattr(self, cat)[name] = setting getattr(self, cat)[name] = setting
def saveSettingsToJSON(self):
# Deletes the settings path member to prevent it from being saved in the JSON
settingsPath = self.settingsPath
del self.settingsPath
with open(settingsPath, 'w') as f:
content = json.dump(self.__dict__, f, cls=MyEncoder, indent=4)
self.settingsPath = settingsPath
Settings = SettingsHolder(main.MainWin.getContent('settings.json')) Settings = SettingsHolder(main.MainWin.getContent('settings.json'))
...@@ -141,7 +141,7 @@ ...@@ -141,7 +141,7 @@
color: rgb(229, 229, 229); color: rgb(229, 229, 229);
} }
QPushButton { QPushButton, QGroupBox {
background-color: rgba(44, 44, 63, 150); background-color: rgba(44, 44, 63, 150);
border: 1px; border: 1px;
border-radius: 10px; border-radius: 10px;
......
...@@ -31,12 +31,9 @@ ...@@ -31,12 +31,9 @@
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="font"> <property name="font">
<font> <font>
<family>FreeSerif</family> <family>Schoolbook Uralic [pyrs]</family>
<pointsize>72</pointsize> <pointsize>72</pointsize>
<weight>50</weight>
<italic>true</italic> <italic>true</italic>
<bold>false</bold>
<underline>false</underline>
</font> </font>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
......
...@@ -6,13 +6,29 @@ ...@@ -6,13 +6,29 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>728</width> <width>1280</width>
<height>540</height> <height>720</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<property name="styleSheet">
<string notr="true">QRadioButton {
border: 2px solid rgb(74, 74, 107);
border-radius: 10px;
border-color: rgb(74, 74, 107);
}
QRadioButton::checked {
background-color: rgba(44, 44, 63, 240);
}
QRadioButton::indicator {
background-color: transparent;
border: 0px solid transparent;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>15</number> <number>15</number>
...@@ -27,145 +43,476 @@ ...@@ -27,145 +43,476 @@
<number>9</number> <number>9</number>
</property> </property>
<item> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QLabel" name="label">
<property name="verticalScrollBarPolicy"> <property name="font">
<enum>Qt::ScrollBarAsNeeded</enum> <font>
<pointsize>40</pointsize>
</font>
</property>
<property name="text">
<string>Options</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbGameOver">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>18</pointsize>
<weight>75</weight>
<bold>true</bold>
<underline>true</underline>
</font>
</property> </property>
<property name="horizontalScrollBarPolicy"> <property name="autoFillBackground">
<enum>Qt::ScrollBarAlwaysOff</enum> <bool>true</bool>
</property> </property>
<property name="widgetResizable"> <property name="title">
<bool>false</bool> <string>Game Over Condition</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
<widget class="QWidget" name="scrollAreaWidgetContents"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="geometry"> <property name="topMargin">
<rect> <number>40</number>
<x>0</x>
<y>0</y>
<width>696</width>
<height>477</height>
</rect>
</property> </property>
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <layout class="QHBoxLayout" name="horizontalLayout">
<horstretch>0</horstretch> <item>
<verstretch>0</verstretch> <spacer name="horizontalSpacer_3">
</sizepolicy> <property name="orientation">
</property> <enum>Qt::Horizontal</enum>
<layout class="QVBoxLayout" name="verticalLayout_2"> </property>
<property name="margin"> <property name="sizeHint" stdset="0">
<number>0</number> <size>
</property> <width>40</width>
<item> <height>20</height>
<widget class="QTableWidget" name="options"> </size>
<property name="frameShape"> </property>
<enum>QFrame::NoFrame</enum> </spacer>
</property> </item>
<property name="frameShadow"> <item>
<enum>QFrame::Plain</enum> <widget class="QRadioButton" name="rbGameOver_Score">
</property> <property name="sizePolicy">
<property name="showGrid"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<bool>true</bool> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<attribute name="horizontalHeaderVisible"> </sizepolicy>
<bool>true</bool> </property>
</attribute> <property name="minimumSize">
<attribute name="horizontalHeaderStretchLastSection"> <size>
<bool>true</bool> <width>280</width>
</attribute> <height>65</height>
<attribute name="verticalHeaderVisible"> </size>
<bool>false</bool> </property>
</attribute> <property name="font">
<column> <font>
<pointsize>18</pointsize>
<weight>50</weight>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text"> <property name="text">
<string>Name</string> <string>By Score</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="rbGameOver_Time">
<property name="minimumSize">
<size>
<width>280</width>
<height>65</height>
</size>
</property>
<property name="font">
<font>
<pointsize>18</pointsize>
<weight>50</weight>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>By Time</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSlider" name="sliderGameOverValue">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>60</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lblGameOverValue">
<property name="minimumSize">
<size>