1 /*
2  * Cantata
3  *
4  * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5  *
6  * ----
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "interfacesettings.h"
25 #include "settings.h"
26 #include "models/sqllibrarymodel.h"
27 #include "support/utils.h"
28 #include "support/fancytabwidget.h"
29 #include "support/pathrequester.h"
30 #include "widgets/basicitemdelegate.h"
31 #include "widgets/playqueueview.h"
32 #include "widgets/itemview.h"
33 #include "db/librarydb.h"
34 #include <QComboBox>
35 #include <QDir>
36 #include <QMap>
37 #include <QRegExp>
38 #include <QSet>
39 #ifdef QT_QTDBUS_FOUND
40 #include <QDBusConnection>
41 #include <QDBusConnectionInterface>
42 #endif
43 #include <QSystemTrayIcon>
44 #include <QSysInfo>
45 #include <QStyleFactory>
46 #include <algorithm>
47 
48 #define REMOVE(w) \
49     w->setVisible(false); \
50     w->deleteLater(); \
51     w=0;
52 
viewTypeString(ItemView::Mode mode)53 static QString viewTypeString(ItemView::Mode mode)
54 {
55     switch (mode) {
56     default:
57     case ItemView::Mode_GroupedTree:  return QObject::tr("Grouped Albums");
58     case ItemView::Mode_Table:        return QObject::tr("Table");
59     }
60 }
61 
addViewTypes(QComboBox * box,QList<ItemView::Mode> modes)62 static void addViewTypes(QComboBox *box, QList<ItemView::Mode> modes)
63 {
64     for (ItemView::Mode m: modes) {
65         box->addItem(viewTypeString(m), m);
66     }
67 }
68 
cueSupportString(MPDParseUtils::CueSupport cs)69 static QString cueSupportString(MPDParseUtils::CueSupport cs)
70 {
71     switch (cs) {
72     default:
73     case MPDParseUtils::Cue_Parse:            return QObject::tr("Parse in Library view, and show in Folders view");
74     case MPDParseUtils::Cue_ListButDontParse: return QObject::tr("Only show in Folders view");
75     case MPDParseUtils::Cue_Ignore:           return QObject::tr("Do not list");
76     }
77 }
78 
addCueSupportTypes(QComboBox * box)79 static void addCueSupportTypes(QComboBox *box)
80 {
81     for (int i=0; i<MPDParseUtils::Cue_Count; ++i) {
82         box->addItem(cueSupportString((MPDParseUtils::CueSupport)i), i);
83     }
84 }
85 
selectEntry(QComboBox * box,int v)86 static void selectEntry(QComboBox *box, int v)
87 {
88     for (int i=1; i<box->count(); ++i) {
89         if (box->itemData(i).toInt()==v) {
90             box->setCurrentIndex(i);
91             return;
92         }
93     }
94 }
95 
getValue(QComboBox * box)96 static inline int getValue(QComboBox *box)
97 {
98     return box->itemData(box->currentIndex()).toInt();
99 }
100 
getStrValue(QComboBox * box)101 static inline QString getStrValue(QComboBox *box)
102 {
103     return box->itemData(box->currentIndex()).toString();
104 }
105 
106 static const char * constValueProperty="value";
107 static const char * constSep=",";
108 
109 class CoverNameValidator : public QValidator
110 {
111     public:
112 
CoverNameValidator(QObject * parent)113     CoverNameValidator(QObject *parent) : QValidator(parent) { }
114 
validate(QString & input,int &) const115     State validate(QString &input, int &) const override
116     {
117         for (int i=0; i<input.length(); ++i) {
118             if (!input[i].isLetterOrNumber() && '%'!=input[i] && ' '!=input[i] && '-'!=input[i]) {
119                 return Invalid;
120             }
121         }
122 
123         return Acceptable;
124     }
125 };
126 
InterfaceSettings(QWidget * p)127 InterfaceSettings::InterfaceSettings(QWidget *p)
128     : QWidget(p)
129     , loaded(false)
130 {
131     bool mprisSettings=false;
132     bool enableTrayItem=Utils::useSystemTray();
133     #ifdef Q_OS_MAC
134     // OSX always displays an entry in the taskbar - and the tray seems to confuse things.
135     bool enableNotifications=QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8;
136     #else
137     #ifdef QT_QTDBUS_FOUND
138     // We have dbus, check that org.freedesktop.Notifications exists
139     bool enableNotifications=QDBusConnection::sessionBus().interface()->isServiceRegistered("org.freedesktop.Notifications");
140     mprisSettings=true;
141     #else // QT_QTDBUS_FOUND
142     bool enableNotifications=true;
143     #endif // QT_QTDBUS_FOUND
144     #endif // Q_MAC_OS
145 
146     setupUi(this);
147     addCueSupportTypes(cueSupport);
148     addViewTypes(playQueueView, QList<ItemView::Mode>() << ItemView::Mode_GroupedTree << ItemView::Mode_Table);
149     yearTag->addItem(tr("Use 'Year' tag to display & sort"));
150     yearTag->addItem(tr("Use 'Original Year' tag to display & sort, fallback to 'Year' if not set"));
151 
152     addView(tr("Play Queue"), QLatin1String("PlayQueuePage"));
153     addView(tr("Library"), QLatin1String("LibraryPage"));
154     addView(tr("Folders"), QLatin1String("FolderPage"));
155     addView(tr("Playlists"), QLatin1String("PlaylistsPage"));
156     addView(tr("Internet - Streams, Jamendo, Maganatune, SoundCloud, and Podcasts"), QLatin1String("OnlineServicesPage"));
157     #ifdef ENABLE_DEVICES_SUPPORT
158     addView(tr("Devices - UMS, MTP (e.g. Android), and AudioCDs"), QLatin1String("DevicesPage"));
159     #else
160     REMOVE(showDeleteAction)
161     #endif
162     addView(tr("Search (via MPD)"), QLatin1String("SearchPage"));
163     addView(tr("Info - Current song information (artist, album, and lyrics)"), QLatin1String("ContextPage"));
164     connect(playQueueView, SIGNAL(currentIndexChanged(int)), SLOT(playQueueViewChanged()));
165     connect(forceSingleClick, SIGNAL(toggled(bool)), SLOT(forceSingleClickChanged()));
166     connect(views, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(viewItemChanged(QListWidgetItem*)));
167 
168     sbStyle->addItem(tr("Large"), FancyTabWidget::Large);
169     sbStyle->addItem(tr("Small"), FancyTabWidget::Small);
170     sbStyle->addItem(tr("Tab-bar"), FancyTabWidget::Tab);
171     sbPosition->addItem(Qt::LeftToRight==layoutDirection() ? tr("Left") : tr("Right"), FancyTabWidget::Side);
172     sbPosition->addItem(tr("Top"), FancyTabWidget::Top);
173     sbPosition->addItem(tr("Bottom"), FancyTabWidget::Bot);
174     connect(sbAutoHide, SIGNAL(toggled(bool)), SLOT(sbAutoHideChanged()));
175     views->setItemDelegate(new BasicItemDelegate(views));
176     playQueueBackground_none->setProperty(constValueProperty, PlayQueueView::BI_None);
177     playQueueBackground_cover->setProperty(constValueProperty, PlayQueueView::BI_Cover);
178     playQueueBackground_custom->setProperty(constValueProperty, PlayQueueView::BI_Custom);
179     playQueueBackgroundFile->setDirMode(false);
180     playQueueBackgroundFile->setFilter(tr("Images (*.png *.jpg)"));
181     int labelWidth=qMax(fontMetrics().horizontalAdvance(QLatin1String("100%")), fontMetrics().horizontalAdvance(tr("10px", "pixels")));
182     playQueueBackgroundOpacityLabel->setFixedWidth(labelWidth);
183     playQueueBackgroundBlurLabel->setFixedWidth(labelWidth);
184     connect(playQueueBackgroundOpacity, SIGNAL(valueChanged(int)), SLOT(setPlayQueueBackgroundOpacityLabel()));
185     connect(playQueueBackgroundBlur, SIGNAL(valueChanged(int)), SLOT(setPlayQueueBackgroundBlurLabel()));
186     connect(playQueueBackground_none, SIGNAL(toggled(bool)), SLOT(enablePlayQueueBackgroundOptions()));
187     connect(playQueueBackground_cover, SIGNAL(toggled(bool)), SLOT(enablePlayQueueBackgroundOptions()));
188     connect(playQueueBackground_custom, SIGNAL(toggled(bool)), SLOT(enablePlayQueueBackgroundOptions()));
189     connect(storeCoversInMpdDir, SIGNAL(toggled(bool)), this, SLOT(storeCoversInMpdDirToggled()));
190     if (!enableNotifications) {
191         REMOVE(systemTrayPopup)
192     }
193     if (enableTrayItem) {
194         connect(systemTrayCheckBox, SIGNAL(toggled(bool)), minimiseOnClose, SLOT(setEnabled(bool)));
195         connect(systemTrayCheckBox, SIGNAL(toggled(bool)), SLOT(enableStartupState()));
196         connect(minimiseOnClose, SIGNAL(toggled(bool)), SLOT(enableStartupState()));
197     } else {
198         REMOVE(systemTrayCheckBox)
199         REMOVE(minimiseOnClose)
200         REMOVE(startupState)
201     }
202 
203     if (!enableNotifications && !enableTrayItem && !mprisSettings) {
204         tabWidget->removeTab(3);
205     } else if (!enableTrayItem && enableNotifications && !mprisSettings) {
206         tabWidget->setTabText(3, tr("Notifications"));
207     }
208     if (!mprisSettings) {
209         REMOVE(enableMpris)
210     }
211     #if defined Q_OS_WIN || defined Q_OS_MAC || !defined QT_QTDBUS_FOUND
212     if (systemTrayPopup && systemTrayCheckBox) {
213         connect(systemTrayCheckBox, SIGNAL(toggled(bool)), SLOT(systemTrayCheckBoxToggled()));
214         connect(systemTrayPopup, SIGNAL(toggled(bool)), SLOT(systemTrayPopupToggled()));
215     }
216     #endif
217     coverFilenameLabel->setToolTip(coverFilename->toolTip());
218     coverFilename->setValidator(new CoverNameValidator(this));
219     #ifdef ENABLE_DEVICES_SUPPORT
220     coverNameNoteLabel->setText(tr("If no setting is specified for 'Filename', then Cantata will use a default of "
221                                    "<code>cover</code>. This filename is used when downloading covers, or when adding "
222                                    "music to your library from devices. This should be specified <b>without</b> an extension."));
223     #else
224     coverNameNoteLabel->setText(tr("If no setting is specified for 'Filename', then Cantata will use a default of "
225                                    "<code>cover</code>. This filename is used when downloading covers. This should be specified <b>without</b> an extension."));
226     #endif
227 
228     QFont f = Utils::smallFont(ignorePrefixesLabel->font());
229     f.setItalic(true);
230     ignorePrefixesLabel->setFont(f);
231     composerGenresLabel->setFont(f);
232     singleTracksFoldersLabel->setFont(f);
233     setMinimumSize(Utils::scaleForDpi(720), Utils::scaleForDpi(620));
234 }
235 
load()236 void InterfaceSettings::load()
237 {
238     ignorePrefixes->setText(QStringList(Settings::self()->ignorePrefixes().toList()).join(QString(constSep)));
239     composerGenres->setText(QStringList(Settings::self()->composerGenres().toList()).join(QString(constSep)));
240     singleTracksFolders->setText(QStringList(Settings::self()->singleTracksFolders().toList()).join(QString(constSep)));
241     selectEntry(cueSupport, Settings::self()->cueSupport());
242     yearTag->setCurrentIndex(Settings::self()->useOriginalYear() ? 1 : 0);
243     #ifdef ENABLE_DEVICES_SUPPORT
244     showDeleteAction->setChecked(Settings::self()->showDeleteAction());
245     #endif
246 
247     selectEntry(playQueueView, Settings::self()->playQueueView());
248     playQueueAutoExpand->setChecked(Settings::self()->playQueueAutoExpand());
249     playQueueStartClosed->setChecked(Settings::self()->playQueueStartClosed());
250     playQueueScroll->setChecked(Settings::self()->playQueueScroll());
251 
252     int pqBgnd=Settings::self()->playQueueBackground();
253     playQueueBackground_none->setChecked(pqBgnd==playQueueBackground_none->property(constValueProperty).toInt());
254     playQueueBackground_cover->setChecked(pqBgnd==playQueueBackground_cover->property(constValueProperty).toInt());
255     playQueueBackground_custom->setChecked(pqBgnd==playQueueBackground_custom->property(constValueProperty).toInt());
256     playQueueBackgroundOpacity->setValue(Settings::self()->playQueueBackgroundOpacity());
257     playQueueBackgroundBlur->setValue(Settings::self()->playQueueBackgroundBlur());
258     playQueueBackgroundFile->setText(Utils::convertPathForDisplay(Settings::self()->playQueueBackgroundFile(), false));
259 
260     playQueueConfirmClear->setChecked(Settings::self()->playQueueConfirmClear());
261     playQueueSearch->setChecked(Settings::self()->playQueueSearch());
262     playQueueViewChanged();
263     forceSingleClick->setChecked(Settings::self()->forceSingleClick());
264     infoTooltips->setChecked(Settings::self()->infoTooltips());
265     showStopButton->setChecked(Settings::self()->showStopButton());
266     showCoverWidget->setChecked(Settings::self()->showCoverWidget());
267     showRatingWidget->setChecked(Settings::self()->showRatingWidget());
268     showTechnicalInfo->setChecked(Settings::self()->showTechnicalInfo());
269     if (systemTrayCheckBox) {
270         systemTrayCheckBox->setChecked(Settings::self()->useSystemTray());
271         if (minimiseOnClose) {
272             minimiseOnClose->setChecked(Settings::self()->minimiseOnClose());
273             minimiseOnClose->setEnabled(systemTrayCheckBox->isChecked());
274         }
275         if (startupState) {
276             switch (Settings::self()->startupState()) {
277             case Settings::SS_ShowMainWindow: startupStateShow->setChecked(true); break;
278             case Settings::SS_HideMainWindow: startupStateHide->setChecked(true); break;
279             case Settings::SS_Previous: startupStateRestore->setChecked(true); break;
280             }
281 
282             enableStartupState();
283         }
284     }
285     if (systemTrayPopup) {
286         systemTrayPopup->setChecked(Settings::self()->showPopups());
287     }
288     fetchCovers->setChecked(Settings::self()->fetchCovers());
289     storeCoversInMpdDir->setChecked(Settings::self()->storeCoversInMpdDir());
290     coverFilename->setText(Settings::self()->coverFilename());
291 
292     QStringList hiddenPages=Settings::self()->hiddenPages();
293     for (int i=0; i<views->count(); ++i) {
294         QListWidgetItem *v=views->item(i);
295         v->setCheckState(hiddenPages.contains(v->data(Qt::UserRole).toString()) ? Qt::Unchecked : Qt::Checked);
296     }
297     int sidebar=Settings::self()->sidebar();
298     selectEntry(sbStyle, sidebar&FancyTabWidget::Style_Mask);
299     selectEntry(sbPosition, sidebar&FancyTabWidget::Position_Mask);
300     sbIconsOnly->setChecked(sidebar&FancyTabWidget::IconOnly);
301     sbAutoHide->setChecked(Settings::self()->splitterAutoHide());
302     sbAutoHideChanged();
303     responsiveSidebar->setChecked(Settings::self()->responsiveSidebar());
304     viewItemChanged(views->item(0));
305     setPlayQueueBackgroundOpacityLabel();
306     setPlayQueueBackgroundBlurLabel();
307     enablePlayQueueBackgroundOptions();
308     if (enableMpris) {
309         enableMpris->setChecked(Settings::self()->mpris());
310     }
311 }
312 
toSet(const QString & str)313 static QSet<QString> toSet(const QString &str)
314 {
315     QStringList parts=str.split(constSep, QString::SkipEmptyParts);
316     QSet<QString> set;
317     for (QString s: parts) {
318         set.insert(s.trimmed());
319     }
320     return set;
321 }
322 
save()323 void InterfaceSettings::save()
324 {
325     Settings::self()->saveIgnorePrefixes(toSet(ignorePrefixes->text()));
326     Settings::self()->saveComposerGenres(toSet(composerGenres->text()));
327     Settings::self()->saveSingleTracksFolders(toSet(singleTracksFolders->text()));
328     Settings::self()->saveCueSupport((MPDParseUtils::CueSupport)(cueSupport->itemData(cueSupport->currentIndex()).toInt()));
329     Settings::self()->saveUseOriginalYear(1==yearTag->currentIndex());
330     #ifdef ENABLE_DEVICES_SUPPORT
331     Settings::self()->saveShowDeleteAction(showDeleteAction->isChecked());
332     #endif
333     Settings::self()->savePlayQueueView(getValue(playQueueView));
334     Settings::self()->savePlayQueueAutoExpand(playQueueAutoExpand->isChecked());
335     Settings::self()->savePlayQueueStartClosed(playQueueStartClosed->isChecked());
336     Settings::self()->savePlayQueueScroll(playQueueScroll->isChecked());
337 
338     if (playQueueBackground_none->isChecked()) {
339         Settings::self()->savePlayQueueBackground(playQueueBackground_none->property(constValueProperty).toInt());
340     } else if (playQueueBackground_cover->isChecked()) {
341         Settings::self()->savePlayQueueBackground(playQueueBackground_cover->property(constValueProperty).toInt());
342     } else if (playQueueBackground_custom->isChecked()) {
343         Settings::self()->savePlayQueueBackground(playQueueBackground_custom->property(constValueProperty).toInt());
344     }
345     Settings::self()->savePlayQueueBackgroundOpacity(playQueueBackgroundOpacity->value());
346     Settings::self()->savePlayQueueBackgroundBlur(playQueueBackgroundBlur->value());
347     Settings::self()->savePlayQueueBackgroundFile(Utils::convertPathFromDisplay(playQueueBackgroundFile->text(), false));
348 
349     Settings::self()->savePlayQueueConfirmClear(playQueueConfirmClear->isChecked());
350     Settings::self()->savePlayQueueSearch(playQueueSearch->isChecked());
351     Settings::self()->saveForceSingleClick(forceSingleClick->isChecked());
352     Settings::self()->saveInfoTooltips(infoTooltips->isChecked());
353     Settings::self()->saveShowStopButton(showStopButton->isChecked());
354     Settings::self()->saveShowCoverWidget(showCoverWidget->isChecked());
355     Settings::self()->saveShowRatingWidget(showRatingWidget->isChecked());
356     Settings::self()->saveShowTechnicalInfo(showTechnicalInfo->isChecked());
357     Settings::self()->saveUseSystemTray(systemTrayCheckBox && systemTrayCheckBox->isChecked());
358     Settings::self()->saveShowPopups(systemTrayPopup && systemTrayPopup->isChecked());
359     Settings::self()->saveMinimiseOnClose(minimiseOnClose && minimiseOnClose->isChecked());
360     if (!startupState || startupStateShow->isChecked()) {
361         Settings::self()->saveStartupState(Settings::SS_ShowMainWindow);
362     } else if (startupStateHide->isChecked()) {
363         Settings::self()->saveStartupState(Settings::SS_HideMainWindow);
364     } else if (startupStateRestore->isChecked()) {
365         Settings::self()->saveStartupState(Settings::SS_Previous);
366     }
367     Settings::self()->saveFetchCovers(fetchCovers->isChecked());
368     Settings::self()->saveStoreCoversInMpdDir(storeCoversInMpdDir->isChecked());
369     Settings::self()->saveCoverFilename(coverFilename->text().trimmed());
370     if (loaded && lang) {
371         Settings::self()->saveLang(lang->itemData(lang->currentIndex()).toString());
372     }
373     if (loaded && styleOption) {
374         Settings::self()->saveStyle(0==styleOption->currentIndex() ? QString() : styleOption->currentText());
375     }
376     QStringList hiddenPages;
377     for (int i=0; i<views->count(); ++i) {
378         QListWidgetItem *v=views->item(i);
379         if (Qt::Unchecked==v->checkState()) {
380             hiddenPages.append(v->data(Qt::UserRole).toString());
381         }
382     }
383     Settings::self()->saveHiddenPages(hiddenPages);
384     int sidebar=getValue(sbStyle)|getValue(sbPosition);
385     if (sbIconsOnly->isChecked()) {
386         sidebar|=FancyTabWidget::IconOnly;
387     }
388     Settings::self()->saveSidebar(sidebar);
389     Settings::self()->saveSplitterAutoHide(sbAutoHide->isChecked());
390     Settings::self()->saveResponsiveSidebar(responsiveSidebar->isChecked());
391     if (enableMpris) {
392         Settings::self()->saveMpris(enableMpris->isChecked());
393     }
394 }
395 
localeAwareCompare(const QString & a,const QString & b)396 static bool localeAwareCompare(const QString &a, const QString &b)
397 {
398     return a.localeAwareCompare(b) < 0;
399 }
400 
translationCodes(const QString & dir)401 static QSet<QString> translationCodes(const QString &dir)
402 {
403     QSet<QString> codes;
404     QDir d(dir);
405     QStringList installed(d.entryList(QStringList() << "*.qm"));
406     QRegExp langRegExp("^cantata_(.*).qm$");
407     for (const QString &filename: installed) {
408         if (langRegExp.exactMatch(filename)) {
409             codes.insert(langRegExp.cap(1));
410         }
411     }
412     return codes;
413 }
414 
showEvent(QShowEvent * e)415 void InterfaceSettings::showEvent(QShowEvent *e)
416 {
417     if (!loaded) {
418         loaded=true;
419 
420         QMap<QString, QString> langMap;
421         QSet<QString> transCodes;
422 
423         transCodes+=translationCodes(qApp->applicationDirPath()+QLatin1String("/translations"));
424         transCodes+=translationCodes(QDir::currentPath()+QLatin1String("/translations"));
425         #ifndef Q_OS_WIN
426         transCodes+=translationCodes(CANTATA_SYS_TRANS_DIR);
427         #endif
428 
429         for (const QString &code: transCodes) {
430             QString langName = QLocale::languageToString(QLocale(code).language());
431             QString nativeName = QLocale(code).nativeLanguageName();
432             if (!nativeName.isEmpty()) {
433                 langName = nativeName;
434             }
435             langMap[QString("%1 (%2)").arg(langName, code)] = code;
436         }
437 
438         langMap[tr("English (en)")] = "en";
439 
440         QString current = Settings::self()->lang();
441         QStringList names = langMap.keys();
442         std::stable_sort(names.begin(), names.end(), localeAwareCompare);
443         lang->addItem(tr("System default"), QString());
444         lang->setCurrentIndex(0);
445         for (const QString &name: names) {
446             lang->addItem(name, langMap[name]);
447             if (langMap[name]==current) {
448                 lang->setCurrentIndex(lang->count()-1);
449             }
450         }
451 
452         if (lang->count()<3) {
453             REMOVE(lang)
454             REMOVE(langLabel)
455             REMOVE(langNoteLabel)
456         } else {
457             connect(lang, SIGNAL(currentIndexChanged(int)), SLOT(langChanged()));
458         }
459 
460         styleOption->addItem(tr("System default"));
461         for (const auto & key: QStyleFactory::keys()) {
462             if (!key.startsWith("bb10") && key!="gtk2") {
463                 styleOption->addItem(key);
464             }
465         }
466 
467         if (styleOption->count()<3) {
468             REMOVE(styleOption)
469             REMOVE(styleLabel)
470             REMOVE(styleNoteLabel)
471         } else {
472             QString selected = Settings::self()->style();
473             styleOption->setCurrentIndex(0);
474             if (!selected.isEmpty()) {
475                 for (int i=1; i<styleOption->count(); ++i) {
476                     if (styleOption->itemText(i) == selected) {
477                         styleOption->setCurrentIndex(i);
478                         break;
479                     }
480                 }
481             }
482             connect(styleOption, SIGNAL(currentIndexChanged(int)), SLOT(styleChanged()));
483         }
484     }
485     QWidget::showEvent(e);
486 }
487 
showPage(const QString & page)488 void InterfaceSettings::showPage(const QString &page)
489 {
490     if (QLatin1String("sidebar")==page) {
491         tabWidget->setCurrentIndex(0);
492     }
493 }
494 
sizeHint() const495 QSize InterfaceSettings::sizeHint() const
496 {
497     QSize sz=QWidget::sizeHint();
498     #ifdef Q_OS_MAC
499     sz.setWidth(sz.width()+32);
500     sz.setHeight(qMin(sz.height(), 500));
501     #endif
502     return sz;
503 }
504 
addView(const QString & v,const QString & prop)505 void InterfaceSettings::addView(const QString &v, const QString &prop)
506 {
507     QListWidgetItem *item=new QListWidgetItem(v, views);
508     item->setCheckState(Qt::Unchecked);
509     item->setData(Qt::UserRole, prop);
510 }
511 
playQueueViewChanged()512 void InterfaceSettings::playQueueViewChanged()
513 {
514     bool grouped=ItemView::Mode_GroupedTree==getValue(playQueueView);
515     playQueueAutoExpand->setEnabled(grouped);
516     playQueueStartClosed->setEnabled(grouped);
517 }
518 
forceSingleClickChanged()519 void InterfaceSettings::forceSingleClickChanged()
520 {
521     singleClickLabel->setOn(forceSingleClick->isChecked()!=Settings::self()->forceSingleClick());
522 }
523 
enableStartupState()524 void InterfaceSettings::enableStartupState()
525 {
526     if (systemTrayCheckBox && minimiseOnClose && startupState) {
527         startupState->setEnabled(systemTrayCheckBox->isChecked() && minimiseOnClose->isChecked());
528     }
529 }
530 
langChanged()531 void InterfaceSettings::langChanged()
532 {
533     langNoteLabel->setOn(lang->itemData(lang->currentIndex()).toString()!=Settings::self()->lang());
534 }
535 
styleChanged()536 void InterfaceSettings::styleChanged()
537 {
538     QString st = 0==styleOption->currentIndex() ? QString() : styleOption->currentText();
539     styleNoteLabel->setOn(st!=Settings::self()->style());
540 }
541 
viewItemChanged(QListWidgetItem * changedItem)542 void InterfaceSettings::viewItemChanged(QListWidgetItem *changedItem)
543 {
544     // If this is the playqueue that has been toggled, then control auto-hide
545     // i.e. can't auto-hide if playqueue is in sidebar
546     if (Qt::Checked==changedItem->checkState() && changedItem==views->item(0)) {
547         sbAutoHide->setChecked(false);
548     }
549 
550     // Ensure we have at least 1 view checked...
551     for (int i=0; i<views->count(); ++i) {
552         QListWidgetItem *v=views->item(i);
553         if (Qt::Checked==v->checkState()) {
554             return;
555         }
556     }
557 
558     views->item(1)->setCheckState(Qt::Checked);
559 }
560 
sbAutoHideChanged()561 void InterfaceSettings::sbAutoHideChanged()
562 {
563     if (sbAutoHide->isChecked()) {
564         views->item(0)->setCheckState(Qt::Unchecked);
565     }
566 }
567 
setPlayQueueBackgroundOpacityLabel()568 void InterfaceSettings::setPlayQueueBackgroundOpacityLabel()
569 {
570     playQueueBackgroundOpacityLabel->setText(tr("%1%", "value%").arg(playQueueBackgroundOpacity->value()));
571 }
572 
setPlayQueueBackgroundBlurLabel()573 void InterfaceSettings::setPlayQueueBackgroundBlurLabel()
574 {
575     playQueueBackgroundBlurLabel->setText(tr("%1 px", "pixels").arg(playQueueBackgroundBlur->value()));
576 }
577 
enablePlayQueueBackgroundOptions()578 void InterfaceSettings::enablePlayQueueBackgroundOptions()
579 {
580     playQueueBackgroundOpacity->setEnabled(!playQueueBackground_none->isChecked());
581     playQueueBackgroundOpacityLabel->setEnabled(playQueueBackgroundOpacity->isEnabled());
582     playQueueBackgroundBlur->setEnabled(playQueueBackgroundOpacity->isEnabled());
583     playQueueBackgroundBlurLabel->setEnabled(playQueueBackgroundOpacity->isEnabled());
584 }
585 
systemTrayCheckBoxToggled()586 void InterfaceSettings::systemTrayCheckBoxToggled()
587 {
588     if (systemTrayCheckBox && systemTrayPopup && !systemTrayCheckBox->isChecked()) {
589         systemTrayPopup->setChecked(false);
590     }
591 }
592 
systemTrayPopupToggled()593 void InterfaceSettings::systemTrayPopupToggled()
594 {
595     if (systemTrayCheckBox && systemTrayPopup && systemTrayPopup->isChecked()) {
596         systemTrayCheckBox->setChecked(true);
597     }
598 }
599 
storeCoversInMpdDirToggled()600 void InterfaceSettings::storeCoversInMpdDirToggled()
601 {
602     storeCoversInMpdDirLabel->setOn(storeCoversInMpdDir->isChecked() && storeCoversInMpdDir->isChecked()!=Settings::self()->storeCoversInMpdDir());
603 }
604 
605 #include "moc_interfacesettings.cpp"
606