1 | import os |
||
2 | |||
3 | from appdirs import AppDirs |
||
4 | |||
5 | from PyQt5.QtCore import Qt |
||
6 | from PyQt5.QtGui import QIcon |
||
7 | from PyQt5.QtWidgets import (QComboBox, QCheckBox, QDialog, QDialogButtonBox, QFileDialog, |
||
8 | QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, |
||
9 | QListWidgetItem, QPushButton, QRadioButton, QStackedWidget, |
||
10 | QVBoxLayout, QWidget) |
||
11 | |||
12 | import toml |
||
13 | |||
14 | from mosaic import utilities |
||
15 | |||
16 | |||
17 | class MediaLibrary(QWidget): |
||
18 | """Contains all of the user configurable options related to the media library.""" |
||
19 | |||
20 | View Code Duplication | def __init__(self, parent=None): |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
21 | """Initialize a page of options to be shown in the preferences dialog.""" |
||
22 | super(MediaLibrary, self).__init__(parent) |
||
23 | |||
24 | self.user_config_file = os.path.join(AppDirs('mosaic', 'Mandeep').user_config_dir, |
||
25 | 'settings.toml') |
||
26 | |||
27 | with open(self.user_config_file) as conffile: |
||
28 | config = toml.load(conffile) |
||
29 | |||
30 | media_library_config = QGroupBox("Media Library Configuration") |
||
31 | |||
32 | self.media_library_label = QLabel('Media Library', self) |
||
33 | self.media_library_line = QLineEdit() |
||
34 | self.media_library_line.setReadOnly(True) |
||
35 | self.media_library_button = QPushButton('Select Path') |
||
36 | |||
37 | self.media_library_button.clicked.connect(lambda: self.select_media_library(config)) |
||
38 | |||
39 | media_library_layout = QVBoxLayout() |
||
40 | |||
41 | media_library_config_layout = QHBoxLayout() |
||
42 | media_library_config_layout.addWidget(self.media_library_label) |
||
43 | media_library_config_layout.addWidget(self.media_library_line) |
||
44 | media_library_config_layout.addWidget(self.media_library_button) |
||
45 | |||
46 | media_library_layout.addLayout(media_library_config_layout) |
||
47 | |||
48 | media_library_config.setLayout(media_library_layout) |
||
49 | |||
50 | main_layout = QVBoxLayout() |
||
51 | main_layout.addWidget(media_library_config) |
||
52 | main_layout.addStretch(1) |
||
53 | self.setLayout(main_layout) |
||
54 | |||
55 | self.media_library_settings(config) |
||
56 | |||
57 | def select_media_library(self, config): |
||
58 | """Open a file dialog to allow the user to select the media library path. |
||
59 | |||
60 | The selected path is written to settings.toml. |
||
61 | """ |
||
62 | library = QFileDialog.getExistingDirectory(self, 'Select Media Library Directory') |
||
63 | if library: |
||
64 | self.media_library_line.setText(library) |
||
65 | |||
66 | config['media_library']['media_library_path'] = library |
||
67 | |||
68 | with open(self.user_config_file, 'w') as conffile: |
||
69 | toml.dump(config, conffile) |
||
70 | |||
71 | def media_library_settings(self, config): |
||
72 | """Set the media library text box to the path of the media library. |
||
73 | |||
74 | If the user has already defined a media library path that was |
||
75 | previously written to settings.toml, the path is shown when the |
||
76 | preferences dialog is opened. |
||
77 | """ |
||
78 | library = config['media_library']['media_library_path'] |
||
79 | if os.path.isdir(library): |
||
80 | self.media_library_line.setText(library) |
||
81 | |||
82 | |||
83 | class Playback(QWidget): |
||
84 | """Contains all of the user configurable options related to media playback.""" |
||
85 | |||
86 | View Code Duplication | def __init__(self, parent=None): |
|
0 ignored issues
–
show
|
|||
87 | """Initiate the abstract widget that is displayed in the preferences dialog.""" |
||
88 | super(Playback, self).__init__(parent) |
||
89 | self.user_config_file = os.path.join(AppDirs('mosaic', 'Mandeep').user_config_dir, |
||
90 | 'settings.toml') |
||
91 | |||
92 | with open(self.user_config_file) as conffile: |
||
93 | config = toml.load(conffile) |
||
94 | |||
95 | playback_config = QGroupBox('Playback Configuration') |
||
96 | playback_config_layout = QVBoxLayout() |
||
97 | playback_config_layout.setAlignment(Qt.AlignTop) |
||
98 | |||
99 | self.cover_art_playback = QCheckBox('Cover Art Playback') |
||
100 | self.playlist_save_checkbox = QCheckBox('Save Playlist on Close') |
||
101 | |||
102 | playback_config_layout.addWidget(self.cover_art_playback) |
||
103 | playback_config_layout.addWidget(self.playlist_save_checkbox) |
||
104 | |||
105 | playback_config.setLayout(playback_config_layout) |
||
106 | |||
107 | main_layout = QVBoxLayout() |
||
108 | main_layout.addWidget(playback_config) |
||
109 | |||
110 | self.setLayout(main_layout) |
||
111 | |||
112 | self.check_playback_setting(config) |
||
113 | self.check_playlist_save(config) |
||
114 | self.cover_art_playback.clicked.connect(lambda: self.cover_art_playback_setting(config)) |
||
115 | self.playlist_save_checkbox.clicked.connect(lambda: self.playlist_save_setting(config)) |
||
116 | |||
117 | def cover_art_playback_setting(self, config): |
||
118 | """Change the cover art playback behavior of the music player. |
||
119 | |||
120 | The default setting allows for the current media |
||
121 | to be paused and played with mouse button clicks on the cover art. |
||
122 | """ |
||
123 | if self.cover_art_playback.isChecked(): |
||
124 | config.setdefault('playback', {})['cover_art'] = True |
||
125 | |||
126 | elif not self.cover_art_playback.isChecked(): |
||
127 | config.setdefault('playback', {})['cover_art'] = False |
||
128 | |||
129 | with open(self.user_config_file, 'w') as conffile: |
||
130 | toml.dump(config, conffile) |
||
131 | |||
132 | def playlist_save_setting(self, config): |
||
133 | """Change the save playlist on close behavior of the music player.""" |
||
134 | if self.playlist_save_checkbox.isChecked(): |
||
135 | config.setdefault('playlist', {})['save_on_close'] = True |
||
136 | |||
137 | elif not self.playlist_save_checkbox.isChecked(): |
||
138 | config.setdefault('playlist', {})['save_on_close'] = False |
||
139 | |||
140 | with open(self.user_config_file, 'w') as conffile: |
||
141 | toml.dump(config, conffile) |
||
142 | |||
143 | def check_playback_setting(self, config): |
||
144 | """Set the cover art playback checkbox state from settings.toml.""" |
||
145 | self.cover_art_playback.setChecked(config['playback']['cover_art']) |
||
146 | |||
147 | def check_playlist_save(self, config): |
||
148 | """Set the playlist save on close state from settings.toml.""" |
||
149 | self.playlist_save_checkbox.setChecked(config['playlist']['save_on_close']) |
||
150 | |||
151 | |||
152 | class ViewOptions(QWidget): |
||
153 | """Contains all of the user configurable options related to the music player window.""" |
||
154 | |||
155 | def __init__(self, parent=None): |
||
156 | """Initiate the View Options page in the preferences dialog.""" |
||
157 | super(ViewOptions, self).__init__(parent) |
||
158 | |||
159 | self.user_config_file = os.path.join(AppDirs('mosaic', 'Mandeep').user_config_dir, |
||
160 | 'settings.toml') |
||
161 | |||
162 | with open(self.user_config_file) as conffile: |
||
163 | config = toml.load(conffile) |
||
164 | |||
165 | dock_config = QGroupBox('Dock Configuration') |
||
166 | |||
167 | self.media_library_view_button = QCheckBox('Show Media Library on Start', self) |
||
168 | self.playlist_view_button = QCheckBox('Show Playlist on Start', self) |
||
169 | |||
170 | dock_start_layout = QVBoxLayout() |
||
171 | dock_start_layout.addWidget(self.media_library_view_button) |
||
172 | dock_start_layout.addWidget(self.playlist_view_button) |
||
173 | |||
174 | self.dock_position = QLabel('Dock Position:') |
||
175 | self.dock_left_side = QRadioButton('Left Side') |
||
176 | self.dock_right_side = QRadioButton('Right Side') |
||
177 | |||
178 | dock_position_layout = QHBoxLayout() |
||
179 | dock_position_layout.addWidget(self.dock_position) |
||
180 | dock_position_layout.addWidget(self.dock_left_side) |
||
181 | dock_position_layout.addWidget(self.dock_right_side) |
||
182 | |||
183 | main_dock_layout = QVBoxLayout() |
||
184 | main_dock_layout.addLayout(dock_start_layout) |
||
185 | main_dock_layout.addLayout(dock_position_layout) |
||
186 | dock_config.setLayout(main_dock_layout) |
||
187 | |||
188 | window_config = QGroupBox("Window Configuration") |
||
189 | |||
190 | size_option = QLabel('Window Size', self) |
||
191 | |||
192 | self.dropdown_box = QComboBox() |
||
193 | self.dropdown_box.addItem('900 x 900') |
||
194 | self.dropdown_box.addItem('800 x 800') |
||
195 | self.dropdown_box.addItem('700 x 700') |
||
196 | self.dropdown_box.addItem('600 x 600') |
||
197 | self.dropdown_box.addItem('500 x 500') |
||
198 | self.dropdown_box.addItem('400 x 400') |
||
199 | |||
200 | window_size_layout = QHBoxLayout() |
||
201 | window_size_layout.addWidget(size_option) |
||
202 | window_size_layout.addWidget(self.dropdown_box) |
||
203 | |||
204 | window_config.setLayout(window_size_layout) |
||
205 | |||
206 | main_layout = QVBoxLayout() |
||
207 | main_layout.addWidget(dock_config) |
||
208 | main_layout.addWidget(window_config) |
||
209 | main_layout.addStretch(1) |
||
210 | self.setLayout(main_layout) |
||
211 | |||
212 | self.check_window_size(config) |
||
213 | self.check_media_library(config) |
||
214 | self.check_playlist_dock(config) |
||
215 | self.check_dock_position(config) |
||
216 | |||
217 | self.dropdown_box.currentIndexChanged.connect(lambda: self.change_size(config)) |
||
218 | self.media_library_view_button.clicked.connect(lambda: self.media_library_view_settings(config)) |
||
219 | self.playlist_view_button.clicked.connect(lambda: self.playlist_view_settings(config)) |
||
220 | self.dock_left_side.clicked.connect(lambda: self.dock_positon_settings(config)) |
||
221 | self.dock_right_side.clicked.connect(lambda: self.dock_positon_settings(config)) |
||
222 | |||
223 | def change_size(self, config): |
||
224 | """Record the change in window size to the settings.toml file.""" |
||
225 | if self.dropdown_box.currentIndex() != -1: |
||
226 | config.setdefault('view_options', {})['window_size'] = self.dropdown_box.currentIndex() |
||
227 | |||
228 | with open(self.user_config_file, 'w') as conffile: |
||
229 | toml.dump(config, conffile) |
||
230 | |||
231 | def check_window_size(self, config): |
||
232 | """Set the dropdown box to the current window size provided by settings.toml.""" |
||
233 | self.dropdown_box.setCurrentIndex(config['view_options']['window_size']) |
||
234 | |||
235 | def media_library_view_settings(self, config): |
||
236 | """Change the behavior of the Media Library dock widget. |
||
237 | |||
238 | The default setting hides the dock on application start. With this option |
||
239 | checked, the media library dock will show on start. |
||
240 | """ |
||
241 | if self.media_library_view_button.isChecked(): |
||
242 | config.setdefault('media_library', {})['show_on_start'] = True |
||
243 | |||
244 | elif not self.media_library_view_button.isChecked(): |
||
245 | config.setdefault('media_library', {})['show_on_start'] = False |
||
246 | |||
247 | with open(self.user_config_file, 'w') as conffile: |
||
248 | toml.dump(config, conffile) |
||
249 | |||
250 | def check_media_library(self, config): |
||
251 | """Set the media library checkbox state from settings.toml.""" |
||
252 | self.media_library_view_button.setChecked(config['media_library']['show_on_start']) |
||
253 | |||
254 | def playlist_view_settings(self, config): |
||
255 | """Change the behavior of the Playlist dock widget. |
||
256 | |||
257 | The default setting hides the dock on application start. With this option |
||
258 | checked, the playlist dock will show on start. |
||
259 | """ |
||
260 | if self.playlist_view_button.isChecked(): |
||
261 | config.setdefault('playlist', {})['show_on_start'] = True |
||
262 | |||
263 | elif not self.playlist_view_button.isChecked(): |
||
264 | config.setdefault('playlist', {})['show_on_start'] = False |
||
265 | |||
266 | with open(self.user_config_file, 'w') as conffile: |
||
267 | toml.dump(config, conffile) |
||
268 | |||
269 | def check_playlist_dock(self, config): |
||
270 | """Set the playlist dock checkbox state from settings.toml.""" |
||
271 | self.playlist_view_button.setChecked(config['playlist']['show_on_start']) |
||
272 | |||
273 | def dock_positon_settings(self, config): |
||
274 | """Write to the settings.toml the radio button chosen by the user.""" |
||
275 | if self.dock_left_side.isChecked(): |
||
276 | config.setdefault('dock', {})['position'] = 'left' |
||
277 | |||
278 | elif self.dock_right_side.isChecked(): |
||
279 | config.setdefault('dock', {})['position'] = 'right' |
||
280 | |||
281 | with open(self.user_config_file, 'w') as conffile: |
||
282 | toml.dump(config, conffile) |
||
283 | |||
284 | def check_dock_position(self, config): |
||
285 | """Select the radio button previously chosen by the user in the preferences dialog.""" |
||
286 | if config['dock']['position'] == 'left': |
||
287 | self.dock_left_side.setChecked(True) |
||
288 | elif config['dock']['position'] == 'right': |
||
289 | self.dock_right_side.setChecked(True) |
||
290 | |||
291 | |||
292 | class PreferencesDialog(QDialog): |
||
293 | """Creates a dialog that shows the user all of the user configurable options. |
||
294 | |||
295 | A list on the left shows all of the available pages, with |
||
296 | the page's contents shown on the right. |
||
297 | """ |
||
298 | |||
299 | def __init__(self, parent=None): |
||
300 | """Initialize the preferences dialog with a list box and a content layout.""" |
||
301 | super(PreferencesDialog, self).__init__(parent) |
||
302 | self.setWindowTitle('Preferences') |
||
303 | |||
304 | settings_icon = utilities.resource_filename('mosaic.images', 'md_settings.png') |
||
305 | self.setWindowIcon(QIcon(settings_icon)) |
||
306 | self.resize(600, 450) |
||
307 | |||
308 | self.contents = QListWidget() |
||
309 | self.contents.setFixedWidth(175) |
||
310 | self.pages = QStackedWidget() |
||
311 | self.button_box = QDialogButtonBox(QDialogButtonBox.Ok) |
||
312 | |||
313 | self.dialog_media_library = MediaLibrary() |
||
314 | self.dialog_playback = Playback() |
||
315 | self.dialog_view_options = ViewOptions() |
||
316 | self.pages.addWidget(self.dialog_media_library) |
||
317 | self.pages.addWidget(self.dialog_playback) |
||
318 | self.pages.addWidget(self.dialog_view_options) |
||
319 | self.list_items() |
||
320 | |||
321 | stack_layout = QVBoxLayout() |
||
322 | stack_layout.addWidget(self.pages) |
||
323 | stack_layout.addWidget(self.button_box) |
||
324 | |||
325 | layout = QHBoxLayout() |
||
326 | layout.addWidget(self.contents) |
||
327 | layout.addLayout(stack_layout) |
||
328 | |||
329 | self.setLayout(layout) |
||
330 | |||
331 | self.contents.currentItemChanged.connect(self.change_page) |
||
332 | self.button_box.accepted.connect(self.accept) |
||
333 | |||
334 | def list_items(self): |
||
335 | """List all of the pages available to the user.""" |
||
336 | media_library_options = QListWidgetItem(self.contents) |
||
337 | media_library_options.setText('Media Library') |
||
338 | media_library_options.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) |
||
339 | self.contents.setCurrentRow(0) |
||
340 | |||
341 | playback_options = QListWidgetItem(self.contents) |
||
342 | playback_options.setText('Playback') |
||
343 | playback_options.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) |
||
344 | |||
345 | view_options = QListWidgetItem(self.contents) |
||
346 | view_options.setText('View Options') |
||
347 | view_options.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) |
||
348 | |||
349 | def change_page(self, current, previous): |
||
350 | """Change the page according to the clicked list item.""" |
||
351 | if not current: |
||
352 | current = previous |
||
353 | |||
354 | self.pages.setCurrentIndex(self.contents.row(current)) |
||
355 |