1 /*
2  * Strawberry Music Player
3  * This file was part of Clementine.
4  * Copyright 2010, David Sansome <me@davidsansome.com>
5  *
6  * Strawberry is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Strawberry is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Strawberry.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "config.h"
22 
23 #include <QWizard>
24 #include <QWizardPage>
25 #include <QLabel>
26 #include <QRadioButton>
27 #include <QVBoxLayout>
28 
29 #include "core/logging.h"
30 #include "core/iconloader.h"
31 
32 #include "smartplaylistquerywizardplugin.h"
33 #include "smartplaylistwizard.h"
34 #include "smartplaylistwizardplugin.h"
35 #include "ui_smartplaylistwizardfinishpage.h"
36 
37 class SmartPlaylistWizard::TypePage : public QWizardPage {  // clazy:exclude=missing-qobject-macro
38  public:
TypePage(QWidget * parent)39   explicit TypePage(QWidget *parent) : QWizardPage(parent), next_id_(-1) {}
40 
nextId() const41   int nextId() const override { return next_id_; }
42   int next_id_;
43 };
44 
45 class SmartPlaylistWizard::FinishPage : public QWizardPage {  // clazy:exclude=missing-qobject-macro
46  public:
FinishPage(QWidget * parent)47   explicit FinishPage(QWidget *parent) : QWizardPage(parent), ui_(new Ui_SmartPlaylistWizardFinishPage) {
48     ui_->setupUi(this);
49     QObject::connect(ui_->name, &QLineEdit::textChanged, this, &SmartPlaylistWizard::FinishPage::completeChanged);
50   }
51 
~FinishPage()52   ~FinishPage() override { delete ui_; }
53 
nextId() const54   int nextId() const override { return -1; }
isComplete() const55   bool isComplete() const override { return !ui_->name->text().isEmpty(); }
56 
57   Ui_SmartPlaylistWizardFinishPage *ui_;
58 
59 };
60 
SmartPlaylistWizard(Application * app,CollectionBackend * collection,QWidget * parent)61 SmartPlaylistWizard::SmartPlaylistWizard(Application *app, CollectionBackend *collection, QWidget *parent)
62     : QWizard(parent),
63       app_(app),
64       collection_(collection),
65       type_page_(new TypePage(this)),
66       finish_page_(new FinishPage(this)),
67       type_index_(-1) {
68 
69   setWindowIcon(IconLoader::Load("strawberry"));
70   setWindowTitle(tr("Smart playlist"));
71 
72   resize(788, 628);
73 
74 #ifdef Q_OS_MACOS
75   // MacStyle leaves an ugly empty space on the left side of the dialog.
76   setWizardStyle(QWizard::ClassicStyle);
77 #endif
78 
79   // Type page
80   type_page_->setTitle(tr("Playlist type"));
81   type_page_->setSubTitle(tr("A smart playlist is a dynamic list of songs that come from your collection.  There are different types of smart playlist that offer different ways of selecting songs."));
82   type_page_->setStyleSheet("QRadioButton { font-weight: bold; } QLabel { margin-bottom: 1em; margin-left: 24px; }");
83   addPage(type_page_);
84 
85   // Finish page
86   finish_page_->setTitle(tr("Finish"));
87   finish_page_->setSubTitle(tr("Choose a name for your smart playlist"));
88   finish_id_ = addPage(finish_page_);
89 
90   new QVBoxLayout(type_page_);
91   AddPlugin(new SmartPlaylistQueryWizardPlugin(app_, collection_, this));
92 
93   // Skip the type page - remove this when we have more than one type
94   setStartId(2);
95 
96 }
97 
~SmartPlaylistWizard()98 SmartPlaylistWizard::~SmartPlaylistWizard() {
99   qDeleteAll(plugins_);
100 }
101 
SetGenerator(PlaylistGeneratorPtr gen)102 void SmartPlaylistWizard::SetGenerator(PlaylistGeneratorPtr gen) {
103 
104   // Find the right type and jump to the start page
105   for (int i = 0; i < plugins_.count(); ++i) {
106     if (plugins_[i]->type() == gen->type()) {
107       TypeChanged(i);
108       // TODO: Put this back in when the setStartId is removed from the ctor next();
109       break;
110     }
111   }
112 
113   if (type_index_ == -1) {
114     qLog(Error) << "Plugin was not found for generator type" << gen->type();
115     return;
116   }
117 
118   // Set the name
119   if (!gen->name().isEmpty()) {
120     setWindowTitle(windowTitle() + " - " + gen->name());
121   }
122   finish_page_->ui_->name->setText(gen->name());
123   finish_page_->ui_->dynamic->setChecked(gen->is_dynamic());
124 
125   // Tell the plugin to load
126   plugins_[type_index_]->SetGenerator(gen);
127 
128 }
129 
AddPlugin(SmartPlaylistWizardPlugin * plugin)130 void SmartPlaylistWizard::AddPlugin(SmartPlaylistWizardPlugin *plugin) {
131 
132   const int index = plugins_.count();
133   plugins_ << plugin;
134   plugin->Init(this, finish_id_);
135 
136   // Create the radio button
137   QRadioButton *radio_button = new QRadioButton(plugin->name(), type_page_);
138   QLabel *description = new QLabel(plugin->description(), type_page_);
139   type_page_->layout()->addWidget(radio_button);
140   type_page_->layout()->addWidget(description);
141 
142   QObject::connect(radio_button, &QRadioButton::clicked, this, [this, index]() { TypeChanged(index); });
143 
144   if (index == 0) {
145     radio_button->setChecked(true);
146     TypeChanged(0);
147   }
148 
149 }
150 
TypeChanged(const int index)151 void SmartPlaylistWizard::TypeChanged(const int index) {
152 
153   type_index_ = index;
154   type_page_->next_id_ = plugins_[type_index_]->start_page();
155 
156 }
157 
CreateGenerator() const158 PlaylistGeneratorPtr SmartPlaylistWizard::CreateGenerator() const {
159 
160   PlaylistGeneratorPtr ret;
161   if (type_index_ == -1) return ret;
162 
163   ret = plugins_[type_index_]->CreateGenerator();
164   if (!ret) return ret;
165 
166   ret->set_name(finish_page_->ui_->name->text());
167   ret->set_dynamic(finish_page_->ui_->dynamic->isChecked());
168   return ret;
169 
170 }
171 
initializePage(const int id)172 void SmartPlaylistWizard::initializePage(const int id) {
173 
174   if (id == finish_id_) {
175     finish_page_->ui_->dynamic_container->setEnabled(plugins_[type_index_]->is_dynamic());
176   }
177   QWizard::initializePage(id);
178 
179 }
180