· 5 years ago · Nov 05, 2020, 11:56 AM
1import sys
2import sqlite3
3from PyQt5.QtCore import QSize, Qt
4from pygame import mixer
5from PyQt5 import QtCore
6from PyQt5.QtGui import QPixmap, QIcon
7from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QWidget, QListWidget, QListWidgetItem, QInputDialog, \
8 QDialog, QPushButton
9from PyQt5 import uic
10from Main_styles import *
11
12
13class MenuWidget(QWidget): # виджет меню с плейлистами
14 def __init__(self):
15 super().__init__()
16 uic.loadUi('menuUI.ui', self)
17 self.playlists: QListWidget
18 self.playlists.addItem("Все треки")
19 self.playlists.addItem("Понравившиеся")
20
21 self.playlists.itemAt(0, 0).setSelected(True)
22
23 self.playlists.setStyleSheet(PLAYLISTS_STYLES)
24
25 self.close_menu_btn.setIcon(QIcon(QPixmap("icons/back.png")))
26 self.close_menu_btn.setIconSize(QSize(25, 25))
27
28 self.cur_playlist = "Все треки"
29
30
31class Main(QMainWindow):
32 def __init__(self):
33 super().__init__()
34 uic.loadUi('mainUI.ui', self)
35 self.setWindowIcon(QIcon('icons/app-ico.png'))
36 self.setWindowTitle('Я.Музычка с приколами')
37 mixer.init()
38
39 self.IS_PLAY = False
40 self.was_paused = False
41 self.DB_NAME = "Tracks.db"
42
43 self.like_btn.installEventFilter(self)
44 self.menu_btn.installEventFilter(self)
45 self.add_new_track_btn.installEventFilter(self)
46 self.delete_cur_track_btn.installEventFilter(self)
47
48 self.play_btn.clicked.connect(self.play_track)
49 self.next_btn.clicked.connect(self.next_track)
50 self.prev_btn.clicked.connect(self.prev_track)
51
52 self.volume_slider.valueChanged.connect(self.change_volume)
53 self.volume_slider.setMaximum(100)
54 self.volume_slider.setMinimum(0)
55 self.volume_slider.setValue(10)
56 mixer.music.set_volume(0.1)
57
58 self.like_btn.clicked.connect(self.like_track)
59
60 self.add_new_track_btn.clicked.connect(self.add_new_track) # add new track into DB
61
62 self.delete_cur_track_btn.clicked.connect(self.delete_cur_track) # delete current track from DB
63
64 self.menu = MenuWidget()
65 self.menu.close_menu_btn.clicked.connect(self.close_menu)
66
67 self.stackedWidget.addWidget(self.menu)
68 self.menu_btn.clicked.connect(self.open_menu)
69 self.menu.close_menu_btn.installEventFilter(self)
70
71 self.menu.create_playlist_btn.clicked.connect(self.create_playlist)
72
73 self.cur_playlist = self.menu.cur_playlist
74 self.menu.playlists.currentItemChanged.connect(self.change_playlist)
75
76 self.playlists = {
77 "Все треки": "Tracks",
78 "Понравившиеся": "Liked"}
79
80 self.apply_styles()
81 self.connect_db()
82 self.update_ui()
83
84 def connect_db(self):
85
86 con = sqlite3.connect(self.DB_NAME)
87 cur = con.cursor()
88 # TODO берем айди только из текущего плейлиста и ищем треки с таким айди в общем плейлисте
89 # TODO пустой плейлист с понравившейся музыкой, исправть баг
90
91 self.tracks = cur.execute(f"""
92 SELECT *
93 FROM Tracks
94 WHERE id in (SELECT id from {self.playlists[self.cur_playlist]} )
95 """).fetchall()
96
97 self.liked_tracks = cur.execute("""
98 SELECT id
99 FROM Liked
100 """).fetchall()
101 con.close()
102 self.cur_ind = 0
103
104 def update_ui(self):
105
106 self.cur_id, self.cur_artist_name, self.cur_track_name, \
107 self.cur_song_avatar, self.cur_track = self.tracks[self.cur_ind]
108 self.track_name.setText(self.cur_track_name)
109 self.artist_name.setText(self.cur_artist_name)
110
111 if (self.tracks[self.cur_ind][0],) in self.liked_tracks:
112 self.like_btn.setIcon(QIcon(QPixmap("icons/liked.png")))
113 else:
114 self.like_btn.setIcon(QIcon(QPixmap("icons/unliked.png")))
115
116 # if not self.IS_PLAY:
117 temp = open("temp", "wb")
118 temp.write(self.cur_track)
119 temp = open("temp", "rb")
120 mixer.music.load(temp)
121
122 self.song_avatar.setText(self.cur_song_avatar) # NONE
123 # TODO обложка трека из байтов
124 # self.song_avatar.setPixmap(QPixmap(self.cur_song_avatar))
125
126 def apply_styles(self):
127 # стили кнопок переключения треков
128 self.play_btn.setStyleSheet(DEFAULT_BTN_STYLES)
129
130 self.next_btn.setStyleSheet(DEFAULT_BTN_STYLES)
131
132 self.prev_btn.setStyleSheet(DEFAULT_BTN_STYLES)
133
134 self.like_btn.setStyleSheet(LIKE_BTN_STYLES)
135
136 self.volume_slider.setStyleSheet(DEFAULT_SLIDER_STYLES)
137
138 # стили для view widget
139 self.view_window.setStyleSheet(DEFAULT_WIDGET_STYLES)
140
141 self.song_avatar.setStyleSheet(SONG_AVATAR_STYLES)
142
143 self.artist_name.setStyleSheet(ARTIST_NAME_STYLES)
144 self.track_name.setStyleSheet(TRACK_NAME_STYLES)
145
146 # SETTING UP ICONS
147
148 self.like_btn.setIcon(QIcon(QPixmap("icons/unliked.png"))) # unliked btn icon
149 self.like_btn.setIconSize(QSize(40, 40))
150
151 self.add_new_track_btn.setIcon(QIcon(QPixmap("icons/add.png"))) # add ADD btn icon
152 self.add_new_track_btn.setIconSize(QSize(30, 30))
153
154 self.delete_cur_track_btn.setIcon(QIcon(QPixmap("icons/delete.png"))) # add DELETE btn icon
155 self.delete_cur_track_btn.setIconSize(QSize(30, 30))
156
157 self.menu_btn.setIcon(QIcon(QPixmap("icons/menu.png"))) # add DELETE btn icon
158 self.menu_btn.setIconSize(QSize(40, 40))
159
160 self.stackedWidget.setStyleSheet(STACKED_WIDGET_STYLES)
161 self.page_3.setStyleSheet("""background:transparent""") # прозрачный фон для виджета кнопки меню
162
163 def add_new_track(self):
164
165 fname = QFileDialog.getOpenFileName(self, 'Выбрать трек', '')[0]
166
167 with open(fname, "rb") as f:
168 f = f.read()
169 artist_name = fname.split("/")[-1].split('.mp3')[0].split("-")[0]
170 track_name = fname.split("/")[-1].split('.mp3')[0].split("-")[1]
171
172 con = sqlite3.connect(self.DB_NAME)
173 cur = con.cursor()
174 args = (artist_name, track_name, f)
175
176 cur.execute("""
177 INSERT INTO Tracks(artist_name, track_name, track)
178 VALUES(?,
179 ?,
180 ?)
181 """, args).fetchall()
182 con.commit()
183 con.close()
184 self.connect_db()
185
186 def delete_cur_track(self):
187 con = sqlite3.connect(self.DB_NAME)
188 cur = con.cursor()
189 cur.execute(f"""
190 DELETE FROM {self.playlists[self.cur_playlist]}
191 where id = ?
192 """, (self.cur_id,)).fetchall()
193 con.commit()
194 con.close()
195 self.connect_db()
196 self.update_ui()
197
198 def play_track(self):
199 if self.IS_PLAY:
200 self.play_btn.setText("▶")
201 self.IS_PLAY = False
202 self.was_paused = True
203 mixer.music.pause()
204 else:
205 self.play_btn.setText("| |")
206 self.IS_PLAY = True
207
208 if self.was_paused:
209 mixer.music.unpause()
210 else:
211 mixer.music.play()
212
213 def next_track(self):
214
215 self.cur_ind += 1
216 if self.cur_ind >= len(self.tracks):
217 self.cur_ind = 0
218
219 self.was_paused = False
220 self.update_ui()
221 if self.IS_PLAY:
222 mixer.music.play()
223
224 def prev_track(self):
225 self.cur_ind -= 1
226 if self.cur_ind < 0:
227 self.cur_ind = len(self.tracks) - 1
228
229 self.was_paused = False
230 self.update_ui()
231 if self.IS_PLAY:
232 mixer.music.play()
233
234 def like_track(self):
235 con = sqlite3.connect(self.DB_NAME)
236 cur = con.cursor()
237
238 if (self.cur_id,) in self.liked_tracks:
239
240 cur.execute("""
241 DELETE from Liked
242 where id = ?
243 """, (self.cur_id,))
244 else:
245
246 cur.execute("""
247 INSERT INTO Liked VALUES(?)
248 """, (self.cur_id,))
249 con.commit()
250 self.liked_tracks = cur.execute("""
251 SELECT id
252 FROM Liked
253 """).fetchall()
254 con.close()
255
256 if (self.cur_id,) in self.liked_tracks:
257 self.like_btn.setIcon(QIcon(QPixmap("icons/liked.png")))
258 else:
259 self.like_btn.setIcon(QIcon(QPixmap("icons/unliked.png")))
260
261 def eventFilter(self, obj, event):
262 if obj is self.like_btn:
263 if event.type() == QtCore.QEvent.HoverEnter:
264 if (self.cur_ind + 1,) in self.liked_tracks:
265 self.like_btn.setIcon(QIcon(QPixmap("icons/H-liked.png")))
266 else:
267 self.like_btn.setIcon(QIcon(QPixmap("icons/H-unliked.png")))
268
269 elif event.type() == QtCore.QEvent.HoverLeave:
270 if (self.cur_ind + 1,) in self.liked_tracks:
271 self.like_btn.setIcon(QIcon(QPixmap("icons/liked.png")))
272 else:
273 self.like_btn.setIcon(QIcon(QPixmap("icons/unliked.png")))
274
275 elif obj is self.add_new_track_btn:
276 if event.type() == QtCore.QEvent.HoverEnter:
277 self.add_new_track_btn.setIcon(QIcon(QPixmap("icons/H-add.png")))
278 elif event.type() == QtCore.QEvent.HoverLeave:
279 self.add_new_track_btn.setIcon(QIcon(QPixmap("icons/add.png")))
280
281 elif obj is self.delete_cur_track_btn:
282 if event.type() == QtCore.QEvent.HoverEnter:
283 self.delete_cur_track_btn.setIcon(QIcon(QPixmap("icons/H-delete.png")))
284 elif event.type() == QtCore.QEvent.HoverLeave:
285 self.delete_cur_track_btn.setIcon(QIcon(QPixmap("icons/delete.png")))
286 elif obj is self.menu_btn:
287 if event.type() == QtCore.QEvent.HoverEnter:
288 self.menu_btn.setIcon(QIcon(QPixmap("icons/H-menu.png")))
289 elif event.type() == QtCore.QEvent.HoverLeave:
290 self.menu_btn.setIcon(QIcon(QPixmap("icons/menu.png")))
291 elif obj is self.menu.close_menu_btn:
292 if event.type() == QtCore.QEvent.HoverEnter:
293 self.menu.close_menu_btn.setIcon(QIcon(QPixmap("icons/H-back.png")))
294 elif event.type() == QtCore.QEvent.HoverLeave:
295 self.menu.close_menu_btn.setIcon(QIcon(QPixmap("icons/back.png")))
296
297 return super().eventFilter(obj, event)
298
299 def change_volume(self):
300 mixer.music.set_volume(self.volume_slider.value() / 100)
301
302 def open_menu(self):
303 self.stackedWidget.setCurrentIndex(2)
304
305 def close_menu(self):
306 self.stackedWidget.setCurrentIndex(0)
307
308 def change_playlist(self):
309 con = sqlite3.connect(self.DB_NAME)
310 cur = con.cursor()
311
312 tracks = cur.execute(f"""
313 SELECT *
314 FROM Tracks
315 WHERE id in (SELECT id from {self.playlists[self.menu.playlists.currentItem().text()]} )
316 """).fetchall() # mb id - 1
317 con.close()
318 if tracks:
319 self.cur_playlist = self.menu.playlists.currentItem().text()
320
321 else:
322 pass
323 # TODO self.menu.playlists.currentItem().setFlags(Qt.NoItemFlags) # disable item
324
325 self.play_btn.setText("▶")
326 self.IS_PLAY = False
327
328 self.connect_db()
329 self.update_ui()
330
331 def create_playlist(self):
332 d = QInputDialog(self)
333 QInputDialog.setStyleSheet(self, PLAYLIST_CREATOR_DIALOG_STYLES)
334 QInputDialog.setOkButtonText(d, "Создать")
335 QInputDialog.setCancelButtonText(d, "Отмена") # todo не работает(
336 playlist_name, ok_pressed = d.getText(self, "Создание нового плейлиста",
337 "Введите название плейлиста:")
338
339 if ok_pressed:
340 t = ""
341 cap = 0
342 for i in playlist_name:
343 if i.isalpha():
344 t += i if cap else i.upper()
345 cap = 0
346 else:
347 cap = 1
348 print(t)
349 playlist_name = "".join(t)
350 con = sqlite3.connect(self.DB_NAME)
351 cur = con.cursor()
352 cur.execute(f"""
353 CREATE TABLE IF NOT EXISTS {playlist_name} (
354 id integer NOT NULL,
355 FOREIGN KEY (id) REFERENCES Tracks (id)
356 );
357 """)
358 con.commit()
359 con.close()
360 self.menu.playlists.addItem(playlist_name)
361 self.playlists[playlist_name] = playlist_name
362 # TODO добавление треков в новые плейлисты
363
364
365def except_hook(cls, exception, traceback):
366 sys.__excepthook__(cls, exception, traceback)
367
368
369if __name__ == "__main__":
370 app = QApplication(sys.argv)
371 main = Main()
372 main.show()
373 sys.excepthook = except_hook
374 sys.exit(app.exec())
375
376# "Я.Музычка с приколами"
377# # Created by Sergey Yaksanov at 28.10.2020
378# Copyright © 2020 Yakser. All rights reserved.
379