/* * Cantata * * Copyright (c) 2011-2014 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 "musiclibraryitemalbum.h" #include "fancytabwidget.h" #include "albumsmodel.h" #include "itemview.h" #include "mpdparseutils.h" #include "utils.h" #include "mediakeys.h" #include "globalstatic.h" #if defined ENABLE_KDE_SUPPORT && defined ENABLE_KWALLET #include #endif #ifndef ENABLE_KDE_SUPPORT #include "mediakeys.h" #endif #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() : isFirstRun(false) , timer(0) , ver(-1) #if defined ENABLE_KDE_SUPPORT && defined ENABLE_KWALLET , wallet(0) #endif { // Only need to read system defaults if we have not previously been configured... if (version()readPassword("mpd", details.password); } } else if (name.isEmpty()) { details.password=mpdDefaults.passwd; } #else details.password=cfg.get("connectionPasswd", name.isEmpty() ? mpdDefaults.passwd : QString()); #endif details.port=cfg.get("connectionPort", name.isEmpty() ? mpdDefaults.port : 6600); #ifdef Q_OS_WIN32 details.dir=Utils::fixPath(QDir::fromNativeSeparators(cfg.get("mpdDir", mpdDefaults.dir))); #else details.dir=Utils::fixPath(cfg.get("mpdDir", mpdDefaults.dir)); #endif details.dynamizerPort=0; } else { QString n=MPDConnectionDetails::configGroupName(name); details.name=name; if (!cfg.hasGroup(n)) { details.name=QString(); n=MPDConnectionDetails::configGroupName(details.name); } if (cfg.hasGroup(n)) { cfg.beginGroup(n); details.hostname=cfg.get("host", name.isEmpty() ? mpdDefaults.host : QString()); details.port=cfg.get("port", name.isEmpty() ? mpdDefaults.port : 6600); #ifdef Q_OS_WIN32 details.dir=Utils::fixPath(QDir::fromNativeSeparators(cfg.get("dir", name.isEmpty() ? mpdDefaults.dir : "/var/lib/mpd/music"))); #else details.dir=Utils::fixPath(cfg.get("dir", name.isEmpty() ? mpdDefaults.dir : "/var/lib/mpd/music")); #endif #if defined ENABLE_KDE_SUPPORT && defined ENABLE_KWALLET if (KWallet::Wallet::isEnabled()) { if (cfg.get("passwd", false)) { if (openWallet()) { wallet->readPassword(name.isEmpty() ? "mpd" : name, details.password); } } else if (name.isEmpty()) { details.password=mpdDefaults.passwd; } } else #endif // ENABLE_KWALLET details.password=cfg.get("passwd", name.isEmpty() ? mpdDefaults.passwd : QString()); details.dynamizerPort=cfg.get("dynamizerPort", 0); details.coverName=cfg.get("coverName", QString()); #ifdef ENABLE_HTTP_STREAM_PLAYBACK details.streamUrl=cfg.get("streamUrl", QString()); #endif cfg.endGroup(); } else { details.hostname=mpdDefaults.host; details.port=mpdDefaults.port; details.dir=mpdDefaults.dir; details.password=mpdDefaults.passwd; details.dynamizerPort=0; details.coverName=QString(); #ifdef ENABLE_HTTP_STREAM_PLAYBACK details.streamUrl=QString(); #endif } } details.setDirReadable(); return details; } QList Settings::allConnections() { #ifdef ENABLE_KDE_SUPPORT QStringList groups=KGlobal::config()->groupList(); #else QStringList groups=cfg.childGroups(); #endif 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; } #if defined ENABLE_KDE_SUPPORT && defined ENABLE_KWALLET bool Settings::openWallet() { if (wallet) { return true; } wallet=KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), QApplication::activeWindow() ? QApplication::activeWindow()->winId() : 0); if (wallet) { if (!wallet->hasFolder(PACKAGE_NAME)) { wallet->createFolder(PACKAGE_NAME); } wallet->setFolder(PACKAGE_NAME); return true; } return false; } #endif #ifndef ENABLE_KDE_SUPPORT QString Settings::iconTheme() { return cfg.get("iconTheme", QString()); } #endif 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::libraryView() { int v=version(); QString def=ItemView::modeStr(vMusicLibraryItemAlbum::CoverExtraLarge || size<0 ? MusicLibraryItemAlbum::CoverMedium : size; } int Settings::albumsCoverSize() { int size=cfg.get("albumsCoverSize", (int)(MusicLibraryItemAlbum::CoverMedium)); return size>MusicLibraryItemAlbum::CoverExtraLarge || size<0 ? MusicLibraryItemAlbum::CoverMedium : size; } int Settings::albumSort() { return cfg.get("albumSort", 0); } int Settings::sidebar() { if (version()MaxFade)) { v=DefaultFade; } return v; } int Settings::httpAllocatedPort() { return cfg.get("httpAllocatedPort", 0); } QString Settings::httpInterface() { return cfg.get("httpInterface", QString()); } bool Settings::alwaysUseHttp() { #ifdef ENABLE_HTTP_SERVER return cfg.get("alwaysUseHttp", false); #else return false; #endif } bool Settings::playQueueGrouped() { return cfg.get("playQueueGrouped", true); } bool Settings::playQueueAutoExpand() { return cfg.get("playQueueAutoExpand", true); } bool Settings::playQueueStartClosed() { return cfg.get("playQueueStartClosed", false); } bool Settings::playQueueScroll() { return cfg.get("playQueueScroll", true); } int Settings::playQueueBackground() { if (version()removeEntry(walletEntry); } } else if (openWallet()) { wallet->writePassword(walletEntry, v.password); } } else #endif // ENABLE_KWALLET cfg.set("passwd", v.password); cfg.set("dynamizerPort", (int)v.dynamizerPort); cfg.set("coverName", v.coverName); #ifdef ENABLE_HTTP_STREAM_PLAYBACK cfg.set("streamUrl", v.streamUrl); #endif cfg.endGroup(); } void Settings::saveCurrentConnection(const QString &v) { cfg.set("currentConnection", v); } void Settings::saveShowFullScreen(bool v) { cfg.set("showFullScreen", 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::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::saveStopDynamizerOnExit(bool v) { cfg.set("stopDynamizerOnExit", v); } void Settings::saveStoreCoversInMpdDir(bool v) { cfg.set("storeCoversInMpdDir", v); } void Settings::saveStoreLyricsInMpdDir(bool v) { cfg.set("storeLyricsInMpdDir", v); } void Settings::saveStoreStreamsInMpdDir(bool v) { cfg.set("storeStreamsInMpdDir", v); } void Settings::saveStoreBackdropsInMpdDir(bool v) { cfg.set("storeBackdropsInMpdDir", v); } void Settings::saveLibraryView(int v) { cfg.set("libraryView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::saveAlbumsView(int v) { cfg.set("albumsView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::saveFolderView(int v) { cfg.set("folderView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::savePlaylistsView(int v) { cfg.set("playlistsView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::saveStreamsView(int v) { cfg.set("streamsView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::saveOnlineView(int v) { cfg.set("onlineView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::saveLibraryArtistImage(bool v) { cfg.set("libraryArtistImage", v); } void Settings::saveLibraryCoverSize(int v) { cfg.set("libraryCoverSize", v); } void Settings::saveAlbumsCoverSize(int v) { cfg.set("albumsCoverSize", v); } void Settings::saveAlbumSort(int v) { cfg.set("albumSort", v); } void Settings::saveSidebar(int v) { cfg.set("sidebar", v); } void Settings::saveLibraryYear(bool v) { cfg.set("libraryYear", v); } void Settings::saveGroupSingle(bool v) { cfg.set("groupSingle", v); } void Settings::saveUseComposer(bool v) { cfg.set("useComposer", 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.set("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::savePage(const QString &v) { cfg.set("page", v); } void Settings::saveHiddenPages(const QStringList &v) { cfg.set("hiddenPages", v); } #ifndef ENABLE_KDE_SUPPORT void Settings::saveMediaKeysIface(const QString &v) { cfg.set("mediaKeysIface", v); } #endif #ifdef ENABLE_DEVICES_SUPPORT void Settings::saveOverwriteSongs(bool v) { cfg.set("overwriteSongs", v); } void Settings::saveShowDeleteAction(bool v) { cfg.set("showDeleteAction", v); } void Settings::saveDevicesView(int v) { cfg.set("devicesView", ItemView::modeStr((ItemView::Mode)v)); } #endif void Settings::saveSearchView(int v) { cfg.set("searchView", ItemView::modeStr((ItemView::Mode)v)); } void Settings::saveStopFadeDuration(int v) { if (v<=MinFade) { v=0; } else if (v>MaxFade) { v=MaxFade; } 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::savePlayQueueGrouped(bool v) { cfg.set("playQueueGrouped", 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.set("playQueueBackgroundFile", v); } void Settings::savePlayQueueConfirmClear(bool v) { cfg.set("playQueueConfirmClea", 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::saveMonoSidebarIcons(bool v) { cfg.set("monoSidebarIcons", 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); } #ifndef Q_OS_WIN32 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::savePodcastAutoDownload(bool v) { cfg.set("podcastAutoDownload", v); } void Settings::saveStartupState(int v) { cfg.set("startupState", getStartupStateStr((StartupState)v)); } void Settings::saveSearchCategory(const QString &v) { cfg.set("searchCategory", v); } void Settings::saveCacheScaledCovers(bool v) { cfg.set("cacheScaledCovers", v); } void Settings::saveFetchCovers(bool v) { cfg.set("fetchCovers", v); } #ifndef ENABLE_KDE_SUPPORT void Settings::saveLang(const QString &v) { cfg.set("lang", v); } #endif void Settings::saveShowMenubar(bool v) { cfg.set("showMenubar", v); } void Settings::save(bool force) { if (force) { if (version()!=PACKAGE_VERSION || isFirstRun) { cfg.set("version", PACKAGE_VERSION_STRING); ver=PACKAGE_VERSION; } cfg.sync(); if (timer) { timer->stop(); } } else { if (!timer) { timer=new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(actualSave())); } timer->start(30*1000); } } void Settings::actualSave() { save(true); }