Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
version 0.1.0
  • Loading branch information
dedekind125 committed Feb 4, 2019
1 parent 0d2d564 commit dba574f
Show file tree
Hide file tree
Showing 26 changed files with 2,710 additions and 0 deletions.
59 changes: 59 additions & 0 deletions ChessClaimController.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""
Chess Claim Tool: ChessClaimController
Copyright (C) 2019 Serntedakis Athanasios <thanasis@brainfriz.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import sys, os.path
from PyQt5.QtWidgets import QApplication
from ChessClaimView import ChessClaimView
from ChessClaimSlots import ChessClaimSlots
from Claims import Claims
from helpers import get_appData_path

class ChessClaimController(QApplication):
""" The Controller of the whole application.
Attributes:
model: Object of the Claims Class.
view: The main view(GUI) of the application.
"""
def __init__(self):
super().__init__(sys.argv)
self.model = Claims()

def set_view(self,view):
self.view = view

def do_start(self):

""" Perform startup operations and shows the dialog.
Called once, on application startup. """

appPath = get_appData_path()

# Set up application directory
if not os.path.exists(appPath): os.makedirs(appPath)

#Connect the signals from the View to the Slots
self.slots = ChessClaimSlots(self.model,self.view)
self.view.set_slots(self.slots)

# Initialize the GUI
self.view.set_GUI()

# Show the GUI
self.view.show()
212 changes: 212 additions & 0 deletions ChessClaimSlots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
"""
Chess Claim Tool: SourceDialogSlots
Copyright (C) 2019 Serntedakis Athanasios <thanasis@brainfriz.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import os.path
from threading import Lock
from PyQt5.QtCore import QThreadPool
from SourceDialogController import SourceDialogController
from SourceDialogView import AddSourceDialog
from workers import DownloadList, MakePgn, Scan, Stop
from helpers import get_appData_path

class ChessClaimSlots:
def __init__(self,model,view):
""" Handles user interaction with the GUI of the Main Window. Each function
is called when a specific action is performed by the user, to fulfill
the request that corresponds to that action model and view wise.
Attributes:
model: Object of the Claims class.
view: The view of the Main Window.
dialogFirstTime(bool): True if the user haven't cliced the "Add Source" Button,
False otherwise.
self.hasDownloadWorker(bool): True if there is a downloadWorker
(at least one source from the web), False otherwise.
"""
self.model = model
self.view = view

self.dialogFirstTime = True
self.hasDownloadWorker = False

def on_sourcesButton_clicked(self):
""" Initialize the Source Dialog MVC model and opens the Source Dialog.
Attributes:
dialog: The Controller of the Source Dialog
trigger: User clicks the "Add Sources" Button on the Main Window.
"""
if (self.dialogFirstTime) :
self.dialog = SourceDialogController()
dialog_view = AddSourceDialog()

""" When the view of the dialog is closed(with the accepted Signal)
update the statusBar accordingly."""
dialog_view.accepted.connect(self.update_statusBar_sources)

self.dialog.set_view(dialog_view)
self.dialog.do_start()

self.dialogFirstTime = False

else:
self.on_stopButton_clicked()
self.dialog.do_resume()

def on_scanButton_clicked(self):
""" Creates the necessary thread(workers) in order to scan the pgn(s)
for the draw claims.
trigger: User clicks the "Start Scan" Button on the Main Window.
"""

""" If the scan thread is alive it means the scan button is already
clicked before. So if the user click it again nothing should happen."""

try:
if (self.scanWorker.isRunning): return
except:
pass

""" Check if there any valid sources before the start of the scan.
If there aren't any valid sources raire the warning dialog and return."""

if (self.dialogFirstTime):
self.view.load_warning()
return
filepathList = self.dialog.get_filepathList()
if not filepathList:
self.view.load_warning()
return

self.view.clear_table() # Clear the table of the output in the case of a previous scan.
self.view.change_scanButton_text("active")

""" If at least one of the sources is from the web we create a download
therad(downloadWorker) to continuously download the web source(s). """

self.hasDownloadWorker = False
downloadList = self.dialog.get_downloadList()
if downloadList:
self.downloadWorker = DownloadList(downloadList,True)
self.downloadWorker.statusSignal.connect(self.update_statusBar_download)
self.hasDownloadWorker = True
self.downloadWorker.start()

""" We create a thread(makePgnWorker) to continuously making the
combined pgn from all the pgn's that were set as sources
Also, a pyqt Signals is connected to this thread in order to update
the downloadLabel in the statusBar.
fileLock: Is a Lock Object. Both makePgnWorker thread and scanWorker
thread (see below) access the combined games.pgn for writing and reading.
Thus to avoid any conflict, with the use of fileLock, we make sure that
only one thread per time uses the game.pgn. """

fileLock = Lock()
self.makePgnWorker = MakePgn(filepathList,True,fileLock)
self.makePgnWorker.start()

appPath = get_appData_path()
filename = os.path.join(appPath,"games.pgn")

""" Create a thread(scanWorker) to scan the combined pgn using the Model.
Also, two pyqt Signals are connected to this thread in order to update
the claimsTable and the statusBar in the GUI. """

livePgnOption = self.view.livePgnOption
self.scanWorker = Scan(self.model,filename,fileLock,livePgnOption)
self.scanWorker.addEntrySignal.connect(self.update_claimsTable)
self.scanWorker.statusSignal.connect(self.update_statusBar_scan)
self.scanWorker.start()

def on_stopButton_clicked(self):
""" Creates a thread in order to stop all the other running Threads(
downloadWorker, makePgnWorker,scanWorker)
trigger: User clicks the "Stop" Button on the Main Window.
"""

# If the scan thread isn't active there is nothing to stop.
try:
if not(self.scanWorker.isRunning):
return
except:
return

""" We create a thead(stopWorker) in order to stop all the other running threads.
Also two pyqt Signals are connected to this thread in order to update the GUI
during the stop process."""

if(self.hasDownloadWorker):
self.stopWorker = Stop(self.model,self.makePgnWorker,self.scanWorker,self.downloadWorker)
else:
self.stopWorker = Stop(self.model,self.makePgnWorker,self.scanWorker)

self.stopWorker.enableSignal.connect(self.on_stop_enable_status)
self.stopWorker.disableSignal.connect(self.on_stop_disable_status)
self.stopWorker.start()

def on_about_clicked(self):
""" Calls the view in order to display the About Dialog.
trigger: User clicked the About section in the menu.
"""
self.view.load_about_dialog()

def on_stop_disable_status(self):
""" Disables the "Scan" & "Stop" Buttons and the statusBar.
Also changes the status of the scanButton.
trigger: By the disableSignal(pyqtSignal)
"""
self.view.change_scanButton_text("wait")
self.view.disable_buttons()
self.view.disable_statusBar()

def on_stop_enable_status(self):
""" Enables the "Scan" & "Stop" Buttons and the statusBar.
Also changes the status of the scanButton, download and scan info at the
statusBar.
trigger: By the enableSignal(pyqtSignal)
"""
self.view.enable_buttons()
self.view.enable_statusBar()

self.view.change_scanButton_text("stop")
self.update_statusBar_download("stop")
self.update_statusBar_scan("stop")

def update_statusBar_sources(self):
validSources = self.dialog.get_validSources()
if (len(validSources) == 0):
self.view.set_sources_status("error")
else:
self.view.set_sources_status("ok",validSources)

""" Functions to update the GUI. Triggered by pyqt Signals."""

def update_claimsTable(self,entry):
self.view.add_to_table(entry[0],entry[1],entry[2],entry[3])

def update_statusBar_download(self,status):
self.view.set_download_status(status)

def update_statusBar_scan(self,status):
self.view.set_scan_status(status)
Loading

0 comments on commit dba574f

Please sign in to comment.