/* * Cantata * * Copyright (c) 2011-2017 Craig Drummond * * ---- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "settings.h" #include "models/sqllibrarymodel.h" #include "support/fancytabwidget.h" #include "widgets/itemview.h" #include "mpd-interface/mpdparseutils.h" #include "support/utils.h" #include "support/globalstatic.h" #include "db/librarydb.h" #include #include #include GLOBAL_STATIC(Settings, instance) struct MpdDefaults { MpdDefaults() : host("localhost") , dir("/var/lib/mpd/music/") , port(6600) { } static QString getVal(const QString &line) { QStringList parts=line.split('\"'); return parts.count()>1 ? parts[1] : QString(); } enum Details { DT_DIR = 0x01, DT_ADDR = 0x02, DT_PORT = 0x04, DT_PASSWD = 0x08, DT_ALL = DT_DIR|DT_ADDR|DT_PORT|DT_PASSWD }; void read() { QFile f("/etc/mpd.conf"); if (f.open(QIODevice::ReadOnly|QIODevice::Text)) { int details=0; while (!f.atEnd()) { QString line = QString::fromUtf8(f.readLine()).trimmed(); if (line.startsWith('#')) { continue; } else if (!(details&DT_DIR) && line.startsWith(QLatin1String("music_directory"))) { QString val=getVal(line); if (!val.isEmpty() && QDir(val).exists()) { dir=Utils::fixPath(val); details|=DT_DIR; } } else if (!(details&DT_ADDR) && line.startsWith(QLatin1String("bind_to_address"))) { QString val=getVal(line); if (!val.isEmpty() && val!=QLatin1String("any")) { host=val; details|=DT_ADDR; } } else if (!(details&DT_PORT) && line.startsWith(QLatin1String("port"))) { int val=getVal(line).toInt(); if (val>0) { port=val; details|=DT_PORT; } } else if (!(details&DT_PASSWD) && line.startsWith(QLatin1String("password"))) { QString val=getVal(line); if (!val.isEmpty()) { QStringList parts=val.split('@'); if (!parts.isEmpty()) { passwd=parts[0]; details|=DT_PASSWD; } } } if (details==DT_ALL) { break; } } } } QString host; QString dir; QString passwd; int port; }; static MpdDefaults mpdDefaults; static QString getStartupStateStr(Settings::StartupState s) { switch (s) { case Settings::SS_ShowMainWindow: return QLatin1String("show"); case Settings::SS_HideMainWindow: return QLatin1String("hide"); default: case Settings::SS_Previous: return QLatin1String("prev"); } } static Settings::StartupState getStartupState(const QString &str) { for (int i=0; i<=Settings::SS_Previous; ++i) { if (getStartupStateStr((Settings::StartupState)i)==str) { return (Settings::StartupState)i; } } return Settings::SS_Previous; } Settings::Settings() : state(AP_Configured) , ver(-1) { // Call 'version' so that it initialises 'ver' and 'state' version(); // Only need to read system defaults if we have not previously been configured... if (!cfg.hasGroup(MPDConnectionDetails::configGroupName())) { mpdDefaults.read(); } } Settings::~Settings() { save(); } QString Settings::currentConnection() { return cfg.get("currentConnection", QString()); } MPDConnectionDetails Settings::connectionDetails(const QString &name) { MPDConnectionDetails details; QString n=MPDConnectionDetails::configGroupName(name); details.name=name; if (!cfg.hasGroup(n)) { details.name=QString(); n=MPDConnectionDetails::configGroupName(details.name); } if (cfg.hasGroup(n)) { Configuration grp(n); details.hostname=grp.get("host", name.isEmpty() ? mpdDefaults.host : QString()); details.port=grp.get("port", name.isEmpty() ? mpdDefaults.port : 6600); details.dir=grp.getDirPath("dir", name.isEmpty() ? mpdDefaults.dir : "/var/lib/mpd/music"); details.password=grp.get("passwd", name.isEmpty() ? mpdDefaults.passwd : QString()); details.coverName=grp.get("coverName", QString()); #ifdef ENABLE_HTTP_STREAM_PLAYBACK details.streamUrl=grp.get("streamUrl", QString()); #endif } else { details.hostname=mpdDefaults.host; details.port=mpdDefaults.port; details.dir=mpdDefaults.dir; details.password=mpdDefaults.passwd; details.coverName=QString(); #ifdef ENABLE_HTTP_STREAM_PLAYBACK details.streamUrl=QString(); #endif } details.setDirReadable(); return details; } QList Settings::allConnections() { QStringList groups=cfg.childGroups(); QList connections; foreach (const QString &grp, groups) { if (cfg.hasGroup(grp) && grp.startsWith("Connection")) { connections.append(connectionDetails(grp=="Connection" ? QString() : grp.mid(11))); } } if (connections.isEmpty()) { // If we are empty, add at lease the default connection... connections.append(connectionDetails()); } return connections; } bool Settings::showPlaylist() { return cfg.get("showPlaylist", true); } bool Settings::showFullScreen() { return cfg.get("showFullScreen", false); } QByteArray Settings::headerState(const QString &key) { if (version()=CANTATA_MAKE_VERSION(0, 9, 50); #endif return cfg.get("storeStreamsInMpdDir", def); } bool Settings::storeBackdropsInMpdDir() { return cfg.get("storeBackdropsInMpdDir", false); } int Settings::sidebar() { if (version() Settings::composerGenres() { return cfg.get("composerGenres", Song::composerGenres().toList()).toSet(); } QSet Settings::singleTracksFolders() { return cfg.get("singleTracksFolders", QStringList()).toSet(); } MPDParseUtils::CueSupport Settings::cueSupport() { return MPDParseUtils::toCueSupport(cfg.get("cueSupport", MPDParseUtils::toStr(MPDParseUtils::Cue_Parse))); } QStringList Settings::lyricProviders() { return cfg.get("lyricProviders", QStringList() << "lyrics.wikia.com" << "lyricstime.com" << "lyricsreg.com" << "lyricsmania.com" << "metrolyrics.com" << "azlyrics.com" << "songlyrics.com" << "elyrics.net" << "lyricsdownload.com" << "lyrics.com" << "lyricsbay.com" << "directlyrics.com" << "loudson.gs" << "teksty.org" << "tekstowo.pl (POLISH)" << "vagalume.uol.com.br" << "vagalume.uol.com.br (PORTUGUESE)"); } QStringList Settings::wikipediaLangs() { return cfg.get("wikipediaLangs", QStringList() << "en:en"); } bool Settings::wikipediaIntroOnly() { return cfg.get("wikipediaIntroOnly", true); } int Settings::contextBackdrop() { return getBoolAsInt("contextBackdrop", 0); } int Settings::contextBackdropOpacity() { return cfg.get("contextBackdropOpacity", 15, 0, 100); } int Settings::contextBackdropBlur() { return cfg.get("contextBackdropBlur", 0, 0, 20); } QString Settings::contextBackdropFile() { return cfg.getFilePath("contextBackdropFile", QString()); } bool Settings::contextDarkBackground() { return cfg.get("contextDarkBackground", false); } int Settings::contextZoom() { return cfg.get("contextZoom", 0); } QString Settings::contextSlimPage() { return cfg.get("contextSlimPage", QString()); } QByteArray Settings::contextSplitterState() { return version() Settings::ignorePrefixes() { return cfg.get("ignorePrefixes", Song::ignorePrefixes().toList()).toSet(); } bool Settings::mpris() { return cfg.get("mpris", true); } void Settings::removeConnectionDetails(const QString &v) { if (v==currentConnection()) { saveCurrentConnection(QString()); } cfg.removeGroup(MPDConnectionDetails::configGroupName(v)); } void Settings::saveConnectionDetails(const MPDConnectionDetails &v) { if (v.name.isEmpty()) { cfg.removeEntry("connectionHost"); cfg.removeEntry("connectionPasswd"); cfg.removeEntry("connectionPort"); cfg.removeEntry("mpdDir"); } QString n=MPDConnectionDetails::configGroupName(v.name); Configuration grp(n); grp.set("host", v.hostname); grp.set("port", (int)v.port); grp.setDirPath("dir", v.dir); grp.set("passwd", v.password); grp.set("coverName", v.coverName); #ifdef ENABLE_HTTP_STREAM_PLAYBACK grp.set("streamUrl", v.streamUrl); #endif } void Settings::saveCurrentConnection(const QString &v) { cfg.set("currentConnection", v); } void Settings::saveShowFullScreen(bool v) { cfg.set("showFullScreen", v); } void Settings::saveShowPlaylist(bool v) { cfg.set("showPlaylist", v); } void Settings::saveHeaderState(const QString &key, const QByteArray &v) { cfg.set(key+"HeaderState", v); } void Settings::saveSplitterState(const QByteArray &v) { cfg.set("splitterState", v); } void Settings::saveSplitterAutoHide(bool v) { cfg.set("splitterAutoHide", v); } void Settings::saveMainWindowSize(const QSize &v) { cfg.set("mainWindowSize", v); } void Settings::saveMainWindowCollapsedSize(const QSize &v) { if (v.width()>16 && v.height()>16) { cfg.set("mainWindowCollapsedSize", v); } } void Settings::saveUseSystemTray(bool v) { cfg.set("useSystemTray", v); } void Settings::saveMinimiseOnClose(bool v) { cfg.set("minimiseOnClose", v); } void Settings::saveShowPopups(bool v) { cfg.set("showPopups", v); } void Settings::saveStopOnExit(bool v) { cfg.set("stopOnExit", v); } void Settings::saveStoreCoversInMpdDir(bool v) { cfg.set("storeCoversInMpdDir", v); } void Settings::saveStoreLyricsInMpdDir(bool v) { cfg.set("storeLyricsInMpdDir", v); } void Settings::saveStoreBackdropsInMpdDir(bool v) { cfg.set("storeBackdropsInMpdDir", v); } void Settings::saveSidebar(int v) { cfg.set("sidebar", v); } void Settings::saveComposerGenres(const QSet &v) { cfg.set("composerGenres", v.toList()); } void Settings::saveSingleTracksFolders(const QSet &v) { cfg.set("singleTracksFolders", v.toList()); } void Settings::saveCueSupport(MPDParseUtils::CueSupport v) { cfg.set("cueSupport", MPDParseUtils::toStr(v)); } void Settings::saveLyricProviders(const QStringList &v) { cfg.set("lyricProviders", v); } void Settings::saveWikipediaLangs(const QStringList &v) { cfg.set("wikipediaLangs", v); } void Settings::saveWikipediaIntroOnly(bool v) { cfg.set("wikipediaIntroOnly", v); } void Settings::saveContextBackdrop(int v) { cfg.set("contextBackdrop", v); } void Settings::saveContextBackdropOpacity(int v) { cfg.set("contextBackdropOpacity", v); } void Settings::saveContextBackdropBlur(int v) { cfg.set("contextBackdropBlur", v); } void Settings::saveContextBackdropFile(const QString &v) { cfg.setFilePath("contextBackdropFile", v); } void Settings::saveContextDarkBackground(bool v) { cfg.set("contextDarkBackground", v); } void Settings::saveContextZoom(int v) { cfg.set("contextZoom", v); } void Settings::saveContextSlimPage(const QString &v) { cfg.set("contextSlimPage", v); } void Settings::saveContextSplitterState(const QByteArray &v) { cfg.set("contextSplitterState", v); } void Settings::saveContextAlwaysCollapsed(bool v) { cfg.set("contextAlwaysCollapsed", v); } void Settings::saveContextSwitchTime(int v) { cfg.set("contextSwitchTime", v); } void Settings::saveContextAutoScroll(bool v) { cfg.set("contextAutoScroll", v); } void Settings::saveContextTrackView(int v) { cfg.set("contextTrackView", v); } void Settings::savePage(const QString &v) { cfg.set("page", v); } void Settings::saveHiddenPages(const QStringList &v) { cfg.set("hiddenPages", v); } #ifdef ENABLE_DEVICES_SUPPORT void Settings::saveOverwriteSongs(bool v) { cfg.set("overwriteSongs", v); } void Settings::saveShowDeleteAction(bool v) { cfg.set("showDeleteAction", v); } #endif void Settings::saveStopFadeDuration(int v) { cfg.set("stopFadeDuration", v); } void Settings::saveHttpAllocatedPort(int v) { cfg.set("httpAllocatedPort", v); } void Settings::saveHttpInterface(const QString &v) { cfg.set("httpInterface", v); } void Settings::savePlayQueueView(int v) { cfg.set("playQueueView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::savePlayQueueAutoExpand(bool v) { cfg.set("playQueueAutoExpand", v); } void Settings::savePlayQueueStartClosed(bool v) { cfg.set("playQueueStartClosed", v); } void Settings::savePlayQueueScroll(bool v) { cfg.set("playQueueScroll", v); } void Settings::savePlayQueueBackground(int v) { cfg.set("playQueueBackground", v); } void Settings::savePlayQueueBackgroundOpacity(int v) { cfg.set("playQueueBackgroundOpacity", v); } void Settings::savePlayQueueBackgroundBlur(int v) { cfg.set("playQueueBackgroundBlur", v); } void Settings::savePlayQueueBackgroundFile(const QString &v) { cfg.setFilePath("playQueueBackgroundFile", v); } void Settings::savePlayQueueConfirmClear(bool v) { cfg.set("playQueueConfirmClear", v); } void Settings::savePlayQueueSearch(bool v) { cfg.set("playQueueSearch", v); } void Settings::savePlayListsStartClosed(bool v) { cfg.set("playListsStartClosed", v); } #ifdef ENABLE_HTTP_STREAM_PLAYBACK void Settings::savePlayStream(bool v) { cfg.set("playStream", v); } #endif #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND void Settings::saveCdAuto(bool v) { cfg.set("cdAuto", v); } void Settings::saveParanoiaFull(bool v) { cfg.set("paranoiaFull", v); } void Settings::saveParanoiaNeverSkip(bool v) { cfg.set("paranoiaNeverSkip", v); } #endif #if defined CDDB_FOUND && defined MUSICBRAINZ5_FOUND void Settings::saveUseCddb(bool v) { cfg.set("useCddb", v); } #endif #ifdef CDDB_FOUND void Settings::saveCddbHost(const QString &v) { cfg.set("cddbHost", v); } void Settings::saveCddbPort(int v) { cfg.set("cddbPort", v); } #endif void Settings::saveForceSingleClick(bool v) { cfg.set("forceSingleClick", v); } void Settings::saveStartHidden(bool v) { cfg.set("startHidden", v); } void Settings::saveShowTimeRemaining(bool v) { cfg.set("showTimeRemaining", v); } void Settings::saveHiddenStreamCategories(const QStringList &v) { cfg.set("hiddenStreamCategories", v); } void Settings::saveHiddenOnlineProviders(const QStringList &v) { cfg.set("hiddenOnlineProviders", v); } #if (defined Q_OS_LINUX && defined QT_QTDBUS_FOUND) || (defined Q_OS_MAC && defined IOKIT_FOUND) void Settings::saveInhibitSuspend(bool v) { cfg.set("inhibitSuspend", v); } #endif void Settings::saveRssUpdate(int v) { cfg.set("rssUpdate", v); } void Settings::saveLastRssUpdate(const QDateTime &v) { cfg.set("lastRssUpdate", v); } void Settings::savePodcastDownloadPath(const QString &v) { cfg.set("podcastDownloadPath", v); } void Settings::savePodcastAutoDownloadLimit(int v) { if (cfg.hasEntry("podcastAutoDownload")) { cfg.removeEntry("podcastAutoDownload"); } cfg.set("podcastAutoDownloadLimit", v); } void Settings::saveStartupState(int v) { cfg.set("startupState", getStartupStateStr((StartupState)v)); } void Settings::saveSearchCategory(const QString &v) { cfg.set("searchCategory", v); } void Settings::saveFetchCovers(bool v) { cfg.set("fetchCovers", v); } void Settings::saveLang(const QString &v) { cfg.set("lang", v); } void Settings::saveShowMenubar(bool v) { cfg.set("showMenubar", v); } void Settings::saveShowCoverWidget(bool v) { cfg.set("showCoverWidget", v); } void Settings::saveShowStopButton(bool v) { cfg.set("showStopButton", v); } void Settings::saveShowRatingWidget(bool v) { cfg.set("showRatingWidget", v); } void Settings::saveInfoTooltips(bool v) { cfg.set("infoTooltips", v); } void Settings::saveRetinaSupport(bool v) { cfg.set("retinaSupport", v); } void Settings::saveIgnorePrefixes(const QSet &v) { cfg.set("ignorePrefixes", v.toList()); } void Settings::saveMpris(bool v) { cfg.set("mpris", v); } void Settings::save() { if (AP_NotConfigured!=state) { if (version()!=PACKAGE_VERSION || AP_FirstRun==state) { cfg.set("version", PACKAGE_VERSION_STRING); ver=PACKAGE_VERSION; } } cfg.sync(); } void Settings::clearVersion() { cfg.removeEntry("version"); state=AP_NotConfigured; } int Settings::getBoolAsInt(const QString &key, int def) { // Old config, sometimes bool was used - which has now been converted // to an int... QString v=cfg.get(key, QString::number(def)); if (QLatin1String("false")==v) { return 0; } if (QLatin1String("true")==v) { return 1; } return v.toInt(); }