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 "settings.h"
25 #include "models/sqllibrarymodel.h"
26 #include "support/fancytabwidget.h"
27 #include "widgets/itemview.h"
28 #include "mpd-interface/mpdparseutils.h"
29 #include "support/utils.h"
30 #include "support/globalstatic.h"
31 #include "db/librarydb.h"
32 #include <QFile>
33 #include <QDir>
34 #include <qglobal.h>
35 
36 GLOBAL_STATIC(Settings, instance)
37 
38 struct MpdDefaults
39 {
MpdDefaultsMpdDefaults40     MpdDefaults()
41         : host("localhost")
42         , dir("/var/lib/mpd/music/")
43         , port(6600) {
44     }
45 
getValMpdDefaults46     static QString getVal(const QString &line) {
47         QStringList parts=line.split('\"');
48         return parts.count()>1 ? parts[1] : QString();
49     }
50 
51     enum Details {
52         DT_DIR    = 0x01,
53         DT_ADDR   = 0x02,
54         DT_PORT   = 0x04,
55         DT_PASSWD = 0x08,
56 
57         DT_ALL    = DT_DIR|DT_ADDR|DT_PORT|DT_PASSWD
58     };
59 
readMpdDefaults60     void read() {
61         QFile f("/etc/mpd.conf");
62 
63         if (f.open(QIODevice::ReadOnly|QIODevice::Text)) {
64             int details=0;
65             while (!f.atEnd()) {
66                 QString line = QString::fromUtf8(f.readLine()).trimmed();
67                 if (line.startsWith('#')) {
68                     continue;
69                 } else if (!(details&DT_DIR) && line.startsWith(QLatin1String("music_directory"))) {
70                     QString val=getVal(line);
71                     if (!val.isEmpty() && QDir(val).exists()) {
72                         dir=Utils::fixPath(val);
73                         details|=DT_DIR;
74                     }
75                 } else if (!(details&DT_ADDR) && line.startsWith(QLatin1String("bind_to_address"))) {
76                     QString val=getVal(line);
77                     if (!val.isEmpty() && val!=QLatin1String("any")) {
78                         host=val;
79                         details|=DT_ADDR;
80                     }
81                 } else if (!(details&DT_PORT) && line.startsWith(QLatin1String("port"))) {
82                     int val=getVal(line).toInt();
83                     if (val>0) {
84                         port=val;
85                         details|=DT_PORT;
86                     }
87                 } else if (!(details&DT_PASSWD) && line.startsWith(QLatin1String("password"))) {
88                     QString val=getVal(line);
89                     if (!val.isEmpty()) {
90                         QStringList parts=val.split('@');
91                         if (!parts.isEmpty()) {
92                             passwd=parts[0];
93                             details|=DT_PASSWD;
94                         }
95                     }
96                 }
97                 if (details==DT_ALL) {
98                     break;
99                 }
100             }
101         }
102     }
103 
104     QString host;
105     QString dir;
106     QString passwd;
107     int port;
108 };
109 
110 static MpdDefaults mpdDefaults;
111 
getStartupStateStr(Settings::StartupState s)112 static QString getStartupStateStr(Settings::StartupState s)
113 {
114     switch (s) {
115     case Settings::SS_ShowMainWindow: return QLatin1String("show");
116     case Settings::SS_HideMainWindow: return QLatin1String("hide");
117     default:
118     case Settings::SS_Previous: return QLatin1String("prev");
119     }
120 }
121 
getStartupState(const QString & str)122 static Settings::StartupState getStartupState(const QString &str)
123 {
124     for (int i=0; i<=Settings::SS_Previous; ++i) {
125         if (getStartupStateStr((Settings::StartupState)i)==str) {
126             return (Settings::StartupState)i;
127         }
128     }
129     return Settings::SS_Previous;
130 }
131 
Settings()132 Settings::Settings()
133     : state(AP_Configured)
134     , ver(-1)
135 {
136     // Call 'version' so that it initialises 'ver' and 'state'
137     version();
138     // Only need to read system defaults if we have not previously been configured...
139     if (!cfg.hasGroup(MPDConnectionDetails::configGroupName())) {
140         mpdDefaults.read();
141     }
142 }
143 
~Settings()144 Settings::~Settings()
145 {
146     save();
147 }
148 
currentConnection()149 QString Settings::currentConnection()
150 {
151     return cfg.get("currentConnection", QString());
152 }
153 
connectionDetails(const QString & name)154 MPDConnectionDetails Settings::connectionDetails(const QString &name)
155 {
156     MPDConnectionDetails details;
157     QString n=MPDConnectionDetails::configGroupName(name);
158     details.name=name;
159     if (!cfg.hasGroup(n)) {
160         details.name=QString();
161         n=MPDConnectionDetails::configGroupName(details.name);
162     }
163     if (cfg.hasGroup(n)) {
164         Configuration grp(n);
165         details.hostname=grp.get("host", name.isEmpty() ? mpdDefaults.host : QString());
166         details.port=grp.get("port", name.isEmpty() ? mpdDefaults.port : 6600);
167         details.dir=grp.getDirPath("dir", name.isEmpty() ? mpdDefaults.dir : "/var/lib/mpd/music");
168         details.password=grp.get("passwd", name.isEmpty() ? mpdDefaults.passwd : QString());
169         #ifdef ENABLE_HTTP_STREAM_PLAYBACK
170         details.streamUrl=grp.get("streamUrl", QString());
171         #endif
172         details.replayGain=grp.get("replayGain", QString());
173         details.applyReplayGain=grp.get("applyReplayGain", true);
174         // if the setting hasn't been set before, we set it to true to allow
175         // for easy migration of existing settings
176         details.allowLocalStreaming=grp.get("allowLocalStreaming", true);
177         details.autoUpdate=grp.get("autoUpdate", false);
178     } else {
179         details.hostname=mpdDefaults.host;
180         details.port=mpdDefaults.port;
181         details.dir=mpdDefaults.dir;
182         details.password=mpdDefaults.passwd;
183         #ifdef ENABLE_HTTP_STREAM_PLAYBACK
184         details.streamUrl=QString();
185         #endif
186         details.applyReplayGain=true;
187         details.allowLocalStreaming=true;
188         details.autoUpdate=false;
189     }
190     details.setDirReadable();
191     return details;
192 }
193 
allConnections()194 QList<MPDConnectionDetails> Settings::allConnections()
195 {
196     QStringList groups=cfg.childGroups();
197     QList<MPDConnectionDetails> connections;
198     for (const QString &grp: groups) {
199         if (cfg.hasGroup(grp) && grp.startsWith("Connection")) {
200             connections.append(connectionDetails(grp=="Connection" ? QString() : grp.mid(11)));
201         }
202     }
203 
204     if (connections.isEmpty()) {
205         // If we are empty, add at lease the default connection...
206         connections.append(connectionDetails());
207     }
208     return connections;
209 }
210 
showPlaylist()211 bool Settings::showPlaylist()
212 {
213     return cfg.get("showPlaylist", true);
214 }
215 
showFullScreen()216 bool Settings::showFullScreen()
217 {
218     return cfg.get("showFullScreen", false);
219 }
220 
headerState(const QString & key)221 QByteArray Settings::headerState(const QString &key)
222 {
223     if (version()<CANTATA_MAKE_VERSION(1, 2, 54)) {
224         return QByteArray();
225     }
226     return cfg.get(key+"HeaderState", QByteArray());
227 }
228 
splitterState()229 QByteArray Settings::splitterState()
230 {
231     return cfg.get("splitterState", QByteArray());
232 }
233 
splitterAutoHide()234 bool Settings::splitterAutoHide()
235 {
236     return cfg.get("splitterAutoHide", false);
237 }
238 
mainWindowSize()239 QSize Settings::mainWindowSize()
240 {
241     return cfg.get("mainWindowSize", QSize());
242 }
243 
mainWindowCollapsedSize()244 QSize Settings::mainWindowCollapsedSize()
245 {
246     return cfg.get("mainWindowCollapsedSize", QSize());
247 }
248 
maximized()249 bool Settings::maximized()
250 {
251     return cfg.get("maximized", false);
252 }
253 
useSystemTray()254 bool Settings::useSystemTray()
255 {
256     return cfg.get("useSystemTray", false);
257 }
258 
minimiseOnClose()259 bool Settings::minimiseOnClose()
260 {
261     return cfg.get("minimiseOnClose", true);
262 }
263 
showPopups()264 bool Settings::showPopups()
265 {
266     return cfg.get("showPopups", false);
267 }
268 
stopOnExit()269 bool Settings::stopOnExit()
270 {
271     return cfg.get("stopOnExit", false);
272 }
273 
storeCoversInMpdDir()274 bool Settings::storeCoversInMpdDir()
275 {
276     return cfg.get("storeCoversInMpdDir", false);
277 }
278 
storeLyricsInMpdDir()279 bool Settings::storeLyricsInMpdDir()
280 {
281     return cfg.get("storeLyricsInMpdDir", false);
282 }
283 
coverFilename()284 QString Settings::coverFilename()
285 {
286     QString name=cfg.get("coverFilename", QString());
287     // name is empty, so for old configs try to get from MPD settings
288     if (name.isEmpty() && version()<CANTATA_MAKE_VERSION(2, 2, 51)) {
289         QStringList groups=cfg.childGroups();
290         QList<MPDConnectionDetails> connections;
291         for (const QString &grp: groups) {
292             if (cfg.hasGroup(grp) && grp.startsWith("Connection")) {
293                 Configuration cfg(grp);
294                 name=cfg.get("coverName", QString());
295                 if (!name.isEmpty()) {
296                     // Use 1st non-empty
297                     saveCoverFilename(name);
298                     return name;
299                 }
300             }
301         }
302     }
303     return name;
304 }
305 
sidebar()306 int Settings::sidebar()
307 {
308     if (version()<CANTATA_MAKE_VERSION(1, 2, 52)) {
309         return (int)(FancyTabWidget::Side|FancyTabWidget::Large);
310     } else {
311         return cfg.get("sidebar", (int)(FancyTabWidget::Side|FancyTabWidget::Large))&FancyTabWidget::All_Mask;
312     }
313 }
314 
composerGenres()315 QSet<QString> Settings::composerGenres()
316 {
317     return cfg.get("composerGenres", Song::composerGenres().toList()).toSet();
318 }
319 
singleTracksFolders()320 QSet<QString> Settings::singleTracksFolders()
321 {
322     return cfg.get("singleTracksFolders", QStringList()).toSet();
323 }
324 
cueSupport()325 MPDParseUtils::CueSupport Settings::cueSupport()
326 {
327     return MPDParseUtils::toCueSupport(cfg.get("cueSupport", MPDParseUtils::toStr(MPDParseUtils::Cue_Parse)));
328 }
329 
lyricProviders()330 QStringList Settings::lyricProviders()
331 {
332     return cfg.get("lyricProviders", QStringList() << "azlyrics.com" << "chartlyrics.com" << "lyrics.wikia.com");
333 }
334 
wikipediaLangs()335 QStringList Settings::wikipediaLangs()
336 {
337     return cfg.get("wikipediaLangs", QStringList() << "en:en");
338 }
339 
wikipediaIntroOnly()340 bool Settings::wikipediaIntroOnly()
341 {
342     return cfg.get("wikipediaIntroOnly", true);
343 }
344 
contextBackdrop()345 int Settings::contextBackdrop()
346 {
347     return getBoolAsInt("contextBackdrop", 0);
348 }
349 
contextBackdropOpacity()350 int Settings::contextBackdropOpacity()
351 {
352     return cfg.get("contextBackdropOpacity", 15, 0, 100);
353 }
354 
contextBackdropBlur()355 int Settings::contextBackdropBlur()
356 {
357     return cfg.get("contextBackdropBlur", 0, 0, 20);
358 }
359 
contextBackdropFile()360 QString Settings::contextBackdropFile()
361 {
362     return cfg.getFilePath("contextBackdropFile", QString());
363 }
364 
contextDarkBackground()365 bool Settings::contextDarkBackground()
366 {
367     return cfg.get("contextDarkBackground", false);
368 }
369 
contextZoom()370 int Settings::contextZoom()
371 {
372     return cfg.get("contextZoom", 0);
373 }
374 
contextSlimPage()375 QString Settings::contextSlimPage()
376 {
377     return cfg.get("contextSlimPage", QString());
378 }
379 
contextSplitterState()380 QByteArray Settings::contextSplitterState()
381 {
382     return version()<CANTATA_MAKE_VERSION(1, 3, 51) ? QByteArray() : cfg.get("contextSplitterState", QByteArray());
383 }
384 
contextAlwaysCollapsed()385 bool Settings::contextAlwaysCollapsed()
386 {
387     return cfg.get("contextAlwaysCollapsed", false);
388 }
389 
contextSwitchTime()390 int Settings::contextSwitchTime()
391 {
392     return cfg.get("contextSwitchTime", 0, 0, 5000);
393 }
394 
contextAutoScroll()395 bool Settings::contextAutoScroll()
396 {
397     return cfg.get("contextAutoScroll", false);
398 }
399 
contextTrackView()400 int Settings::contextTrackView()
401 {
402     return cfg.get("contextTrackView", 0);
403 }
404 
page()405 QString Settings::page()
406 {
407     return cfg.get("page", QString());
408 }
409 
hiddenPages()410 QStringList Settings::hiddenPages()
411 {
412     QStringList config=cfg.get("hiddenPages", QStringList() << "PlayQueuePage" << "ContextPage");
413     // If splitter auto-hide is enabled, then playqueue cannot be in sidebar!
414     if (splitterAutoHide() && !config.contains("PlayQueuePage")) {
415         config << "PlayQueuePage";
416     }
417     return config;
418 }
419 
420 #ifdef ENABLE_DEVICES_SUPPORT
overwriteSongs()421 bool Settings::overwriteSongs()
422 {
423     return cfg.get("overwriteSongs", false);
424 }
425 
showDeleteAction()426 bool Settings::showDeleteAction()
427 {
428     return cfg.get("showDeleteAction", false);
429 }
430 #endif
431 
version()432 int Settings::version()
433 {
434     if (-1==ver) {
435         state=cfg.hasEntry("version") ? AP_Configured : AP_FirstRun;
436         QStringList parts=cfg.get("version", QLatin1String(PACKAGE_VERSION_STRING)).split('.');
437         if (3==parts.size()) {
438             ver=CANTATA_MAKE_VERSION(parts.at(0).toInt(), parts.at(1).toInt(), parts.at(2).toInt());
439         } else {
440             ver=PACKAGE_VERSION;
441             cfg.set("version", PACKAGE_VERSION_STRING);
442         }
443     }
444     return ver;
445 }
446 
stopFadeDuration()447 int Settings::stopFadeDuration()
448 {
449     return cfg.get("stopFadeDuration", (int)MPDConnection::DefaultFade, (int)MPDConnection::MinFade, (int)MPDConnection::MaxFade);
450 }
451 
httpAllocatedPort()452 int Settings::httpAllocatedPort()
453 {
454     return cfg.get("httpAllocatedPort", 0);
455 }
456 
httpInterface()457 QString Settings::httpInterface()
458 {
459     return cfg.get("httpInterface", QString());
460 }
461 
playQueueView()462 int Settings::playQueueView()
463 {
464     if (version()<CANTATA_MAKE_VERSION(1, 3, 53)) {
465         return cfg.get("playQueueGrouped", true) ? ItemView::Mode_GroupedTree : ItemView::Mode_Table;
466     }
467     return ItemView::toMode(cfg.get("playQueueView", ItemView::modeStr(ItemView::Mode_GroupedTree)));
468 }
469 
playQueueAutoExpand()470 bool Settings::playQueueAutoExpand()
471 {
472     return cfg.get("playQueueAutoExpand", true);
473 }
474 
playQueueStartClosed()475 bool Settings::playQueueStartClosed()
476 {
477     return cfg.get("playQueueStartClosed", false);
478 }
479 
playQueueScroll()480 bool Settings::playQueueScroll()
481 {
482     return cfg.get("playQueueScroll", true);
483 }
484 
playQueueBackground()485 int Settings::playQueueBackground()
486 {
487     return getBoolAsInt("playQueueBackground", 0);
488 }
489 
playQueueBackgroundOpacity()490 int Settings::playQueueBackgroundOpacity()
491 {
492     return cfg.get("playQueueBackgroundOpacity", 15, 0, 100);
493 }
494 
playQueueBackgroundBlur()495 int Settings::playQueueBackgroundBlur()
496 {
497     return cfg.get("playQueueBackgroundBlur", 0, 0, 20);
498 }
499 
playQueueBackgroundFile()500 QString Settings::playQueueBackgroundFile()
501 {
502     return cfg.getFilePath("playQueueBackgroundFile", QString());
503 }
504 
playQueueConfirmClear()505 bool Settings::playQueueConfirmClear()
506 {
507     return cfg.get("playQueueConfirmClear", false);
508 }
509 
playQueueSearch()510 bool Settings::playQueueSearch()
511 {
512     return cfg.get("playQueueSearch", true);
513 }
514 
playListsStartClosed()515 bool Settings::playListsStartClosed()
516 {
517     return cfg.get("playListsStartClosed", true);
518 }
519 
520 #ifdef ENABLE_HTTP_STREAM_PLAYBACK
playStream()521 bool Settings::playStream()
522 {
523     return cfg.get("playStream", false);
524 }
525 #endif
526 
527 #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
cdAuto()528 bool Settings::cdAuto()
529 {
530     return cfg.get("cdAuto", true);
531 }
532 
paranoiaFull()533 bool Settings::paranoiaFull()
534 {
535     return cfg.get("paranoiaFull", true);
536 }
537 
paranoiaNeverSkip()538 bool Settings::paranoiaNeverSkip()
539 {
540     return cfg.get("paranoiaNeverSkip", true);
541 }
542 
paranoiaOffset()543 int Settings::paranoiaOffset()
544 {
545     return cfg.get("paranoiaOffset", 0);
546 }
547 #endif
548 
549 #if defined CDDB_FOUND && defined MUSICBRAINZ5_FOUND
useCddb()550 bool Settings::useCddb()
551 {
552     return cfg.get("useCddb", true);
553 }
554 #endif
555 
556 #ifdef CDDB_FOUND
cddbHost()557 QString Settings::cddbHost()
558 {
559     return cfg.get("cddbHost", QString("gnudb.gnudb.org"));
560 }
561 
cddbPort()562 int Settings::cddbPort()
563 {
564     return cfg.get("cddbPort", 80);
565 }
566 #endif
567 
forceSingleClick()568 bool Settings::forceSingleClick()
569 {
570     return cfg.get("forceSingleClick", true);
571 }
572 
startHidden()573 bool Settings::startHidden()
574 {
575     return useSystemTray() ? cfg.get("startHidden", false) : false;
576 }
577 
showTimeRemaining()578 bool Settings::showTimeRemaining()
579 {
580     return cfg.get("showTimeRemaining", false);
581 }
582 
hiddenStreamCategories()583 QStringList Settings::hiddenStreamCategories()
584 {
585     return cfg.get("hiddenStreamCategories", QStringList());
586 }
587 
hiddenOnlineProviders()588 QStringList Settings::hiddenOnlineProviders()
589 {
590     return cfg.get("hiddenOnlineProviders", QStringList());
591 }
592 
593 #if (defined Q_OS_LINUX && defined QT_QTDBUS_FOUND) || (defined Q_OS_MAC && defined IOKIT_FOUND)
inhibitSuspend()594 bool Settings::inhibitSuspend()
595 {
596     return cfg.get("inhibitSuspend", false);
597 }
598 #endif
599 
rssUpdate()600 int Settings::rssUpdate()
601 {
602     return cfg.get("rssUpdate", 0, 0, 7*24*60);
603 }
604 
lastRssUpdate()605 QDateTime Settings::lastRssUpdate()
606 {
607     return cfg.get("lastRssUpdate", QDateTime());
608 }
609 
podcastDownloadPath()610 QString Settings::podcastDownloadPath()
611 {
612     return Utils::fixPath(cfg.get("podcastDownloadPath", Utils::fixPath(QDir::homePath())+QLatin1String("Podcasts/")));
613 }
614 
podcastAutoDownloadLimit()615 int Settings::podcastAutoDownloadLimit()
616 {
617     if (cfg.hasEntry("podcastAutoDownload")) {
618         return cfg.get("podcastAutoDownload", false) ? 1000 : 0;
619     }
620     return cfg.get("podcastAutoDownloadLimit", 0, 0, 1000);
621 }
622 
volumeStep()623 int Settings::volumeStep()
624 {
625     return cfg.get("volumeStep", 5, 1, 20);
626 }
627 
startupState()628 Settings::StartupState Settings::startupState()
629 {
630     return getStartupState(cfg.get("startupState", getStartupStateStr(SS_Previous)));
631 }
632 
searchCategory()633 QString Settings::searchCategory()
634 {
635     return cfg.get("searchCategory", QString());
636 }
637 
fetchCovers()638 bool Settings::fetchCovers()
639 {
640     return cfg.get("fetchCovers", true);
641 }
642 
lang()643 QString Settings::lang()
644 {
645     return cfg.get("lang", QString());
646 }
647 
showCoverWidget()648 bool Settings::showCoverWidget()
649 {
650     return cfg.get("showCoverWidget", true);
651 }
652 
showStopButton()653 bool Settings::showStopButton()
654 {
655     return cfg.get("showStopButton", false);
656 }
657 
showRatingWidget()658 bool Settings::showRatingWidget()
659 {
660     return cfg.get("showRatingWidget", false);
661 }
662 
showTechnicalInfo()663 bool Settings::showTechnicalInfo()
664 {
665     return cfg.get("showTechnicalInfo", false);
666 }
667 
infoTooltips()668 bool Settings::infoTooltips()
669 {
670     return cfg.get("infoTooltips", true);
671 }
672 
ignorePrefixes()673 QSet<QString> Settings::ignorePrefixes()
674 {
675     return cfg.get("ignorePrefixes", Song::ignorePrefixes().toList()).toSet();
676 }
677 
mpris()678 bool Settings::mpris()
679 {
680     return cfg.get("mpris", true);
681 }
682 
style()683 QString Settings::style()
684 {
685     return cfg.get("style", QString());
686 }
687 
688 #if !defined Q_OS_WIN && !defined Q_OS_MAC
showMenubar()689 bool Settings::showMenubar()
690 {
691     return cfg.get("showMenubar", false);
692 }
693 #endif
694 
useOriginalYear()695 bool Settings::useOriginalYear()
696 {
697     return cfg.get("useOriginalYear", false);
698 }
699 
responsiveSidebar()700 bool Settings::responsiveSidebar()
701 {
702     return cfg.get("responsiveSidebar", true);
703 }
704 
removeConnectionDetails(const QString & v)705 void Settings::removeConnectionDetails(const QString &v)
706 {
707     if (v==currentConnection()) {
708         saveCurrentConnection(QString());
709     }
710     cfg.removeGroup(MPDConnectionDetails::configGroupName(v));
711 }
712 
saveConnectionDetails(const MPDConnectionDetails & v)713 void Settings::saveConnectionDetails(const MPDConnectionDetails &v)
714 {
715     if (v.name.isEmpty()) {
716         cfg.removeEntry("connectionHost");
717         cfg.removeEntry("connectionPasswd");
718         cfg.removeEntry("connectionPort");
719         cfg.removeEntry("mpdDir");
720     }
721 
722     QString n=MPDConnectionDetails::configGroupName(v.name);
723     Configuration grp(n);
724     grp.set("host", v.hostname);
725     grp.set("port", (int)v.port);
726     if (v.dir.startsWith("http:", Qt::CaseInsensitive) || v.dir.startsWith("https:", Qt::CaseInsensitive)) {
727         grp.set("dir", v.dir);
728     } else {
729         grp.setDirPath("dir", v.dir);
730     }
731     grp.set("passwd", v.password);
732     #ifdef ENABLE_HTTP_STREAM_PLAYBACK
733     grp.set("streamUrl", v.streamUrl);
734     #endif
735     grp.set("applyReplayGain", v.applyReplayGain);
736     grp.set("allowLocalStreaming", v.allowLocalStreaming);
737     grp.set("autoUpdate", v.autoUpdate);
738 }
739 
saveCurrentConnection(const QString & v)740 void Settings::saveCurrentConnection(const QString &v)
741 {
742     cfg.set("currentConnection", v);
743 }
744 
saveShowFullScreen(bool v)745 void Settings::saveShowFullScreen(bool v)
746 {
747     cfg.set("showFullScreen", v);
748 }
749 
saveShowPlaylist(bool v)750 void Settings::saveShowPlaylist(bool v)
751 {
752     cfg.set("showPlaylist", v);
753 }
754 
saveHeaderState(const QString & key,const QByteArray & v)755 void Settings::saveHeaderState(const QString &key, const QByteArray &v)
756 {
757     cfg.set(key+"HeaderState", v);
758 }
759 
saveSplitterState(const QByteArray & v)760 void Settings::saveSplitterState(const QByteArray &v)
761 {
762     cfg.set("splitterState", v);
763 }
764 
saveSplitterAutoHide(bool v)765 void Settings::saveSplitterAutoHide(bool v)
766 {
767     cfg.set("splitterAutoHide", v);
768 }
769 
saveMainWindowSize(const QSize & v)770 void Settings::saveMainWindowSize(const QSize &v)
771 {
772     cfg.set("mainWindowSize", v);
773 }
774 
saveMaximized(bool v)775 void Settings::saveMaximized(bool v)
776 {
777     cfg.set("maximized", v);
778 }
779 
saveMainWindowCollapsedSize(const QSize & v)780 void Settings::saveMainWindowCollapsedSize(const QSize &v)
781 {
782     if (v.width()>16 && v.height()>16) {
783         cfg.set("mainWindowCollapsedSize", v);
784     }
785 }
786 
saveUseSystemTray(bool v)787 void Settings::saveUseSystemTray(bool v)
788 {
789     cfg.set("useSystemTray", v);
790 }
791 
saveMinimiseOnClose(bool v)792 void Settings::saveMinimiseOnClose(bool v)
793 {
794     cfg.set("minimiseOnClose", v);
795 }
796 
saveShowPopups(bool v)797 void Settings::saveShowPopups(bool v)
798 {
799     cfg.set("showPopups", v);
800 }
801 
saveStopOnExit(bool v)802 void Settings::saveStopOnExit(bool v)
803 {
804     cfg.set("stopOnExit", v);
805 }
806 
saveStoreCoversInMpdDir(bool v)807 void Settings::saveStoreCoversInMpdDir(bool v)
808 {
809     cfg.set("storeCoversInMpdDir", v);
810 }
811 
saveStoreLyricsInMpdDir(bool v)812 void Settings::saveStoreLyricsInMpdDir(bool v)
813 {
814     cfg.set("storeLyricsInMpdDir", v);
815 }
816 
saveCoverFilename(const QString & v)817 void Settings::saveCoverFilename(const QString &v)
818 {
819     cfg.set("coverFilename", v);
820 }
821 
saveSidebar(int v)822 void Settings::saveSidebar(int v)
823 {
824     cfg.set("sidebar", v);
825 }
826 
saveComposerGenres(const QSet<QString> & v)827 void Settings::saveComposerGenres(const QSet<QString> &v)
828 {
829     cfg.set("composerGenres", v.toList());
830 }
831 
saveSingleTracksFolders(const QSet<QString> & v)832 void Settings::saveSingleTracksFolders(const QSet<QString> &v)
833 {
834     cfg.set("singleTracksFolders", v.toList());
835 }
836 
saveCueSupport(MPDParseUtils::CueSupport v)837 void Settings::saveCueSupport(MPDParseUtils::CueSupport v)
838 {
839     cfg.set("cueSupport", MPDParseUtils::toStr(v));
840 }
841 
saveLyricProviders(const QStringList & v)842 void Settings::saveLyricProviders(const QStringList &v)
843 {
844     cfg.set("lyricProviders", v);
845 }
846 
saveWikipediaLangs(const QStringList & v)847 void Settings::saveWikipediaLangs(const QStringList &v)
848 {
849     cfg.set("wikipediaLangs", v);
850 }
851 
saveWikipediaIntroOnly(bool v)852 void Settings::saveWikipediaIntroOnly(bool v)
853 {
854     cfg.set("wikipediaIntroOnly", v);
855 }
856 
saveContextBackdrop(int v)857 void Settings::saveContextBackdrop(int v)
858 {
859     cfg.set("contextBackdrop", v);
860 }
861 
saveContextBackdropOpacity(int v)862 void Settings::saveContextBackdropOpacity(int v)
863 {
864     cfg.set("contextBackdropOpacity", v);
865 }
866 
saveContextBackdropBlur(int v)867 void Settings::saveContextBackdropBlur(int v)
868 {
869     cfg.set("contextBackdropBlur", v);
870 }
871 
saveContextBackdropFile(const QString & v)872 void Settings::saveContextBackdropFile(const QString &v)
873 {
874     cfg.setFilePath("contextBackdropFile", v);
875 }
876 
saveContextDarkBackground(bool v)877 void Settings::saveContextDarkBackground(bool v)
878 {
879     cfg.set("contextDarkBackground", v);
880 }
881 
saveContextZoom(int v)882 void Settings::saveContextZoom(int v)
883 {
884     cfg.set("contextZoom", v);
885 }
886 
saveContextSlimPage(const QString & v)887 void Settings::saveContextSlimPage(const QString &v)
888 {
889     cfg.set("contextSlimPage", v);
890 }
891 
saveContextSplitterState(const QByteArray & v)892 void Settings::saveContextSplitterState(const QByteArray &v)
893 {
894     cfg.set("contextSplitterState", v);
895 }
896 
saveContextAlwaysCollapsed(bool v)897 void Settings::saveContextAlwaysCollapsed(bool v)
898 {
899     cfg.set("contextAlwaysCollapsed", v);
900 }
901 
saveContextSwitchTime(int v)902 void Settings::saveContextSwitchTime(int v)
903 {
904     cfg.set("contextSwitchTime", v);
905 }
906 
saveContextAutoScroll(bool v)907 void Settings::saveContextAutoScroll(bool v)
908 {
909     cfg.set("contextAutoScroll", v);
910 }
911 
saveContextTrackView(int v)912 void Settings::saveContextTrackView(int v)
913 {
914     cfg.set("contextTrackView", v);
915 }
916 
savePage(const QString & v)917 void Settings::savePage(const QString &v)
918 {
919     cfg.set("page", v);
920 }
921 
saveHiddenPages(const QStringList & v)922 void Settings::saveHiddenPages(const QStringList &v)
923 {
924     cfg.set("hiddenPages", v);
925 }
926 
927 #ifdef ENABLE_DEVICES_SUPPORT
saveOverwriteSongs(bool v)928 void Settings::saveOverwriteSongs(bool v)
929 {
930     cfg.set("overwriteSongs", v);
931 }
932 
saveShowDeleteAction(bool v)933 void Settings::saveShowDeleteAction(bool v)
934 {
935     cfg.set("showDeleteAction", v);
936 }
937 #endif
938 
saveStopFadeDuration(int v)939 void Settings::saveStopFadeDuration(int v)
940 {
941     cfg.set("stopFadeDuration", v);
942 }
943 
saveHttpAllocatedPort(int v)944 void Settings::saveHttpAllocatedPort(int v)
945 {
946     cfg.set("httpAllocatedPort", v);
947 }
948 
saveHttpInterface(const QString & v)949 void Settings::saveHttpInterface(const QString &v)
950 {
951     cfg.set("httpInterface", v);
952 }
953 
savePlayQueueView(int v)954 void Settings::savePlayQueueView(int v)
955 {
956     cfg.set("playQueueView", ItemView::modeStr((ItemView::Mode)v));
957 }
958 
savePlayQueueAutoExpand(bool v)959 void Settings::savePlayQueueAutoExpand(bool v)
960 {
961     cfg.set("playQueueAutoExpand", v);
962 }
963 
savePlayQueueStartClosed(bool v)964 void Settings::savePlayQueueStartClosed(bool v)
965 {
966     cfg.set("playQueueStartClosed", v);
967 }
968 
savePlayQueueScroll(bool v)969 void Settings::savePlayQueueScroll(bool v)
970 {
971     cfg.set("playQueueScroll", v);
972 }
973 
savePlayQueueBackground(int v)974 void Settings::savePlayQueueBackground(int v)
975 {
976     cfg.set("playQueueBackground", v);
977 }
978 
savePlayQueueBackgroundOpacity(int v)979 void Settings::savePlayQueueBackgroundOpacity(int v)
980 {
981     cfg.set("playQueueBackgroundOpacity", v);
982 }
983 
savePlayQueueBackgroundBlur(int v)984 void Settings::savePlayQueueBackgroundBlur(int v)
985 {
986     cfg.set("playQueueBackgroundBlur", v);
987 }
988 
savePlayQueueBackgroundFile(const QString & v)989 void Settings::savePlayQueueBackgroundFile(const QString &v)
990 {
991     cfg.setFilePath("playQueueBackgroundFile", v);
992 }
993 
savePlayQueueConfirmClear(bool v)994 void Settings::savePlayQueueConfirmClear(bool v)
995 {
996     cfg.set("playQueueConfirmClear", v);
997 }
998 
savePlayQueueSearch(bool v)999 void Settings::savePlayQueueSearch(bool v)
1000 {
1001     cfg.set("playQueueSearch", v);
1002 }
1003 
savePlayListsStartClosed(bool v)1004 void Settings::savePlayListsStartClosed(bool v)
1005 {
1006     cfg.set("playListsStartClosed", v);
1007 }
1008 
1009 #ifdef ENABLE_HTTP_STREAM_PLAYBACK
savePlayStream(bool v)1010 void Settings::savePlayStream(bool v)
1011 {
1012     cfg.set("playStream", v);
1013 }
1014 #endif
1015 
1016 #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
saveCdAuto(bool v)1017 void Settings::saveCdAuto(bool v)
1018 {
1019     cfg.set("cdAuto", v);
1020 }
1021 
saveParanoiaFull(bool v)1022 void Settings::saveParanoiaFull(bool v)
1023 {
1024     cfg.set("paranoiaFull", v);
1025 }
1026 
saveParanoiaNeverSkip(bool v)1027 void Settings::saveParanoiaNeverSkip(bool v)
1028 {
1029     cfg.set("paranoiaNeverSkip", v);
1030 }
1031 
saveParanoiaOffset(int v)1032 void Settings::saveParanoiaOffset(int v)
1033 {
1034     cfg.set("paranoiaOffset", v);
1035 }
1036 #endif
1037 
1038 #if defined CDDB_FOUND && defined MUSICBRAINZ5_FOUND
saveUseCddb(bool v)1039 void Settings::saveUseCddb(bool v)
1040 {
1041     cfg.set("useCddb", v);
1042 }
1043 #endif
1044 
1045 #ifdef CDDB_FOUND
saveCddbHost(const QString & v)1046 void Settings::saveCddbHost(const QString &v)
1047 {
1048     cfg.set("cddbHost", v);
1049 }
1050 
saveCddbPort(int v)1051 void Settings::saveCddbPort(int v)
1052 {
1053     cfg.set("cddbPort", v);
1054 }
1055 #endif
1056 
saveForceSingleClick(bool v)1057 void Settings::saveForceSingleClick(bool v)
1058 {
1059     cfg.set("forceSingleClick", v);
1060 }
1061 
saveStartHidden(bool v)1062 void Settings::saveStartHidden(bool v)
1063 {
1064     cfg.set("startHidden", v);
1065 }
1066 
saveShowTimeRemaining(bool v)1067 void Settings::saveShowTimeRemaining(bool v)
1068 {
1069     cfg.set("showTimeRemaining", v);
1070 }
1071 
saveHiddenStreamCategories(const QStringList & v)1072 void Settings::saveHiddenStreamCategories(const QStringList &v)
1073 {
1074     cfg.set("hiddenStreamCategories", v);
1075 }
1076 
saveHiddenOnlineProviders(const QStringList & v)1077 void Settings::saveHiddenOnlineProviders(const QStringList &v)
1078 {
1079     cfg.set("hiddenOnlineProviders", v);
1080 }
1081 
1082 #if (defined Q_OS_LINUX && defined QT_QTDBUS_FOUND) || (defined Q_OS_MAC && defined IOKIT_FOUND)
saveInhibitSuspend(bool v)1083 void Settings::saveInhibitSuspend(bool v)
1084 {
1085     cfg.set("inhibitSuspend", v);
1086 }
1087 #endif
1088 
saveRssUpdate(int v)1089 void Settings::saveRssUpdate(int v)
1090 {
1091     cfg.set("rssUpdate", v);
1092 }
1093 
saveLastRssUpdate(const QDateTime & v)1094 void Settings::saveLastRssUpdate(const QDateTime &v)
1095 {
1096     cfg.set("lastRssUpdate", v);
1097 }
1098 
savePodcastDownloadPath(const QString & v)1099 void Settings::savePodcastDownloadPath(const QString &v)
1100 {
1101     cfg.set("podcastDownloadPath", v);
1102 }
1103 
savePodcastAutoDownloadLimit(int v)1104 void Settings::savePodcastAutoDownloadLimit(int v)
1105 {
1106     if (cfg.hasEntry("podcastAutoDownload")) {
1107         cfg.removeEntry("podcastAutoDownload");
1108     }
1109     cfg.set("podcastAutoDownloadLimit", v);
1110 }
1111 
saveVolumeStep(int v)1112 void Settings::saveVolumeStep(int v)
1113 {
1114     cfg.set("volumeStep", v);
1115 }
1116 
saveStartupState(int v)1117 void Settings::saveStartupState(int v)
1118 {
1119     cfg.set("startupState", getStartupStateStr((StartupState)v));
1120 }
1121 
saveSearchCategory(const QString & v)1122 void Settings::saveSearchCategory(const QString &v)
1123 {
1124     cfg.set("searchCategory", v);
1125 }
1126 
saveFetchCovers(bool v)1127 void Settings::saveFetchCovers(bool v)
1128 {
1129     cfg.set("fetchCovers", v);
1130 }
1131 
saveLang(const QString & v)1132 void Settings::saveLang(const QString &v)
1133 {
1134     cfg.set("lang", v);
1135 }
1136 
saveShowCoverWidget(bool v)1137 void Settings::saveShowCoverWidget(bool v)
1138 {
1139     cfg.set("showCoverWidget", v);
1140 }
1141 
saveShowStopButton(bool v)1142 void Settings::saveShowStopButton(bool v)
1143 {
1144     cfg.set("showStopButton", v);
1145 }
1146 
saveShowRatingWidget(bool v)1147 void Settings::saveShowRatingWidget(bool v)
1148 {
1149     cfg.set("showRatingWidget", v);
1150 }
1151 
saveShowTechnicalInfo(bool v)1152 void Settings::saveShowTechnicalInfo(bool v)
1153 {
1154     cfg.set("showTechnicalInfo", v);
1155 }
1156 
saveInfoTooltips(bool v)1157 void Settings::saveInfoTooltips(bool v)
1158 {
1159     cfg.set("infoTooltips", v);
1160 }
1161 
saveIgnorePrefixes(const QSet<QString> & v)1162 void Settings::saveIgnorePrefixes(const QSet<QString> &v)
1163 {
1164     cfg.set("ignorePrefixes", v.toList());
1165 }
1166 
saveMpris(bool v)1167 void Settings::saveMpris(bool v)
1168 {
1169     cfg.set("mpris", v);
1170 }
1171 
saveReplayGain(const QString & conn,const QString & v)1172 void Settings::saveReplayGain(const QString &conn, const QString &v)
1173 {
1174     QString n=MPDConnectionDetails::configGroupName(conn);
1175     Configuration grp(n);
1176     grp.set("replayGain", v);
1177 }
1178 
saveStyle(const QString & v)1179 void Settings::saveStyle(const QString &v)
1180 {
1181     cfg.set("style", v);
1182 }
1183 
1184 #if !defined Q_OS_WIN && !defined Q_OS_MAC
saveShowMenubar(bool v)1185 void Settings::saveShowMenubar(bool v)
1186 {
1187     cfg.set("showMenubar", v);
1188 }
1189 #endif
1190 
saveUseOriginalYear(bool v)1191 void Settings::saveUseOriginalYear(bool v)
1192 {
1193     cfg.set("useOriginalYear", v);
1194 }
1195 
saveResponsiveSidebar(bool v)1196 void Settings::saveResponsiveSidebar(bool v)
1197 {
1198     cfg.set("responsiveSidebar", v);
1199 }
1200 
save()1201 void Settings::save()
1202 {
1203     if (AP_NotConfigured!=state) {
1204         if (version()!=PACKAGE_VERSION || AP_FirstRun==state) {
1205             cfg.set("version", PACKAGE_VERSION_STRING);
1206             ver=PACKAGE_VERSION;
1207         }
1208     }
1209     cfg.sync();
1210 }
1211 
clearVersion()1212 void Settings::clearVersion()
1213 {
1214     cfg.removeEntry("version");
1215     state=AP_NotConfigured;
1216 }
1217 
getBoolAsInt(const QString & key,int def)1218 int Settings::getBoolAsInt(const QString &key, int def)
1219 {
1220     // Old config, sometimes bool was used - which has now been converted
1221     // to an int...
1222     QString v=cfg.get(key, QString::number(def));
1223     if (QLatin1String("false")==v) {
1224         return 0;
1225     }
1226     if (QLatin1String("true")==v) {
1227         return 1;
1228     }
1229     return v.toInt();
1230 }
1231