Skip to content

Commit

Permalink
Add Makefile and possibility to delete a deck
Browse files Browse the repository at this point in the history
The Makefile is compatible with Linux, macOS and Windows
To delete a deck there is now an option in the file menu
Also added a way to quit from the file menu
  • Loading branch information
MarcoBenelli committed Dec 9, 2021
1 parent bc0a962 commit 8398333
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 61 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
**/__pycache__
src/img/fugue-icons-3.5.6
build
dist
*.spec
.vscode
27 changes: 27 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ifeq ($(OS),Windows_NT)
pathsep = ;
options = --onefile --windowed
else
pathsep = :
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
options = --windowed --name 'Study and Repeat'
else
options = --onefile
endif
endif

dist/study_and_repeat : src/**/*.py
pyinstaller $(options) --icon src/img/favicon.ico \
--add-data 'src/img/fugue-icons-3.5.6/icons-shadowless/*.png$(pathsep)src/img/fugue-icons-3.5.6/icons-shadowless' \
--add-data 'src/img/favicon.ico$(pathsep)src/img' \
src/study_and_repeat.py

.PHONY : clean
clean :
ifeq ($(OS),Windows_NT)
-rmdir /s /q build dist
-erase .\*.spec
else
rm --recursive --force build dist ./*.spec
endif
8 changes: 6 additions & 2 deletions src/model/deck.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,14 @@ def calculate_delay(self, correctness: bool) -> None:
self._cards_strengths[c.identifier] = 1
self._queues[0].append(c)

def dump(self):
with open(f'{config.DECKS_DIR}{self.name}/{config.DECK_FILE}', 'wb') as f:
def dump(self) -> None:
with open(f'{config.DECKS_DIR}{self.name}/{config.DECK_FILE}',
'wb') as f:
pickle.dump(self, f)

def delete(self) -> None:
shutil.rmtree(f'{config.DECKS_DIR}{self.name}')


def load_deck(filepath: str) -> Deck:
with open(filepath, 'rb') as f:
Expand Down
5 changes: 1 addition & 4 deletions src/view/editor_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ class EditorWidget(secondary_widget.SecondaryWidget):
question_prefix = '- '
proportion = 6

def __init__(self, d: deck.Deck, *args, **kwargs) -> None:
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

self.window().setWindowTitle(f'Study and Repeat - {d.name}')

self._deck = d
h_layout = QtWidgets.QHBoxLayout()

left_widget = QtWidgets.QWidget()
Expand Down
75 changes: 61 additions & 14 deletions src/view/home_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,41 @@

class HomeWidget(QtWidgets.QWidget):

def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

horizontal_layout = QtWidgets.QHBoxLayout(self)
outer_layout = QtWidgets.QVBoxLayout(self)
label = QtWidgets.QLabel('Your decks')
label.setAlignment(QtCore.Qt.AlignCenter)
font = label.font()
font.setBold(True)
font.setPointSize(24)
label.setFont(font)
outer_layout.addWidget(label)

self._scroll_area = QtWidgets.QScrollArea(self)
self._scroll_area.setWidgetResizable(True)
self._scroll_area_widget_contents = QtWidgets.QWidget()
self._vertical_layout = QtWidgets.QVBoxLayout(
self._scroll_area_widget_contents)
self._vertical_layout.setAlignment(QtCore.Qt.AlignCenter)
self.populate_list()
horizontal_layout.addWidget(self._scroll_area)
outer_layout.addWidget(self._scroll_area)

def populate_list(self) -> None:
self._scroll_area_widget_contents = QtWidgets.QWidget()
self._inner_layout = QtWidgets.QVBoxLayout(
self._scroll_area_widget_contents)
self._inner_layout.setAlignment(QtCore.Qt.AlignCenter)
for deck_name in sorted(os.listdir(config.DECKS_DIR)):
if deck_name.startswith('.'):
continue
widget = QtWidgets.QWidget(self._scroll_area_widget_contents)
horizontal_layout = QtWidgets.QHBoxLayout(widget)
frame = QtWidgets.QFrame(self._scroll_area_widget_contents)
frame.setFrameStyle(QtWidgets.QFrame.Box)
horizontal_layout = QtWidgets.QHBoxLayout(frame)
horizontal_layout.setAlignment(QtCore.Qt.AlignCenter)
line_edit = QtWidgets.QLineEdit(deck_name, widget)
line_edit.setReadOnly(True)
line_edit.setMaximumWidth(400)
horizontal_layout.addWidget(line_edit)
label = QtWidgets.QLabel(deck_name, frame)
label.setFixedWidth(400)
font = label.font()
font.setPointSize(12)
label.setFont(font)
horizontal_layout.addWidget(label)
study_btn = QtWidgets.QPushButton(
QtGui.QIcon(f'{config.ICONS_DIR}book-open.png'), '')
study_btn.setFixedWidth(32)
Expand All @@ -43,7 +54,7 @@ def populate_list(self) -> None:
edit_btn.setFixedWidth(32)
edit_btn.released.connect(lambda d=deck_name: self.edit_deck(d))
horizontal_layout.addWidget(edit_btn)
self._vertical_layout.addWidget(widget)
self._inner_layout.addWidget(frame)
self._scroll_area.setWidget(self._scroll_area_widget_contents)

def edit_deck(self, name: str) -> None:
Expand All @@ -56,5 +67,41 @@ def study_deck(self, name: str) -> None:
f'{config.DECKS_DIR}{name}/{config.DECK_FILE}'),
parent=self.window())

def delete_deck(self) -> None:
dlg = SelectDeckDialog('delete', self)
if dlg.exec():
dlg.deck.delete()
self.populate_list()

def exit(self) -> None:
pass


class SelectDeckDialog(QtWidgets.QDialog):

def __init__(self, action: str, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.setWindowTitle(f'Select deck to {action}')
self.resize(400, 150)
self.setMinimumSize(self.size())
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)

self._combo_box = QtWidgets.QComboBox()
for deck_name in sorted(os.listdir(config.DECKS_DIR)):
if deck_name.startswith('.'):
continue
self._combo_box.addItem(deck_name)
layout.addWidget(self._combo_box)

q_btn = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
button_box = QtWidgets.QDialogButtonBox(q_btn, parent=self)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
layout.addWidget(button_box)

def accept(self, *args, **kwargs) -> None:
super().accept()
self.deck = deck.load_deck(
f'{config.DECKS_DIR}{self._combo_box.currentText()}/'
+ config.DECK_FILE)
65 changes: 34 additions & 31 deletions src/view/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,52 +20,55 @@ def __init__(self, *args, **kwargs) -> None:
menubar = QtWidgets.QMenuBar(self)

menu_file = QtWidgets.QMenu(menubar)
menu_export_deck = QtWidgets.QMenu(menu_file)
# menu_export_deck = QtWidgets.QMenu(menu_file)
self.setMenuBar(menubar)
action_new_deck = QtWidgets.QAction(self)
self.action_new_deck = QtWidgets.QAction(self)
action_quit = QtWidgets.QAction(self)
action_import_deck = QtWidgets.QAction(self)
action_local_export = QtWidgets.QAction(self)
action_remote_export = QtWidgets.QAction(self)
# action_import_deck = QtWidgets.QAction(self)
# action_local_export = QtWidgets.QAction(self)
# action_remote_export = QtWidgets.QAction(self)
action_delete_deck = QtWidgets.QAction(self)
menu_export_deck.addAction(action_local_export)
menu_export_deck.addAction(action_remote_export)
menu_file.addAction(action_new_deck)
menu_file.addAction(action_import_deck)
menu_file.addAction(menu_export_deck.menuAction())
# menu_export_deck.addAction(action_local_export)
# menu_export_deck.addAction(action_remote_export)
menu_file.addAction(self.action_new_deck)
# menu_file.addAction(action_import_deck)
# menu_file.addAction(menu_export_deck.menuAction())
menu_file.addAction(action_delete_deck)
menu_file.addAction(action_quit)
menubar.addAction(menu_file.menuAction())
menu_help = QtWidgets.QMenu(menubar)
action_about = QtWidgets.QAction(self)
menu_help.addAction(action_about)
menubar.addAction(menu_help.menuAction())
# menu_help = QtWidgets.QMenu(menubar)
# action_about = QtWidgets.QAction(self)
# menu_help.addAction(action_about)
# menubar.addAction(menu_help.menuAction())

menu_file.setTitle(QtCore.QCoreApplication.translate(
'Study and Repeat', 'File'))
menu_export_deck.setTitle(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Export deck'))
menu_help.setTitle(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Help'))
action_new_deck.setText(QtCore.QCoreApplication.translate(
# menu_export_deck.setTitle(QtCore.QCoreApplication.translate(
# 'Study and Repeat', 'Export deck'))
# menu_help.setTitle(QtCore.QCoreApplication.translate(
# 'Study and Repeat', 'Help'))
self.action_new_deck.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'New deck'))
action_about.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'About'))
# action_about.setText(QtCore.QCoreApplication.translate(
# 'Study and Repeat', 'About'))
action_quit.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Quit'))
action_import_deck.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Import deck'))
action_local_export.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Local export'))
action_remote_export.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Remote export'))
# action_import_deck.setText(QtCore.QCoreApplication.translate(
# 'Study and Repeat', 'Import deck'))
# action_local_export.setText(QtCore.QCoreApplication.translate(
# 'Study and Repeat', 'Local export'))
# action_remote_export.setText(QtCore.QCoreApplication.translate(
# 'Study and Repeat', 'Remote export'))
action_delete_deck.setText(QtCore.QCoreApplication.translate(
'Study and Repeat', 'Delete deck'))

action_new_deck.triggered.connect(self.create_deck)
self.action_new_deck.triggered.connect(self.create_deck)
action_quit.triggered.connect(self.close)
action_delete_deck.triggered.connect(
lambda: self.centralWidget().delete_deck())

def create_deck(self) -> None:
dlg = CustomDialog(self)
dlg = NewDeckDialog(self)
if dlg.exec():
editor_widget.EditorWidget(dlg.deck, parent=self)

Expand All @@ -74,7 +77,7 @@ def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
return super().closeEvent(a0)


class CustomDialog(QtWidgets.QDialog):
class NewDeckDialog(QtWidgets.QDialog):

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
Expand All @@ -85,7 +88,7 @@ def __init__(self, *args, **kwargs) -> None:
self.setLayout(layout)

self._error_label = QtWidgets.QLabel('The only permitted characters are '
+ 'a..z, A..Z, 0..9 and _')
+ 'a-z, A-Z, 0-9 and _')
self._error_label.setStyleSheet("color: #ff0000")
layout.addWidget(self._error_label)
self._error_label.hide()
Expand Down
21 changes: 15 additions & 6 deletions src/view/secondary_widget.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@


from PyQt5 import QtWidgets
from PyQt5 import QtWidgets, QtGui

from view import home_widget
from model import deck
import config


class SecondaryWidget(QtWidgets.QWidget):

def __init__(self, *args, **kwargs) -> None:
def __init__(self, d: deck.Deck, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._deck = d
self.window().setWindowTitle(f'Study and Repeat - {self._deck.name}')

self._layout = QtWidgets.QVBoxLayout()
self.setLayout(self._layout)
back_btn = QtWidgets.QPushButton(QtGui.QIcon(
f'{config.ICONS_DIR}home.png'), '')
f'{config.ICONS_DIR}home.png'), '')
back_btn.setFixedWidth(32)
self._layout.addWidget(back_btn)
back_btn.released.connect(self.back_home)
self._central_widget = QtWidgets.QWidget()
self._layout.addWidget(self._central_widget)
self.window().setCentralWidget(self)
self.window().setCentralWidget(self)
self.window().action_new_deck.setVisible(False)

def back_home(self) -> None:
self.window().action_new_deck.setVisible(True)
self.window().setCentralWidget(home_widget.HomeWidget())
self.window().setWindowTitle('Study and Repeat')
self.exit()

def delete_deck(self) -> None:
self._deck.delete()
self.window().action_new_deck.setVisible(True)
self.window().setCentralWidget(home_widget.HomeWidget())
self.window().setWindowTitle('Study and Repeat')
self.exit()
5 changes: 1 addition & 4 deletions src/view/study_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@

class StudyWidget(secondary_widget.SecondaryWidget):

def __init__(self, d: deck.Deck, *args, **kwargs) -> None:
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

self.window().setWindowTitle(f'Study and Repeat - {d.name}')

self._deck = d
v_layout = QtWidgets.QVBoxLayout()
self._question_text = QtWidgets.QLineEdit()
self._question_text.setReadOnly(True)
Expand Down

0 comments on commit 8398333

Please sign in to comment.