1 /* This file is part of Clementine.
2    Copyright 2010, 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 "playlistsequence.h"
19 #include "ui_playlistsequence.h"
20 #include "ui/iconloader.h"
21 
22 #include <QMenu>
23 #include <QActionGroup>
24 #include <QSettings>
25 #include <QtDebug>
26 #include <QPainter>
27 
28 const char* PlaylistSequence::kSettingsGroup = "PlaylistSequence";
29 
PlaylistSequence(QWidget * parent,SettingsProvider * settings)30 PlaylistSequence::PlaylistSequence(QWidget* parent, SettingsProvider* settings)
31     : QWidget(parent),
32       ui_(new Ui_PlaylistSequence),
33       settings_(settings ? settings : new DefaultSettingsProvider),
34       repeat_menu_(new QMenu(this)),
35       shuffle_menu_(new QMenu(this)),
36       loading_(false),
37       repeat_mode_(Repeat_Off),
38       shuffle_mode_(Shuffle_Off),
39       dynamic_(false) {
40   ui_->setupUi(this);
41 
42   // Icons
43   ui_->repeat->setIcon(
44       AddDesaturatedIcon(IconLoader::Load("media-playlist-repeat", IconLoader::Base)));
45   ui_->shuffle->setIcon(
46       AddDesaturatedIcon(IconLoader::Load("media-playlist-shuffle", IconLoader::Base)));
47 
48   // Remove arrow indicators
49   ui_->repeat->setStyleSheet("QToolButton::menu-indicator { image: none; }");
50   ui_->shuffle->setStyleSheet("QToolButton::menu-indicator { image: none; }");
51 
52   settings_->set_group(kSettingsGroup);
53 
54   QActionGroup* repeat_group = new QActionGroup(this);
55   repeat_group->addAction(ui_->action_repeat_off);
56   repeat_group->addAction(ui_->action_repeat_track);
57   repeat_group->addAction(ui_->action_repeat_album);
58   repeat_group->addAction(ui_->action_repeat_playlist);
59   repeat_group->addAction(ui_->action_repeat_onebyone);
60   repeat_group->addAction(ui_->action_repeat_intro);
61   repeat_menu_->addActions(repeat_group->actions());
62   ui_->repeat->setMenu(repeat_menu_);
63 
64   QActionGroup* shuffle_group = new QActionGroup(this);
65   shuffle_group->addAction(ui_->action_shuffle_off);
66   shuffle_group->addAction(ui_->action_shuffle_all);
67   shuffle_group->addAction(ui_->action_shuffle_inside_album);
68   shuffle_group->addAction(ui_->action_shuffle_albums);
69   shuffle_menu_->addActions(shuffle_group->actions());
70   ui_->shuffle->setMenu(shuffle_menu_);
71 
72   connect(repeat_group, SIGNAL(triggered(QAction*)),
73           SLOT(RepeatActionTriggered(QAction*)));
74   connect(shuffle_group, SIGNAL(triggered(QAction*)),
75           SLOT(ShuffleActionTriggered(QAction*)));
76 
77   Load();
78 }
79 
~PlaylistSequence()80 PlaylistSequence::~PlaylistSequence() { delete ui_; }
81 
Load()82 void PlaylistSequence::Load() {
83   loading_ = true;  // Stops these setter functions calling Save()
84   SetShuffleMode(
85       ShuffleMode(settings_->value("shuffle_mode", Shuffle_Off).toInt()));
86   SetRepeatMode(
87       RepeatMode(settings_->value("repeat_mode", Repeat_Off).toInt()));
88   loading_ = false;
89 }
90 
Save()91 void PlaylistSequence::Save() {
92   if (loading_) return;
93 
94   settings_->setValue("shuffle_mode", shuffle_mode_);
95   settings_->setValue("repeat_mode", repeat_mode_);
96 }
97 
AddDesaturatedIcon(const QIcon & icon)98 QIcon PlaylistSequence::AddDesaturatedIcon(const QIcon& icon) {
99   QIcon ret;
100   for (const QSize& size : icon.availableSizes()) {
101     QPixmap on(icon.pixmap(size));
102     QPixmap off(DesaturatedPixmap(on));
103 
104     ret.addPixmap(off, QIcon::Normal, QIcon::Off);
105     ret.addPixmap(on, QIcon::Normal, QIcon::On);
106   }
107   return ret;
108 }
109 
DesaturatedPixmap(const QPixmap & pixmap)110 QPixmap PlaylistSequence::DesaturatedPixmap(const QPixmap& pixmap) {
111   QPixmap ret(pixmap.size());
112   ret.fill(Qt::transparent);
113 
114   QPainter p(&ret);
115   p.setOpacity(0.5);
116   p.drawPixmap(0, 0, pixmap);
117   p.end();
118 
119   return ret;
120 }
121 
RepeatActionTriggered(QAction * action)122 void PlaylistSequence::RepeatActionTriggered(QAction* action) {
123   RepeatMode mode = Repeat_Off;
124   if (action == ui_->action_repeat_track) mode = Repeat_Track;
125   if (action == ui_->action_repeat_album) mode = Repeat_Album;
126   if (action == ui_->action_repeat_playlist) mode = Repeat_Playlist;
127   if (action == ui_->action_repeat_onebyone) mode = Repeat_OneByOne;
128   if (action == ui_->action_repeat_intro) mode = Repeat_Intro;
129 
130   SetRepeatMode(mode);
131 }
132 
ShuffleActionTriggered(QAction * action)133 void PlaylistSequence::ShuffleActionTriggered(QAction* action) {
134   ShuffleMode mode = Shuffle_Off;
135   if (action == ui_->action_shuffle_all) mode = Shuffle_All;
136   if (action == ui_->action_shuffle_inside_album) mode = Shuffle_InsideAlbum;
137   if (action == ui_->action_shuffle_albums) mode = Shuffle_Albums;
138 
139   SetShuffleMode(mode);
140 }
141 
SetRepeatMode(RepeatMode mode)142 void PlaylistSequence::SetRepeatMode(RepeatMode mode) {
143   ui_->repeat->setChecked(mode != Repeat_Off);
144 
145   switch (mode) {
146     case Repeat_Off:
147       ui_->action_repeat_off->setChecked(true);
148       break;
149     case Repeat_Track:
150       ui_->action_repeat_track->setChecked(true);
151       break;
152     case Repeat_Album:
153       ui_->action_repeat_album->setChecked(true);
154       break;
155     case Repeat_Playlist:
156       ui_->action_repeat_playlist->setChecked(true);
157       break;
158     case Repeat_OneByOne:
159       ui_->action_repeat_onebyone->setChecked(true);
160       break;
161     case Repeat_Intro:
162       ui_->action_repeat_intro->setChecked(true);
163       break;
164   }
165 
166   if (mode != repeat_mode_) {
167     repeat_mode_ = mode;
168     emit RepeatModeChanged(mode);
169   }
170 
171   Save();
172 }
173 
SetShuffleMode(ShuffleMode mode)174 void PlaylistSequence::SetShuffleMode(ShuffleMode mode) {
175   ui_->shuffle->setChecked(mode != Shuffle_Off);
176 
177   switch (mode) {
178     case Shuffle_Off:
179       ui_->action_shuffle_off->setChecked(true);
180       break;
181     case Shuffle_All:
182       ui_->action_shuffle_all->setChecked(true);
183       break;
184     case Shuffle_InsideAlbum:
185       ui_->action_shuffle_inside_album->setChecked(true);
186       break;
187     case Shuffle_Albums:
188       ui_->action_shuffle_albums->setChecked(true);
189       break;
190   }
191 
192   if (mode != shuffle_mode_) {
193     shuffle_mode_ = mode;
194     emit ShuffleModeChanged(mode);
195   }
196 
197   Save();
198 }
199 
SetUsingDynamicPlaylist(bool dynamic)200 void PlaylistSequence::SetUsingDynamicPlaylist(bool dynamic) {
201   dynamic_ = dynamic;
202   const QString not_available(
203       tr("Not available while using a dynamic playlist"));
204 
205   setEnabled(!dynamic);
206   ui_->shuffle->setToolTip(dynamic ? not_available : tr("Shuffle"));
207   ui_->repeat->setToolTip(dynamic ? not_available : tr("Repeat"));
208 }
209 
shuffle_mode() const210 PlaylistSequence::ShuffleMode PlaylistSequence::shuffle_mode() const {
211   return dynamic_ ? Shuffle_Off : shuffle_mode_;
212 }
213 
repeat_mode() const214 PlaylistSequence::RepeatMode PlaylistSequence::repeat_mode() const {
215   return dynamic_ ? Repeat_Off : repeat_mode_;
216 }
217 
218 // called from global shortcut
CycleShuffleMode()219 void PlaylistSequence::CycleShuffleMode() {
220   ShuffleMode mode = Shuffle_Off;
221   // we cycle through the shuffle modes
222   switch (shuffle_mode()) {
223     case Shuffle_Off:
224       mode = Shuffle_All;
225       break;
226     case Shuffle_All:
227       mode = Shuffle_InsideAlbum;
228       break;
229     case Shuffle_InsideAlbum:
230       mode = Shuffle_Albums;
231       break;
232     case Shuffle_Albums:
233       break;
234   }
235 
236   SetShuffleMode(mode);
237 }
238 
239 // called from global shortcut
CycleRepeatMode()240 void PlaylistSequence::CycleRepeatMode() {
241   RepeatMode mode = Repeat_Off;
242   // we cycle through the repeat modes
243   switch (repeat_mode()) {
244     case Repeat_Off:
245       mode = Repeat_Track;
246       break;
247     case Repeat_Track:
248       mode = Repeat_Album;
249       break;
250     case Repeat_Album:
251       mode = Repeat_Playlist;
252       break;
253     case Repeat_Playlist:
254       mode = Repeat_OneByOne;
255       break;
256     case Repeat_OneByOne:
257       mode = Repeat_Intro;
258       break;
259     case Repeat_Intro:
260       break;
261   }
262 
263   SetRepeatMode(mode);
264 }
265