Skip to content

Commit fdef557

Browse files
committed
feat: Сделал разделение игр на категории
1 parent 80b673d commit fdef557

File tree

7 files changed

+315
-29
lines changed

7 files changed

+315
-29
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.idea
22
ui/add_game_dialog.ui
33
ui/mainWindow.ui
4+
ui/createCategory.ui
45
venv
56
main.spec
67
build

db.py

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,28 @@ def get_connection(self):
2121
def create_tables(self):
2222
conn = self.get_connection()
2323
cursor = conn.cursor()
24+
25+
cursor.execute(
26+
"""CREATE TABLE IF NOT EXISTS Categories (
27+
id INTEGER PRIMARY KEY AUTOINCREMENT,
28+
name TEXT NOT NULL UNIQUE
29+
)"""
30+
)
31+
2432
cursor.execute(
2533
"""CREATE TABLE IF NOT EXISTS Games (
2634
id INTEGER PRIMARY KEY AUTOINCREMENT,
2735
name TEXT NOT NULL UNIQUE,
28-
path TEXT NOT NULL UNIQUE
36+
path TEXT NOT NULL UNIQUE,
37+
category_id INTEGER NOT NULL,
38+
FOREIGN KEY (category_id) REFERENCES Categories(id)
2939
)"""
3040
)
41+
42+
cursor.execute(
43+
"INSERT OR IGNORE INTO Categories (name) VALUES (?)", ("Все",)
44+
)
45+
3146
conn.commit()
3247
conn.close()
3348

@@ -47,13 +62,13 @@ def check_path_is_unique(self, game_path):
4762
count = cursor.fetchone()[0]
4863
return count == 0
4964

50-
def insert_game(self, name, game_path):
65+
def insert_game(self, name, game_path, category_id):
5166
conn = self.get_connection()
5267
cursor = conn.cursor()
5368
try:
5469
cursor.execute(
55-
"INSERT INTO Games (name, path) VALUES (?, ?)",
56-
(name, game_path),
70+
"INSERT INTO Games (name, path, category_id) VALUES (?, ?, ?)",
71+
(name, game_path, category_id),
5772
)
5873
conn.commit()
5974
print(f"Игра '{name}' добавлена в базу данных")
@@ -64,6 +79,55 @@ def insert_game(self, name, game_path):
6479
finally:
6580
conn.close()
6681

82+
def insert_category(self, name):
83+
conn = self.get_connection()
84+
cursor = conn.cursor()
85+
try:
86+
cursor.execute(
87+
"INSERT INTO Categories (name) VALUES (?)",
88+
(name,),
89+
)
90+
conn.commit()
91+
except sqlite3.IntegrityError:
92+
print(f"Ошибка: категория с именем '{name}' уже существует")
93+
except Exception as e:
94+
print(f"Ошибка при добавлении категории: {e}")
95+
finally:
96+
conn.close()
97+
98+
def get_categories(self):
99+
conn = self.get_connection()
100+
cursor = conn.cursor()
101+
cursor.execute("""SELECT name FROM Categories""")
102+
categories = cursor.fetchall()
103+
conn.close()
104+
return categories
105+
106+
def get_category_name_by_id(self, _id):
107+
conn = self.get_connection()
108+
cursor = conn.cursor()
109+
cursor.execute("SELECT name FROM Categories WHERE id = ?", (_id,))
110+
name = cursor.fetchone()[0]
111+
conn.close()
112+
return name
113+
114+
def get_category_id_by_name(self, name):
115+
conn = self.get_connection()
116+
cursor = conn.cursor()
117+
cursor.execute("SELECT id FROM Categories WHERE name = ?", (name,))
118+
_id = cursor.fetchone()[0]
119+
conn.close()
120+
return _id
121+
122+
def category_name_check_unique(self, name):
123+
conn = self.get_connection()
124+
cursor = conn.cursor()
125+
cursor.execute(
126+
"SELECT COUNT(*) FROM Categories WHERE name = ?", (name,)
127+
)
128+
count = cursor.fetchone()[0]
129+
return count == 0
130+
67131
def delete_game(self, name):
68132
conn = self.get_connection()
69133
cursor = conn.cursor()

dialogs.py

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
from PyQt6.QtWidgets import QDialog, QFileDialog, QMessageBox
22

33
from db import database
4-
from ui.add_game_dialog_ui import Ui_Dialog
4+
from ui.add_game_dialog_ui import Ui_Dialog as AddGameUI
5+
from ui.createCategory_ui import Ui_Dialog as AddCategoryUI
56

67

7-
class AddGameDialog(QDialog, Ui_Dialog):
8+
class AddGameDialog(QDialog, AddGameUI):
89
def __init__(self):
910
super().__init__()
10-
self.setFixedSize(450, 120)
11+
self.setFixedSize(450, 180)
1112

1213
self.setupUi(self)
1314
self.path_button.clicked.connect(self.choose_file)
1415

1516
self.buttonBox.accepted.disconnect()
1617
self.buttonBox.rejected.disconnect()
1718

19+
self.get_categories()
20+
1821
self.buttonBox.accepted.connect(self.accept_dialog)
1922
self.buttonBox.rejected.connect(self.reject)
2023

24+
def get_categories(self):
25+
combobox = self.comboBox
26+
categories = database.get_categories()
27+
for category in categories:
28+
combobox.addItem(category[0])
29+
2130
def choose_file(self):
2231
file_path = QFileDialog.getOpenFileName(
2332
self, "Выбрать файл", "", "EXE - Файл (*.exe)"
@@ -28,6 +37,9 @@ def choose_file(self):
2837
def accept_dialog(self):
2938
game_name = self.game_name.text().strip()
3039
game_path = self.file_path.text().strip()
40+
category_id = database.get_category_id_by_name(
41+
self.comboBox.currentText()
42+
)
3143

3244
if not game_name:
3345
QMessageBox.warning(self, "Ошибка", "Введите название игры")
@@ -37,6 +49,9 @@ def accept_dialog(self):
3749
QMessageBox.warning(self, "Ошибка", "Выберите файл игры")
3850
return
3951

52+
if not category_id:
53+
category_id = 1
54+
4055
if not database.check_name_is_unique(game_name):
4156
QMessageBox.warning(
4257
self, "Ошибка", "Игра с таким именем уже существует"
@@ -50,11 +65,51 @@ def accept_dialog(self):
5065
return
5166

5267
try:
53-
database.insert_game(game_name, game_path)
68+
database.insert_game(game_name, game_path, category_id)
5469
self.accept()
5570
QMessageBox.information(self, "Успех", "Игра добавлена!")
5671

5772
except Exception as e:
5873
QMessageBox.critical(
5974
self, "Ошибка", f"Не удалось добавить игру: {str(e)}"
6075
)
76+
77+
78+
class AddCategoryDialog(QDialog, AddCategoryUI):
79+
def __init__(self):
80+
super().__init__()
81+
self.setFixedSize(300, 110)
82+
83+
self.setupUi(self)
84+
85+
self.buttonBox.accepted.disconnect()
86+
self.buttonBox.rejected.disconnect()
87+
88+
self.buttonBox.accepted.connect(self.accept_dialog)
89+
self.buttonBox.rejected.connect(self.reject)
90+
91+
def accept_dialog(self):
92+
category_name = self.lineEdit.text().strip()
93+
if not category_name:
94+
QMessageBox.warning(
95+
self, "Ошибка", "Категория не может быть пустой"
96+
)
97+
return
98+
99+
if not database.category_name_check_unique(category_name):
100+
QMessageBox.warning(
101+
self, "Ошибка", "Категория с таким именем уже есть"
102+
)
103+
return
104+
105+
try:
106+
database.insert_category(category_name)
107+
self.accept()
108+
QMessageBox.information(
109+
self, "Успех", "Категория успешно добавлена"
110+
)
111+
112+
except Exception as e:
113+
QMessageBox.critical(
114+
self, "Ошибка", f"Не удалось добавить категорию: {str(e)}"
115+
)

main.py

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33

4+
from PyQt6.QtGui import QAction
45
from PyQt6.QtWidgets import QApplication, QMainWindow, QMessageBox
56

67
import dialogs
@@ -19,26 +20,31 @@ def resource_path(relative_path: str) -> str:
1920
class QtLauncher(QMainWindow, Ui_MainWindow):
2021
def __init__(self):
2122
super().__init__()
22-
self.setFixedSize(750, 420)
23+
self.setFixedSize(750, 400)
2324
self.setupUi(self)
2425

2526
self.update_game_list()
2627
txt_editor.create_txt()
2728
self.update_last_game_list()
2829
json_editor.create_json()
2930

31+
self.update_menu_bar()
32+
3033
theme_file = resource_path(f"style/{json_editor.get_theme()}.qss")
3134
with open(theme_file, "r", encoding="utf-8") as qss:
3235
self.setStyleSheet(qss.read())
3336

3437
# Сигналы
35-
self.add_game.clicked.connect(self.open_dialog)
38+
self.add_game.clicked.connect(lambda: self.open_dialog("add_game"))
3639
self.list_games.itemDoubleClicked.connect(self.open_game)
3740
self.delete_game.clicked.connect(self.delete_game_from_list)
3841
self.sort_name_a_z.clicked.connect(lambda: self.sort_games(""))
3942
self.sort_name_z_a.clicked.connect(lambda: self.sort_games("r"))
4043
self.action_2.triggered.connect(lambda: self.set_theme("light"))
4144
self.action_3.triggered.connect(lambda: self.set_theme("dark"))
45+
self.create_category.triggered.connect(
46+
lambda: self.open_dialog("add_category")
47+
)
4248

4349
def set_theme(self, theme):
4450
theme_file = resource_path(f"style/{theme}.qss")
@@ -83,10 +89,66 @@ def open_game(self, item):
8389
QMessageBox.warning(self, "Ошибка!", str(e))
8490
self.update_last_game_list()
8591

86-
def open_dialog(self):
87-
dialog = dialogs.AddGameDialog()
88-
dialog.exec()
89-
self.update_game_list()
92+
def open_dialog(self, dialog):
93+
if dialog == "add_game":
94+
_dialog = dialogs.AddGameDialog()
95+
_dialog.exec()
96+
self.update_game_list()
97+
if dialog == "add_category":
98+
_dialog = dialogs.AddCategoryDialog()
99+
_dialog.exec()
100+
self.update_menu_bar()
101+
102+
def update_menu_bar(self):
103+
menu = self.menu_3
104+
actions = menu.actions()
105+
106+
separator_index = -1
107+
for i, action in enumerate(actions):
108+
if action.isSeparator():
109+
separator_index = i
110+
break
111+
112+
if separator_index != -1:
113+
for action in actions[separator_index + 1 :]:
114+
menu.removeAction(action)
115+
116+
categories = database.get_categories()
117+
for category in categories:
118+
category_name = category[0]
119+
action = QAction(category_name, self)
120+
action.triggered.connect(
121+
lambda checked, cat_name=category_name: self.on_category_selected(
122+
cat_name
123+
)
124+
)
125+
menu.addAction(action)
126+
127+
def on_category_selected(self, category_name):
128+
self.filter_games_by_category(category_name)
129+
130+
def filter_games_by_category(self, category_name):
131+
if category_name != "Все":
132+
category_id = database.get_category_id_by_name(category_name)
133+
134+
if category_id:
135+
conn = database.get_connection()
136+
cursor = conn.cursor()
137+
cursor.execute(
138+
"SELECT name FROM Games WHERE category_id = ?",
139+
(category_id,),
140+
)
141+
games = cursor.fetchall()
142+
conn.close()
143+
144+
self.list_games.clear()
145+
for game in games:
146+
self.list_games.addItem(game[0])
147+
else:
148+
self.update_game_list()
149+
else:
150+
self.list_games.clear()
151+
self.update_game_list()
90152

91153

92154
if __name__ == "__main__":

ui/add_game_dialog_ui.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
class Ui_Dialog(object):
1313
def setupUi(self, Dialog):
1414
Dialog.setObjectName("Dialog")
15-
Dialog.resize(450, 120)
15+
Dialog.resize(450, 171)
1616
Dialog.setSizeGripEnabled(False)
1717
Dialog.setModal(False)
1818
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
19-
self.buttonBox.setGeometry(QtCore.QRect(220, 80, 220, 40))
19+
self.buttonBox.setGeometry(QtCore.QRect(220, 130, 220, 40))
2020
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
2121
self.buttonBox.setStandardButtons(
2222
QtWidgets.QDialogButtonBox.StandardButton.Cancel
@@ -57,6 +57,26 @@ def setupUi(self, Dialog):
5757
self.file_path.setText("")
5858
self.file_path.setReadOnly(True)
5959
self.file_path.setObjectName("file_path")
60+
self.label_2 = QtWidgets.QLabel(parent=Dialog)
61+
self.label_2.setGeometry(QtCore.QRect(10, 100, 80, 20))
62+
font = QtGui.QFont()
63+
font.setFamily("Arial")
64+
font.setPointSize(10)
65+
font.setBold(False)
66+
font.setUnderline(False)
67+
font.setWeight(50)
68+
self.label_2.setFont(font)
69+
self.label_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
70+
self.label_2.setObjectName("label_2")
71+
self.comboBox = QtWidgets.QComboBox(parent=Dialog)
72+
self.comboBox.setGeometry(QtCore.QRect(100, 100, 111, 22))
73+
font = QtGui.QFont()
74+
font.setFamily("Arial")
75+
font.setPointSize(10)
76+
self.comboBox.setFont(font)
77+
self.comboBox.setEditable(False)
78+
self.comboBox.setFrame(True)
79+
self.comboBox.setObjectName("comboBox")
6080

6181
self.retranslateUi(Dialog)
6282
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
@@ -68,3 +88,4 @@ def retranslateUi(self, Dialog):
6888
Dialog.setWindowTitle(_translate("Dialog", "Добавить игру"))
6989
self.label.setText(_translate("Dialog", "Имя игры"))
7090
self.path_button.setText(_translate("Dialog", "Путь к файлу"))
91+
self.label_2.setText(_translate("Dialog", "Категория"))

0 commit comments

Comments
 (0)