1 /* PlaylistContextMenu.cpp */
2
3 /* Copyright (C) 2011-2020 Michael Lugmair (Lucio Carreras)
4 *
5 * This file is part of sayonara player
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "PlaylistContextMenu.h"
22 #include "PlaylistBookmarksMenu.h"
23
24 #include "Gui/Playlist/PlaylistActionMenu.h"
25 #include "Gui/Utils/Icons.h"
26 #include "Gui/Utils/Widgets/RatingLabel.h"
27
28 #include "Interfaces/DynamicPlayback.h"
29
30 #include "Utils/globals.h"
31 #include "Utils/Language/Language.h"
PrivateBottomBarButton::Private32 #include "Utils/MetaData/MetaData.h"
33
34 using Playlist::ContextMenu;
BottomBarButton(const QIcon & icon,QWidget * parent)35 using Playlist::BookmarksMenu;
36 using Playlist::ActionMenu;
37
38 namespace
39 {
40 ContextMenu::Entries analyzeTrack(const MetaData& track)
41 {
42 const auto isLibraryTrack = (track.id() >= 0);
setIcon(const QIcon & icon)43 const auto isLocalTrack = (track.radioMode() == RadioMode::Off);
44
45 return ((isLibraryTrack) ? ContextMenu::EntryBookmarks : 0) |
46 ((isLibraryTrack) ? ContextMenu::EntryFindInLibrary : 0) |
47 ((isLocalTrack) ? ContextMenu::EntryRating : 0) |
paintEvent(QPaintEvent * e)48 ContextMenu::EntryLyrics;
49 }
50 }
51
52 struct ContextMenu::Private
53 {
54 QMap<ContextMenu::Entry, QAction*> entryActionMap;
55
56 QMenu* ratingMenu;
57 BookmarksMenu* bookmarksMenu;
58 QMenu* playlistModeMenu;
59 QAction* playlistModeAction;
60
61 Private(DynamicPlaybackChecker* dynamicPlaybackChecker, ContextMenu* parent) :
62 ratingMenu {new QMenu(parent)},
63 bookmarksMenu {new BookmarksMenu(parent)},
64 playlistModeMenu {new ActionMenu(dynamicPlaybackChecker, parent)},
65 playlistModeAction {parent->addMenu(playlistModeMenu)}
66 {
67 entryActionMap[EntryRating] = parent->addMenu(ratingMenu);
68 entryActionMap[EntryBookmarks] = parent->addMenu(bookmarksMenu);
69 entryActionMap[EntryCurrentTrack] = new QAction(parent);
70 entryActionMap[EntryFindInLibrary] = new QAction(parent);
71 entryActionMap[EntryReverse] = new QAction(parent);
72
73 parent->addActions
74 ({
75 entryActionMap[EntryReverse],
76 entryActionMap[EntryCurrentTrack],
77 entryActionMap[EntryFindInLibrary],
78 });
79 }
80 };
81
82 ContextMenu::ContextMenu(DynamicPlaybackChecker* dynamicPlaybackChecker, QWidget* parent) :
83 Library::ContextMenu(parent)
84 {
85 m = Pimpl::make<Private>(dynamicPlaybackChecker, this);
86
87 QList<QAction*> ratingActions;
88 for(auto i = +Rating::Zero; i != +Rating::Last; i++)
89 {
90 ratingActions << initRatingAction(static_cast<Rating>(i), m->ratingMenu);
91 }
92
93 m->ratingMenu->addActions(ratingActions);
94
95 connect(m->entryActionMap[EntryCurrentTrack], &QAction::triggered, this, &ContextMenu::sigJumpToCurrentTrack);
96 connect(m->entryActionMap[EntryFindInLibrary], &QAction::triggered, this, &ContextMenu::sigFindTrackTriggered);
97 connect(m->entryActionMap[EntryReverse], &QAction::triggered, this, &ContextMenu::sigReverseTriggered);
98
99 connect(m->bookmarksMenu, &BookmarksMenu::sigBookmarkPressed, this, &ContextMenu::bookmarkPressed);
100
101 skinChanged();
102 }
103
104 ContextMenu::~ContextMenu() = default;
105
106 ContextMenu::Entries ContextMenu::entries() const
107 {
108 auto entries = Library::ContextMenu::entries();
109
110 for(auto it = m->entryActionMap.begin(); it != m->entryActionMap.end(); it++)
111 {
112 if(it.value()->isVisible())
113 {
114 entries |= it.key();
115 }
116 }
117
118 return entries;
119 }
120
121 void ContextMenu::showActions(ContextMenu::Entries entries)
122 {
123 Library::ContextMenu::showActions(entries);
124
125 for(auto it = m->entryActionMap.begin(); it != m->entryActionMap.end(); it++)
126 {
127 const auto isVisible = (entries & it.key());
128 it.value()->setVisible(isVisible);
129 }
130 }
131
132 void ContextMenu::setRating(Rating rating)
133 {
134 const auto actions = m->ratingMenu->actions();
135 for(auto* action : actions)
136 {
137 const auto data = action->data().value<Rating>();
138 action->setChecked(data == rating);
139 }
140
141 const auto ratingText = Lang::get(Lang::Rating);
142
143 const auto text = (rating != Rating::Zero && rating != Rating::Last)
144 ? QString("%1 (%2)").arg(ratingText).arg(+rating)
145 : static_cast<QString>(ratingText);
146
147 m->entryActionMap[EntryRating]->setText(text);
148 }
149
150 ContextMenu::Entries ContextMenu::setTrack(const MetaData& track, bool isCurrentTrack)
151 {
152 const auto isLibraryTrack = (track.id() >= 0);
153
154 m->bookmarksMenu->setTrack(track, (isCurrentTrack && isLibraryTrack));
155 setRating(track.rating());
156
157 return analyzeTrack(track);
158 }
159
160 void ContextMenu::clearTrack()
161 {
162 m->bookmarksMenu->setTrack(MetaData(), false);
163 setRating(Rating::Last);
164 }
165
166 QAction* ContextMenu::initRatingAction(Rating rating, QObject* parent)
167 {
168 auto* action = new QAction(QString::number(+rating), parent);
169
170 action->setData(QVariant::fromValue(rating));
171 action->setCheckable(true);
172
173 connect(action, &QAction::triggered, this, [&]([[maybe_unused]] const auto b) {
174 emit sigRatingChanged(rating);
175 });
176
177 return action;
178 }
179
180 void ContextMenu::languageChanged()
181 {
182 Library::ContextMenu::languageChanged();
183
184 m->entryActionMap[EntryRating]->setText(Lang::get(Lang::Rating));
185 m->entryActionMap[EntryBookmarks]->setText(Lang::get(Lang::Bookmarks));
186 m->entryActionMap[EntryCurrentTrack]->setText(tr("Jump to current track") + QString(" "));
187 m->entryActionMap[EntryFindInLibrary]->setText(tr("Show track in library") + QString(" "));
188 m->entryActionMap[EntryReverse]->setText(Lang::get(Lang::ReverseOrder));
189 m->playlistModeAction->setText(tr("Playlist mode"));
190
191 m->entryActionMap[EntryCurrentTrack]->setShortcut(QKeySequence(Qt::ControlModifier | Qt::Key_J));
192 m->entryActionMap[EntryFindInLibrary]->setShortcut(QKeySequence(Qt::ControlModifier | Qt::Key_G));
193 }
194
195 void ContextMenu::skinChanged()
196 {
197 Library::ContextMenu::skinChanged();
198
199 using namespace Gui;
200 m->entryActionMap[EntryRating]->setIcon(Icons::icon(Icons::Star));
201 m->entryActionMap[EntryFindInLibrary]->setIcon(Icons::icon(Icons::Search));
202 }
203
204 void ContextMenu::bookmarkPressed(Seconds timestamp)
205 {
206 emit sigBookmarkPressed(timestamp);
207 }
208