1 /* This file is part of Clementine.
2 Copyright 2011, 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 "globalsearch.h"
19 #include "globalsearchsettingspage.h"
20 #include "core/logging.h"
21 #include "ui/iconloader.h"
22 #include "ui/settingsdialog.h"
23 #include "ui_globalsearchsettingspage.h"
24
25 #include <algorithm>
26
27 #include <QSettings>
28
GlobalSearchSettingsPage(SettingsDialog * dialog)29 GlobalSearchSettingsPage::GlobalSearchSettingsPage(SettingsDialog* dialog)
30 : SettingsPage(dialog), ui_(new Ui::GlobalSearchSettingsPage) {
31 ui_->setupUi(this);
32 setWindowIcon(IconLoader::Load("search", IconLoader::Base));
33
34 ui_->sources->header()->setSectionResizeMode(0, QHeaderView::Stretch);
35 ui_->sources->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
36
37 warning_icon_ = IconLoader::Load("dialog-warning", IconLoader::Base);
38
39 connect(ui_->up, SIGNAL(clicked()), SLOT(MoveUp()));
40 connect(ui_->down, SIGNAL(clicked()), SLOT(MoveDown()));
41 connect(ui_->configure, SIGNAL(clicked()), SLOT(ConfigureProvider()));
42 connect(ui_->sources,
43 SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
44 SLOT(CurrentProviderChanged(QTreeWidgetItem*)));
45 }
46
~GlobalSearchSettingsPage()47 GlobalSearchSettingsPage::~GlobalSearchSettingsPage() {}
48
CompareProviderId(SearchProvider * left,SearchProvider * right)49 static bool CompareProviderId(SearchProvider* left, SearchProvider* right) {
50 return left->id() < right->id();
51 }
52
Load()53 void GlobalSearchSettingsPage::Load() {
54 QSettings s;
55 s.beginGroup(GlobalSearch::kSettingsGroup);
56
57 GlobalSearch* engine = dialog()->global_search();
58 QList<SearchProvider*> providers = engine->providers();
59
60 // Sort the list of providers alphabetically (by id) initially, so any that
61 // aren't in the provider_order list will take this order.
62 std::sort(providers.begin(), providers.end(), CompareProviderId);
63
64 // Add the ones in the configured list first
65 ui_->sources->clear();
66 for (const QString& id :
67 s.value("provider_order", QStringList() << "library").toStringList()) {
68 // Find a matching provider for this id
69 for (QList<SearchProvider*>::iterator it = providers.begin();
70 it != providers.end(); ++it) {
71 if ((*it)->id() == id) {
72 AddProviderItem(engine, *it);
73 providers.erase(it);
74 break;
75 }
76 }
77 }
78
79 // Now add any others that are remaining
80 for (SearchProvider* provider : providers) {
81 AddProviderItem(engine, provider);
82 }
83
84 ui_->show_providers->setChecked(s.value("show_providers", true).toBool());
85 ui_->show_suggestions->setChecked(s.value("show_suggestions", true).toBool());
86 }
87
AddProviderItem(GlobalSearch * engine,SearchProvider * provider)88 void GlobalSearchSettingsPage::AddProviderItem(GlobalSearch* engine,
89 SearchProvider* provider) {
90 QTreeWidgetItem* item = new QTreeWidgetItem;
91 item->setText(0, provider->name());
92 item->setIcon(0, provider->icon());
93 item->setData(0, Qt::UserRole, QVariant::fromValue(provider));
94
95 UpdateLoggedInState(engine, item, true);
96
97 ui_->sources->invisibleRootItem()->addChild(item);
98 }
99
UpdateLoggedInState(GlobalSearch * engine,QTreeWidgetItem * item,bool set_checked_state)100 void GlobalSearchSettingsPage::UpdateLoggedInState(GlobalSearch* engine,
101 QTreeWidgetItem* item,
102 bool set_checked_state) {
103 SearchProvider* provider =
104 item->data(0, Qt::UserRole).value<SearchProvider*>();
105
106 const bool enabled = engine->is_provider_enabled(provider);
107 const bool logged_in = provider->IsLoggedIn();
108
109 Qt::CheckState check_state =
110 logged_in && enabled ? Qt::Checked : Qt::Unchecked;
111 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
112 if (logged_in) flags |= Qt::ItemIsUserCheckable;
113
114 if (set_checked_state) item->setData(0, Qt::CheckStateRole, check_state);
115 item->setFlags(flags);
116
117 if (logged_in) {
118 item->setIcon(1, QIcon());
119 item->setText(1, QString());
120 } else {
121 item->setIcon(1, warning_icon_);
122 item->setText(1, tr("Not logged in") + " ");
123 }
124 }
125
Save()126 void GlobalSearchSettingsPage::Save() {
127 QSettings s;
128 s.beginGroup(GlobalSearch::kSettingsGroup);
129
130 QStringList provider_order;
131
132 for (int i = 0; i < ui_->sources->invisibleRootItem()->childCount(); ++i) {
133 const QTreeWidgetItem* item = ui_->sources->invisibleRootItem()->child(i);
134 const SearchProvider* provider =
135 item->data(0, Qt::UserRole).value<SearchProvider*>();
136
137 provider_order << provider->id();
138
139 // Only save the enabled state for this provider if it's logged in.
140 if (item->flags() & Qt::ItemIsUserCheckable) {
141 s.setValue("enabled_" + provider->id(),
142 item->data(0, Qt::CheckStateRole).toInt() == Qt::Checked);
143 }
144 }
145
146 s.setValue("provider_order", provider_order);
147 s.setValue("show_providers", ui_->show_providers->isChecked());
148 s.setValue("show_suggestions", ui_->show_suggestions->isChecked());
149 }
150
MoveUp()151 void GlobalSearchSettingsPage::MoveUp() { MoveCurrentItem(-1); }
152
MoveDown()153 void GlobalSearchSettingsPage::MoveDown() { MoveCurrentItem(+1); }
154
MoveCurrentItem(int d)155 void GlobalSearchSettingsPage::MoveCurrentItem(int d) {
156 QTreeWidgetItem* item = ui_->sources->currentItem();
157 if (!item) return;
158
159 QTreeWidgetItem* root = ui_->sources->invisibleRootItem();
160
161 const int row = root->indexOfChild(item);
162 const int new_row = qBound(0, row + d, root->childCount());
163
164 if (row == new_row) return;
165
166 root->removeChild(item);
167 root->insertChild(new_row, item);
168
169 ui_->sources->setCurrentItem(item);
170 }
171
ConfigureProvider()172 void GlobalSearchSettingsPage::ConfigureProvider() {
173 QTreeWidgetItem* item = ui_->sources->currentItem();
174 if (!item) return;
175
176 SearchProvider* provider =
177 item->data(0, Qt::UserRole).value<SearchProvider*>();
178 provider->ShowConfig();
179 }
180
CurrentProviderChanged(QTreeWidgetItem * item)181 void GlobalSearchSettingsPage::CurrentProviderChanged(QTreeWidgetItem* item) {
182 if (!item) return;
183
184 QTreeWidgetItem* root = ui_->sources->invisibleRootItem();
185 SearchProvider* provider =
186 item->data(0, Qt::UserRole).value<SearchProvider*>();
187 const int row = root->indexOfChild(item);
188
189 ui_->up->setEnabled(row != 0);
190 ui_->down->setEnabled(row != root->childCount() - 1);
191 ui_->configure->setEnabled(provider->can_show_config());
192 }
193
showEvent(QShowEvent * e)194 void GlobalSearchSettingsPage::showEvent(QShowEvent* e) {
195 QWidget::showEvent(e);
196
197 // Update the logged-in state of each item when we come back to this page in
198 // the dialog.
199 for (int i = 0; i < ui_->sources->invisibleRootItem()->childCount(); ++i) {
200 UpdateLoggedInState(dialog()->global_search(),
201 ui_->sources->invisibleRootItem()->child(i), false);
202 }
203 }
204