...
 
Commits (3)
/__pycache__/
*/__pycache__/
/.spyproject/
*/*.log
*/*_ui.py
*/*_rc.py
[codestyle]
indentation = True
[main]
version = 0.1.0
[encoding]
text_encoding = utf-8
[main]
version = 0.1.0
[vcs]
use_version_control = False
version_control_system =
[main]
version = 0.1.0
[workspace]
restore_data_on_startup = True
save_data_on_exit = True
save_history = True
save_non_project_files = False
[main]
version = 0.1.0
recent_files = ['/home/antoine/prog/PR/source-rasp/main.py', '/home/antoine/prog/PR/source-rasp/modules/game.py', '/home/antoine/prog/PR/content/settings.json', '/home/antoine/prog/PR/source-rasp/replay.py', '/home/antoine/prog/PR/source-rasp/com.py']
......@@ -103,4 +103,4 @@ For the time being, those are provided by the PI camera module.
## Todo
* [ ] Filter serial ports to get arduinos or specific serial id
* [ ] Add the possibility to stop the replay mid-video by pushing any button
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 18:34:40 2018
@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""
import logging
import sqlite3
class DatabaseError(Exception):
pass
class Database():
__db = None
def __init__(self):
if not Database.__db:
from main import MainWin
db_path = MainWin.getContent('babyfut.sqlite')
self._connection = sqlite3.connect(db_path)
@staticmethod
def instance():
'''
Singleton
'''
if not Database.__db:
Database.__db = Database()
return Database.__db
@property
def _cursor(self):
return self._connection.cursor()
def select_one(self, query, *args):
res = self._cursor.execute(query, args).fetchone()
if not res:
raise DatabaseError('Query \"{}\" returned nothing with args {}'.format(query, args))
return res
def select_guest_team(self):
return self.select_one('SELECT id FROM players WHERE fname LIKE "guest"')[0]
def insert_team(self, players, goals):
if len(players)<2:
players.append(None)
logging.debug('DB Inserting {} to table Teams'.format((goals, players[0], players[1],)))
self._cursor.execute('INSERT INTO Teams (nGoals, player1, player2) VALUES (?, ?, ?)', (goals, players[0], players[1],))
self._connection.commit()
return self._cursor.execute('SELECT seq FROM sqlite_sequence WHERE name="Teams"').fetchone()[0]
def insert_match(self, start_time, duration, team1, team2):
logging.debug('DB Inserting {} to table Matchs'.format((start_time, duration, team1, team2,)))
self._cursor.execute('INSERT INTO Matchs (timestamp, duration, winningTeam, losingTeam) VALUES (?, ?, ?, ?)', (start_time, duration, team1, team2,))
self._connection.commit()
def close(self):
self._connection.close()
......@@ -9,7 +9,11 @@ Created on Wed Apr 18 18:34:40 2018
import logging
import pyautogui # PyPi library
from threading import Thread
import RPi.GPIO as GPIO
from main import OnRasp
if OnRasp:
import RPi.GPIO as GPIO
from player import Side
......@@ -27,21 +31,23 @@ class GPIOThread(Thread):
Thread.__init__(self)
self.dispatcher = dispatcher
self.continueRunning = True
if OnRasp:
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
for pin in GPIOThread._keyButtonBindings.keys():
print(pin)
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(pin, GPIO.RISING, callback=self.handleButtonPress)
for pin in GPIOThread._keyButtonBindings.keys():
print(pin)
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(pin, GPIO.RISING, callback=self.handleButtonPress)
def run(self):
try:
while self.continueRunning:
pass
finally:
GPIOThread.clean()
if OnRasp:
try:
while self.continueRunning:
pass
finally:
GPIOThread.clean()
def handleButtonPress(self, button_pin):
if button_pin not in GPIOThread._keyButtonBindings.keys():
......@@ -56,4 +62,5 @@ class GPIOThread(Thread):
@staticmethod
def clean():
GPIO.cleanup()
if OnRasp:
GPIO.cleanup()
......@@ -6,6 +6,9 @@ Created on Wed Apr 18 18:34:40 2018
@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""
import os
OnRasp = os.uname()[1] == 'raspberrypi'
import sys
import logging
import threading
......@@ -19,6 +22,7 @@ from ui.main_ui import Ui_MainWindow
from modules import *
from player import Side
from input import GPIOThread
from database import Database
class MainWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
......@@ -52,6 +56,8 @@ class MainWin(QtWidgets.QMainWindow):
self.ui.panels.currentWidget().load()
self.displaySystemTime()
self.startTimer(1000)
self._loadSettings()
#def eventFilter(target, event):
# return event.type()==QEvent.KeyPress and event.key() not in acceptedKeys
......@@ -80,10 +86,10 @@ class MainWin(QtWidgets.QMainWindow):
contentFolder = join(dirname(dirname(abspath(__file__))), 'content')
return join(contentFolder, path)
def _refreshAfterSettings(self):
def _loadSettings(self):
from settings import Settings
if Settings.ui['fullscreen']:
if Settings['ui.fullscreen']:
self.showFullScreen()
QApplication.setOverrideCursor(Qt.BlankCursor);
else:
......@@ -122,3 +128,4 @@ if __name__=='__main__':
finally:
GPIOThread.clean()
Database.instance().close()
......@@ -40,12 +40,11 @@ class Module(QtWidgets.QWidget):
self.mainwin.ui.panels.setCurrentIndex(newmod_idx)
self.mainwin.ui.panels.setFocusProxy(self.mainwin.modules[newmod_idx])
self.mainwin.modules[newmod_idx].setFocus()
self.mainwin.modules[newmod_idx].load()
# Select first element of the Module
self.mainwin.modules[newmod_idx].focusNextChild()
self.mainwin.modules[newmod_idx].focusPreviousChild()
self.mainwin.modules[newmod_idx].focusPreviousChild()
self.mainwin.modules[newmod_idx].load()
def send(self, to, **kwargs):
mod_idx = self.mainwin.findMod(to)
......
......@@ -48,9 +48,9 @@ class AuthLeagueModule(AuthModuleBase):
# Update the left side description
player.displayImg(self.ui.img)
self.ui.lblName.setText(player.name)
self.ui.lblStat1.setText('{} Victories'.format(player.stats.victories))
self.ui.lblStat2.setText('{} Games Played'.format(player.stats.games_played))
self.ui.lblStat3.setText('{} Goals Scored'.format(player.stats.goals_scored))
self.ui.lblStat1.setText('{} Victories'.format(player.stats['victories']))
self.ui.lblStat2.setText('{} Games Played'.format(player.stats['games_played']))
self.ui.lblStat3.setText('{} Goals Scored'.format(player.stats['goals_scored']))
if player!=PlayerEmpty:
# Update the right side list, making sure that the added player is showed
......
......@@ -12,7 +12,8 @@ from PyQt5 import QtWidgets
from PyQt5.QtGui import QRegion
from PyQt5.QtCore import QTime, QTimer, QRect, Qt
from player import Side
from database import Database, DatabaseError
from player import Side, PlayerGuest
from module import Module
import modules
from ui.endgame_ui import Ui_Form as EndGameWidget
......@@ -31,13 +32,16 @@ class EndGameModule(Module):
self.setActiveP2(len(self.players[self.winSide])>1)
self.displayPlayers()
db = Database.instance()
idTeams = {}
for side in [Side.Left, Side.Right]:
for player in self.players[side]:
player.stats.victories += 1 if side==self.winSide else 0
player.stats.goals_scored += self.scores[side]
player.stats.time_played += self.time
player.stats.games_played += 1
player.save()
if PlayerGuest in self.players[side]:
idTeams[side] = db.select_guest_team()
else:
idTeams[side] = db.insert_team([player.id for player in self.players[side]], self.scores[side])
db.insert_match(int(self.start_time), int(self.duration), idTeams[self.winSide], idTeams[self.winSide.opposite])
# Quit the screen after 5 seconds if the user doesn't do it before
#self.screenTimeout.start(5000)
......@@ -58,8 +62,12 @@ class EndGameModule(Module):
self.winSide = val
elif key=='scores':
self.scores = val
elif key=='time':
self.time = val
elif key=='start_time':
self.start_time = val
print('start_time {}'.format(val))
elif key=='duration':
self.duration = val
print('duration {}'.format(val))
#else:
# raise ValueError('Unknown message identifier {}'.format(kwargs)
......
......@@ -11,7 +11,7 @@ import logging
from PyQt5 import QtWidgets
from PyQt5.QtGui import QRegion
from PyQt5.QtCore import QTime, QTimer, QRect, Qt, QUrl
from PyQt5.QtCore import QDateTime, QDate, QTime, QTimer, QRect, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
......@@ -40,7 +40,7 @@ class GameOverChecker():
if self.conditionType=='score' and scores[bestPlayer]>=self.limit:
return bestPlayer
elif self.conditionType=='time' and time>self.limit:
elif self.conditionType=='time' and time>=self.limit:
return bestPlayer
else:
return Side.Undef
......@@ -69,7 +69,14 @@ class GameModule(Module):
self.showingReplay = False
if self.replayer:
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()]):
self.players[Side.Left ].append(PlayerGuest)
......@@ -174,5 +181,8 @@ class GameModule(Module):
winSide = self.gameoverChecker.check(self.getGameTime(), self.scores)
if winSide!=Side.Undef:
self.send(modules.EndGameModule, players=self.players, winSide=winSide, scores=self.scores, time=self.getGameTime())
start_timestamp = int(QDateTime(QDate.currentDate(), self.gameStartTime).toMSecsSinceEpoch()/1000)
self.send(modules.EndGameModule, players=self.players, winSide=winSide, scores=self.scores)
self.send(modules.EndGameModule, start_time=start_timestamp, duration=self.getGameTime())
self.switchModule(modules.EndGameModule)
......@@ -28,10 +28,10 @@ class LeaderboardItemWidget(QtWidgets.QWidget):
self.ui.lblFName.setText(player.fname)
self.ui.lblLName.setText(player.lname)
self.ui.lblVictories.setText (self.ui.lblVictories.text().replace('####', str(player.stats.victories)))
self.ui.lblGamesPlayed.setText (self.ui.lblGamesPlayed.text().replace('####', str(player.stats.games_played)))
self.ui.lblGoalsScored.setText (self.ui.lblGoalsScored.text().replace('####', str(player.stats.goals_scored)))
self.ui.lblMinutesPlayed.setText(self.ui.lblMinutesPlayed.text().replace('####', str(player.stats.time_played)))
self.ui.lblVictories.setText (self.ui.lblVictories.text().replace('####', str(player.stats['victories'])))
self.ui.lblGamesPlayed.setText (self.ui.lblGamesPlayed.text().replace('####', str(player.stats['games_played'])))
self.ui.lblGoalsScored.setText (self.ui.lblGoalsScored.text().replace('####', str(player.stats['goals_scored'])))
self.ui.lblMinutesPlayed.setText(self.ui.lblMinutesPlayed.text().replace('####', str(player.stats['time_played'])))
self.ui.pushButton.clicked.connect(lambda: logging.debug('clicked'))
......@@ -48,13 +48,14 @@ class LeaderboardModule(Module):
self.selectedSort = 0
self.sortMethodRB = [self.ui.rbName, self.ui.rbVictories, self.ui.rbScore, self.ui.rbGamesPlayed, self.ui.rbTimePlayed]
self.sortMethodAttr = ['lname', 'stats.victories', 'stats.goals_scored', 'stats.games_played', 'stats.time_played']
self.sortMethodAttr = ['lname', 'stats_property.victories', 'stats_property.goals_scored', 'stats_property.games_played', 'stats_property.time_played']
self.sortMethodRB[self.selectedSort].setChecked(True)
def load(self):
logging.debug('Loading LeaderboardModule')
self.loadList()
self.setFocus()
def unload(self):
logging.debug('Unloading LeaderboardModule')
......
......@@ -56,7 +56,7 @@ class MenuModule(Module):
self.send(modules.MenuModule, rfid=-2, source=Side.Left)
elif e.key() == Qt.Key_Right:
self.send(modules.MenuModule, rfid=-4, source=Side.Right)
self.send(modules.MenuModule, rfid=-3, source=Side.Right)
elif e.key() == Qt.Key_Return:
if QApplication.focusWidget()==None:
......
......@@ -8,8 +8,8 @@ Created on Wed Apr 18 18:34:40 2018
import logging
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QTableWidgetItem, QComboBox, QApplication
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtWidgets import QRadioButton, QSlider
from settings import Settings
from module import Module
......@@ -19,39 +19,85 @@ from ui.options_ui import Ui_Form as OptionsWidget
class OptionsModule(Module):
def __init__(self, parent):
super().__init__(parent, OptionsWidget())
# Button connections
self.ui.btnSave.clicked.connect(self.handleSave)
self.ui.btnBack.clicked.connect(self.handleBack)
self.ui.sliderGameOverValue.valueChanged.connect(self.updateGameOverLabel)
self.ui.rbGameOver_Score.clicked.connect(self.updateGameOverLabel)
self.ui.rbGameOver_Time.clicked.connect(self.updateGameOverLabel)
self.ui.sliderGameOverValue.installEventFilter(self)
def load(self):
logging.debug('Loading OptionsModule')
cbb = QComboBox()
cbb.addItem('true')
cbb.addItem('false')
self.ui.options.insertRow(self.ui.options.rowCount())
self.ui.options.setItem(self.ui.options.rowCount()-1, 0, QTableWidgetItem('FullScreen'))
self.ui.options.setCellWidget(self.ui.options.rowCount()-1, 1, cbb)
# Set Gameover condition from settings
self.ui.rbGameOver_Score.setChecked(Settings['gameover.type']=='score')
self.ui.rbGameOver_Time.setChecked(Settings['gameover.type']=='time')
self.ui.sliderGameOverValue.setValue(Settings['gameover.value'])
# 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):
logging.debug('Unloading OptionsModule')
# Delete the table's content
self.ui.options.setRowCount(0)
def other(self, **kwargs):
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):
if e.key() == Qt.Key_Escape:
self.handleBack()
elif e.key() == Qt.Key_Return:
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):
Settings['ui.fullscreen'] = self.ui.options.cellWidget(0, 1).currentText().lower() == 'true'
self.mainwin._refreshAfterSettings()
Settings['ui.language'] = 'en' if self.ui.rbLanguage_English.isChecked() else 'fr'
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)
def handleBack(self):
# ToDo: Maybe add a warning
self.switchModule(modules.MenuModule)
......@@ -7,7 +7,10 @@ Created on Wed Apr 18 18:34:40 2018
"""
import logging
import sqlite3
from enum import Enum
from database import Database, DatabaseError
class Side(Enum):
'''
......@@ -16,52 +19,43 @@ class Side(Enum):
Undef = -1
Left = 0
Right = 1
@property
def opposite(self):
return Side.Right if self==Side.Left else Side.Left
class Player():
def __init__(self, id, fname='', lname='', pic_path=':ui/img/placeholder_head.jpg'):
__query_infos = 'SELECT id, fname, lname, pic FROM Players WHERE rfid==?'
__query_time_goals_games = 'SELECT SUM(Matchs.duration) AS timePlayed, SUM(Teams.nGoals) AS goalsScored, COUNT(*) AS gamesPlayed FROM Teams INNER JOIN Matchs ON (Teams.id==Matchs.winningTeam OR Teams.id==Matchs.losingTeam) WHERE (Teams.player1==? OR player2==?)'
__query_victories = 'SELECT COUNT(*) AS victories FROM Players INNER JOIN Teams ON (Players.id==Teams.player1 OR Players.id==Teams.player2) INNER JOIN Matchs ON (Teams.id==Matchs.winningTeam) WHERE Players.id==?'
_placeholder_pic_path = ':ui/img/placeholder_head.jpg'
def __init__(self, id, fname, lname, pic_path, stats):
self.id = id
self.fname = fname
self.lname = lname
self.pic_path = pic_path
self.stats = Stat(id)
self.pic_path = pic_path if pic_path else Player._placeholder_pic_path # Default pic if None
self.stats = stats
@staticmethod
def fromRFID(id):
fname, lname, pic_url = '','','' # Replace with DB calls
if id==-1:
player = Player(id, 'Guest')
elif id==-2:
player = Player(id, 'Alfredo', 'Enrique')
elif id==-3:
player = Player(id, 'Bastien', 'Dali')
player.stats.victories = 1
elif id==-4:
player = Player(id, 'Carim', 'Cuebache')
player.stats.time_played = 1
elif id==-5:
player = Player(id, 'Dorian', 'Boulet')
player.stats.games_played = 1
elif id==-6:
player = Player(id, 'Enzo', 'Arobaz')
player.stats.goals_scored = 1
def fromRFID(rfid):
db = Database.instance()
try:
# Retrieve generic informations
id, fname, lname, pic = db.select_one(Player.__query_infos, rfid)
elif id==-10:
player = Player(id, 'Name', '')
player.stats.victories = ''
player.stats.time_played = ''
player.stats.games_played = ''
player.stats.goals_scored = ''
# Retrieve stats
stats = {}
stats['time_played'], stats['goals_scored'], stats['games_played'] = db.select_one(Player.__query_time_goals_games, id, id)
stats['victories'], = db.select_one(Player.__query_victories, id)
else:
player = Player(id, fname, lname, pic_url)
return Player(id, fname, lname, pic, stats)
return player
except DatabaseError as e:
logging.warn('DB Error: {}'.format(e))
return PlayerGuest
def displayImg(self, containerWidget):
containerWidget.setStyleSheet('border-image: url({});'.format(self.pic_path))
......@@ -70,29 +64,21 @@ class Player():
'''
Update or create the player in database
'''
# TODO
pass
@property
def name(self):
return '{} {}'.format(self.fname, self.lname.upper())
@property
def pic(self):
return QPixmap(self.pic_path)
class Stat():
def __init__(self, player_id):
self.victories = 0
self.time_played = 0
self.games_played = 0
self.goals_scored = 0
def stats_property(self):
class Stat:
def __init__(self, stats):
self.victories = stats['victories']
self.time_played = stats['time_played']
self.goals_scored = stats['goals_scored']
self.games_played = stats['games_played']
if player_id >= 0:
self.victories = 0
self.time_played = 0
self.games_played = 0
self.goals_scored = 0
return Stat(self.stats)
PlayerGuest = Player.fromRFID(-1)
PlayerEmpty = Player.fromRFID(-10)
PlayerEmpty = Player(-1, '', '', Player._placeholder_pic_path, {'time_played':'', 'goals_scored':'', 'games_played':'', 'victories': ''})
......@@ -6,15 +6,12 @@ Created on Wed Apr 18 18:34:40 2018
@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""
import os
from threading import Thread, Event
from main import MainWin
from main import MainWin, OnRasp
from settings import Settings
onRasp = os.uname()[1] == 'raspberrypi'
if onRasp:
if OnRasp:
import picamera
class Replay(Thread):
......@@ -27,7 +24,7 @@ class Replay(Thread):
self.stop_flag = Event()
self.stopped_flag = Event()
if onRasp:
if OnRasp:
self.cam = picamera.PiCamera()
self.cam.resolution = Settings['picam.resolution']
self.cam.framerate = Settings['picam.fps']
......@@ -36,14 +33,15 @@ class Replay(Thread):
self.stream = picamera.PiCameraCircularIO(self.cam, seconds=Settings['replay.duration'])
def start_recording(self):
if onRasp:
if OnRasp:
self.start_flag.set()
def stop_recording(self):
if onRasp:
if OnRasp:
self.stop_flag.set()
self.stopped_flag.wait()
# Clear all control flags
self.stop_flag.clear()
self.start_flag.clear()
self.stopped_flag.clear()
......@@ -69,6 +67,8 @@ class Replay(Thread):
self.stream.copy_to(self.replayPath)
self.stream.clear()
# Set this flag to tell the calling thread that replay is saved
self.stopped_flag.set()
self.cam.close()
......@@ -76,4 +76,4 @@ class Replay(Thread):
@staticmethod
def isCamAvailable():
return onRasp # and other checks (ToDo)
return OnRasp # and other checks (ToDo)
......@@ -9,10 +9,20 @@ Created on Wed Apr 18 18:34:40 2018
import json
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):
TypeName = ''
def __init__(self, value):
self.type = type(self).TypeName
self.value = value
class SettingBoolean(Setting):
......@@ -36,10 +46,9 @@ class SettingRange(Setting):
def __init__(self, value, limits):
Setting.__init__(self, value)
self.lower_limit = min(limits)
self.upper_limit = max(limits)
self.range = [min(limits), 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)))
class SettingsHolder(object):
......@@ -73,13 +82,8 @@ class SettingsHolder(object):
@staticmethod
def _parseKey(key):
return [k for k in key.split('.') if k]
def _init_ui(self):
self.ui.append(Setting())
def loadSettingsFromJSON(self):
settings = list()
with open(self.settingsPath, 'r') as f:
content = json.load(f)
......@@ -106,4 +110,14 @@ class SettingsHolder(object):
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'))
......@@ -141,7 +141,7 @@
color: rgb(229, 229, 229);
}
QPushButton {
QPushButton, QGroupBox {
background-color: rgba(44, 44, 63, 150);
border: 1px;
border-radius: 10px;
......
......@@ -31,12 +31,9 @@
<widget class="QLabel" name="label">
<property name="font">
<font>
<family>FreeSerif</family>
<family>Schoolbook Uralic [pyrs]</family>
<pointsize>72</pointsize>
<weight>50</weight>
<italic>true</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="styleSheet">
......
This diff is collapsed.