1 /* This file is part of Clementine.
2    Copyright 2012, David Sansome <me@davidsansome.com>
3 
4    Clementine is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    Clementine is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "appearancesettingspage.h"
19 
20 #include <QApplication>
21 #include <QColorDialog>
22 #include <QFileDialog>
23 #include <QPainter>
24 #include <QSettings>
25 
26 #include "config.h"
27 #include "iconloader.h"
28 #include "mainwindow.h"
29 #include "settingsdialog.h"
30 #include "ui_appearancesettingspage.h"
31 #include "core/appearance.h"
32 #include "core/application.h"
33 #include "core/logging.h"
34 #include "playlist/playlistview.h"
35 #include "ui/albumcoverchoicecontroller.h"
36 
37 #ifdef HAVE_MOODBAR
38 #include "moodbar/moodbarrenderer.h"
39 #endif
40 
41 const int AppearanceSettingsPage::kMoodbarPreviewWidth = 150;
42 const int AppearanceSettingsPage::kMoodbarPreviewHeight = 18;
43 
AppearanceSettingsPage(SettingsDialog * dialog)44 AppearanceSettingsPage::AppearanceSettingsPage(SettingsDialog* dialog)
45     : SettingsPage(dialog),
46       ui_(new Ui_AppearanceSettingsPage),
47       original_use_a_custom_color_set_(false),
48       playlist_view_background_image_type_(PlaylistView::Default),
49       initialised_moodbar_previews_(false) {
50   ui_->setupUi(this);
51   setWindowIcon(IconLoader::Load("view-media-visualization", IconLoader::Base));
52 
53   connect(ui_->blur_slider, SIGNAL(valueChanged(int)),
54           SLOT(BlurLevelChanged(int)));
55   connect(ui_->opacity_slider, SIGNAL(valueChanged(int)),
56           SLOT(OpacityLevelChanged(int)));
57 
58   Load();
59 
60   connect(ui_->select_foreground_color, SIGNAL(pressed()),
61           SLOT(SelectForegroundColor()));
62   connect(ui_->select_background_color, SIGNAL(pressed()),
63           SLOT(SelectBackgroundColor()));
64   connect(ui_->use_a_custom_color_set, SIGNAL(toggled(bool)),
65           SLOT(UseCustomColorSetOptionChanged(bool)));
66 
67   connect(ui_->select_background_image_filename_button, SIGNAL(pressed()),
68           SLOT(SelectBackgroundImage()));
69   connect(ui_->use_custom_background_image, SIGNAL(toggled(bool)),
70           ui_->background_image_filename, SLOT(setEnabled(bool)));
71   connect(ui_->use_custom_background_image, SIGNAL(toggled(bool)),
72           ui_->select_background_image_filename_button, SLOT(setEnabled(bool)));
73 
74   connect(ui_->use_custom_background_image, SIGNAL(toggled(bool)),
75           ui_->blur_slider, SLOT(setEnabled(bool)));
76   connect(ui_->use_album_cover_background, SIGNAL(toggled(bool)),
77           ui_->blur_slider, SLOT(setEnabled(bool)));
78 
79   connect(ui_->use_default_background, SIGNAL(toggled(bool)),
80           SLOT(DisableBlurAndOpacitySliders(bool)));
81   connect(ui_->use_no_background, SIGNAL(toggled(bool)),
82           SLOT(DisableBlurAndOpacitySliders(bool)));
83 #if !defined(Q_OS_UNIX) || defined(Q_OS_MAC)
84   ui_->b_use_sys_icons->setDisabled(true);
85 #endif
86 }
87 
~AppearanceSettingsPage()88 AppearanceSettingsPage::~AppearanceSettingsPage() { delete ui_; }
89 
Load()90 void AppearanceSettingsPage::Load() {
91   QSettings s;
92   s.beginGroup(Appearance::kSettingsGroup);
93 
94   QPalette p = QApplication::palette();
95 
96   // Keep in mind originals colors, in case the user clicks on Cancel, to be
97   // able to restore colors
98   original_use_a_custom_color_set_ =
99       s.value(Appearance::kUseCustomColorSet, false).toBool();
100 
101   original_foreground_color_ =
102       s.value(Appearance::kForegroundColor, p.color(QPalette::WindowText))
103           .value<QColor>();
104   current_foreground_color_ = original_foreground_color_;
105   original_background_color_ =
106       s.value(Appearance::kBackgroundColor, p.color(QPalette::Window))
107           .value<QColor>();
108   current_background_color_ = original_background_color_;
109 
110   InitColorSelectorsColors();
111   ui_->b_use_sys_icons->setChecked(s.value("b_use_sys_icons", false).toBool());
112   ui_->b_hide_filter_toolbar->setChecked(s.value("b_hide_filter_toolbar",false).toBool());
113   s.endGroup();
114 
115   // Playlist settings
116   s.beginGroup(Playlist::kSettingsGroup);
117   playlist_view_background_image_type_ =
118       static_cast<PlaylistView::BackgroundImageType>(
119           s.value(PlaylistView::kSettingBackgroundImageType).toInt());
120   playlist_view_background_image_filename_ =
121       s.value(PlaylistView::kSettingBackgroundImageFilename).toString();
122 
123   ui_->use_system_color_set->setChecked(!original_use_a_custom_color_set_);
124   ui_->use_a_custom_color_set->setChecked(original_use_a_custom_color_set_);
125 
126   switch (playlist_view_background_image_type_) {
127     case PlaylistView::None:
128       ui_->use_no_background->setChecked(true);
129       DisableBlurAndOpacitySliders(true);
130       break;
131     case PlaylistView::AlbumCover:
132       ui_->use_album_cover_background->setChecked(true);
133       break;
134     case PlaylistView::Custom:
135       ui_->use_custom_background_image->setChecked(true);
136       break;
137     case PlaylistView::Default:
138     default:
139       ui_->use_default_background->setChecked(true);
140       DisableBlurAndOpacitySliders(true);
141   }
142   ui_->background_image_filename->setText(
143       playlist_view_background_image_filename_);
144   ui_->blur_slider->setValue(
145       s.value("blur_radius", PlaylistView::kDefaultBlurRadius).toInt());
146   ui_->opacity_slider->setValue(
147       s.value("opacity_level", PlaylistView::kDefaultOpacityLevel).toInt());
148 
149   s.endGroup();
150 
151   // Moodbar settings
152   s.beginGroup("Moodbar");
153   ui_->moodbar_show->setChecked(s.value("show", true).toBool());
154   ui_->moodbar_style->setCurrentIndex(s.value("style", 0).toInt());
155   ui_->moodbar_calculate->setChecked(!s.value("calculate", true).toBool());
156   ui_->moodbar_save->setChecked(
157       s.value("save_alongside_originals", false).toBool());
158   s.endGroup();
159 
160   InitMoodbarPreviews();
161 }
162 
Save()163 void AppearanceSettingsPage::Save() {
164   QSettings s;
165   s.beginGroup(Appearance::kSettingsGroup);
166   bool use_a_custom_color_set = ui_->use_a_custom_color_set->isChecked();
167   s.setValue(Appearance::kUseCustomColorSet, use_a_custom_color_set);
168   if (use_a_custom_color_set) {
169     s.setValue(Appearance::kBackgroundColor, current_background_color_);
170     s.setValue(Appearance::kForegroundColor, current_foreground_color_);
171   } else {
172     dialog()->appearance()->ResetToSystemDefaultTheme();
173   }
174   s.setValue("b_use_sys_icons", ui_->b_use_sys_icons->isChecked());
175   s.setValue("b_hide_filter_toolbar", ui_->b_hide_filter_toolbar->isChecked());
176   s.endGroup();
177 
178   // Playlist settings
179   s.beginGroup(Playlist::kSettingsGroup);
180   playlist_view_background_image_filename_ =
181       ui_->background_image_filename->text();
182   if (ui_->use_no_background->isChecked()) {
183     playlist_view_background_image_type_ = PlaylistView::None;
184   } else if (ui_->use_album_cover_background->isChecked()) {
185     playlist_view_background_image_type_ = PlaylistView::AlbumCover;
186   } else if (ui_->use_default_background->isChecked()) {
187     playlist_view_background_image_type_ = PlaylistView::Default;
188   } else if (ui_->use_custom_background_image->isChecked()) {
189     playlist_view_background_image_type_ = PlaylistView::Custom;
190     s.setValue(PlaylistView::kSettingBackgroundImageFilename,
191                playlist_view_background_image_filename_);
192   }
193   s.setValue(PlaylistView::kSettingBackgroundImageType,
194              playlist_view_background_image_type_);
195   s.setValue("blur_radius", ui_->blur_slider->value());
196   s.setValue("opacity_level", ui_->opacity_slider->value());
197   s.endGroup();
198 
199   // Moodbar settings
200   s.beginGroup("Moodbar");
201   s.setValue("calculate", !ui_->moodbar_calculate->isChecked());
202   s.setValue("show", ui_->moodbar_show->isChecked());
203   s.setValue("style", ui_->moodbar_style->currentIndex());
204   s.setValue("save_alongside_originals", ui_->moodbar_save->isChecked());
205   s.endGroup();
206 }
207 
Cancel()208 void AppearanceSettingsPage::Cancel() {
209   if (original_use_a_custom_color_set_) {
210     dialog()->appearance()->ChangeForegroundColor(original_foreground_color_);
211     dialog()->appearance()->ChangeBackgroundColor(original_background_color_);
212   } else {
213     dialog()->appearance()->ResetToSystemDefaultTheme();
214   }
215 }
216 
SelectForegroundColor()217 void AppearanceSettingsPage::SelectForegroundColor() {
218   QColor color_selected = QColorDialog::getColor(current_foreground_color_);
219   if (!color_selected.isValid()) return;
220 
221   current_foreground_color_ = color_selected;
222   dialog()->appearance()->ChangeForegroundColor(color_selected);
223 
224   UpdateColorSelectorColor(ui_->select_foreground_color, color_selected);
225 }
226 
SelectBackgroundColor()227 void AppearanceSettingsPage::SelectBackgroundColor() {
228   QColor color_selected = QColorDialog::getColor(current_background_color_);
229   if (!color_selected.isValid()) return;
230 
231   current_background_color_ = color_selected;
232   dialog()->appearance()->ChangeBackgroundColor(color_selected);
233 
234   UpdateColorSelectorColor(ui_->select_background_color, color_selected);
235 }
236 
UseCustomColorSetOptionChanged(bool checked)237 void AppearanceSettingsPage::UseCustomColorSetOptionChanged(bool checked) {
238   if (checked) {
239     dialog()->appearance()->ChangeForegroundColor(current_foreground_color_);
240     dialog()->appearance()->ChangeBackgroundColor(current_background_color_);
241   } else {
242     dialog()->appearance()->ResetToSystemDefaultTheme();
243   }
244 }
245 
InitColorSelectorsColors()246 void AppearanceSettingsPage::InitColorSelectorsColors() {
247   UpdateColorSelectorColor(ui_->select_foreground_color,
248                            current_foreground_color_);
249   UpdateColorSelectorColor(ui_->select_background_color,
250                            current_background_color_);
251 }
252 
UpdateColorSelectorColor(QWidget * color_selector,const QColor & color)253 void AppearanceSettingsPage::UpdateColorSelectorColor(QWidget* color_selector,
254                                                       const QColor& color) {
255   QString css =
256       QString("background-color: rgb(%1, %2, %3); color: rgb(255, 255, 255)")
257           .arg(color.red())
258           .arg(color.green())
259           .arg(color.blue());
260   color_selector->setStyleSheet(css);
261 }
262 
SelectBackgroundImage()263 void AppearanceSettingsPage::SelectBackgroundImage() {
264   QString selected_filename = QFileDialog::getOpenFileName(
265       this, tr("Select background image"),
266       playlist_view_background_image_filename_,
267       tr(AlbumCoverChoiceController::kLoadImageFileFilter) + ";;" +
268           tr(AlbumCoverChoiceController::kAllFilesFilter));
269   if (selected_filename.isEmpty()) return;
270   playlist_view_background_image_filename_ = selected_filename;
271   ui_->background_image_filename->setText(
272       playlist_view_background_image_filename_);
273 }
274 
BlurLevelChanged(int value)275 void AppearanceSettingsPage::BlurLevelChanged(int value) {
276   ui_->background_blur_radius_label->setText(QString("%1px").arg(value));
277 }
278 
OpacityLevelChanged(int percent)279 void AppearanceSettingsPage::OpacityLevelChanged(int percent) {
280   ui_->background_opacity_label->setText(QString("%1\%").arg(percent));
281 }
282 
InitMoodbarPreviews()283 void AppearanceSettingsPage::InitMoodbarPreviews() {
284 #ifdef HAVE_MOODBAR
285   if (initialised_moodbar_previews_) return;
286   initialised_moodbar_previews_ = true;
287 
288   const QSize preview_size(kMoodbarPreviewWidth, kMoodbarPreviewHeight);
289   ui_->moodbar_style->setIconSize(preview_size);
290 
291   // Read the sample data
292   QFile file(":sample.mood");
293   if (!file.open(QIODevice::ReadOnly)) {
294     qLog(Warning) << "Unable to open moodbar sample file";
295     return;
296   }
297   QByteArray data(file.readAll());
298 
299   // Render and set each preview
300   for (int i = 0; i < MoodbarRenderer::StyleCount; ++i) {
301     const MoodbarRenderer::MoodbarStyle style =
302         MoodbarRenderer::MoodbarStyle(i);
303     const ColorVector colors = MoodbarRenderer::Colors(data, style, palette());
304 
305     QPixmap pixmap(preview_size);
306     QPainter p(&pixmap);
307     MoodbarRenderer::Render(colors, &p, pixmap.rect());
308     p.end();
309 
310     ui_->moodbar_style->addItem(MoodbarRenderer::StyleName(style));
311     ui_->moodbar_style->setItemData(i, pixmap, Qt::DecorationRole);
312   }
313 #else
314   ui_->moodbar_group->hide();
315 #endif
316 }
317 
DisableBlurAndOpacitySliders(bool checked)318 void AppearanceSettingsPage::DisableBlurAndOpacitySliders(bool checked) {
319   // Blur slider
320   ui_->blur_slider->setDisabled(checked);
321   ui_->background_blur_radius_label->setDisabled(checked);
322   ui_->select_background_blur_label->setDisabled(checked);
323 
324   // Opacity slider
325   ui_->opacity_slider->setDisabled(checked);
326   ui_->background_opacity_label->setDisabled(checked);
327   ui_->select_opacity_level_label->setDisabled(checked);
328 }
329