1 /*
2     SPDX-FileCopyrightText: 2020 Kevin Ottens <kevin.ottens@enioka.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "desktoppathssettings.h"
8 
9 #include <KLocalizedString>
10 
11 #include <QDir>
12 
13 namespace
14 {
15 // save in XDG user-dirs.dirs config file, this is where KGlobalSettings/QDesktopServices reads from.
userDirsConfig()16 KSharedConfig::Ptr userDirsConfig()
17 {
18     const QString userDirsFilePath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs");
19     return KSharedConfig::openConfig(userDirsFilePath, KConfig::SimpleConfig);
20 }
21 }
22 
23 class XdgPathsSettingsStore : public QObject
24 {
25     Q_OBJECT
26     Q_PROPERTY(QUrl desktopLocation READ desktopLocation WRITE setDesktopLocation)
27     Q_PROPERTY(QUrl documentsLocation READ documentsLocation WRITE setDocumentsLocation)
28     Q_PROPERTY(QUrl downloadsLocation READ downloadsLocation WRITE setDownloadsLocation)
29     Q_PROPERTY(QUrl musicLocation READ musicLocation WRITE setMusicLocation)
30     Q_PROPERTY(QUrl picturesLocation READ picturesLocation WRITE setPicturesLocation)
31     Q_PROPERTY(QUrl videosLocation READ videosLocation WRITE setVideosLocation)
32 public:
XdgPathsSettingsStore(DesktopPathsSettings * parent=nullptr)33     XdgPathsSettingsStore(DesktopPathsSettings *parent = nullptr)
34         : QObject(parent)
35         , m_settings(parent)
36     {
37     }
38 
desktopLocation() const39     QUrl desktopLocation() const
40     {
41         return readUrl(QStringLiteral("XDG_DESKTOP_DIR"), m_settings->defaultDesktopLocation());
42     }
43 
setDesktopLocation(const QUrl & url)44     void setDesktopLocation(const QUrl &url)
45     {
46         writeUrl(QStringLiteral("XDG_DESKTOP_DIR"), url);
47     }
48 
documentsLocation() const49     QUrl documentsLocation() const
50     {
51         return readUrl(QStringLiteral("XDG_DOCUMENTS_DIR"), m_settings->defaultDocumentsLocation());
52     }
53 
setDocumentsLocation(const QUrl & url)54     void setDocumentsLocation(const QUrl &url)
55     {
56         writeUrl(QStringLiteral("XDG_DOCUMENTS_DIR"), url);
57     }
58 
downloadsLocation() const59     QUrl downloadsLocation() const
60     {
61         return readUrl(QStringLiteral("XDG_DOWNLOAD_DIR"), m_settings->defaultDownloadsLocation());
62     }
63 
setDownloadsLocation(const QUrl & url)64     void setDownloadsLocation(const QUrl &url)
65     {
66         writeUrl(QStringLiteral("XDG_DOWNLOAD_DIR"), url);
67     }
68 
musicLocation() const69     QUrl musicLocation() const
70     {
71         return readUrl(QStringLiteral("XDG_MUSIC_DIR"), m_settings->defaultMusicLocation());
72     }
73 
setMusicLocation(const QUrl & url)74     void setMusicLocation(const QUrl &url)
75     {
76         writeUrl(QStringLiteral("XDG_MUSIC_DIR"), url);
77     }
78 
picturesLocation() const79     QUrl picturesLocation() const
80     {
81         return readUrl(QStringLiteral("XDG_PICTURES_DIR"), m_settings->defaultPicturesLocation());
82     }
83 
setPicturesLocation(const QUrl & url)84     void setPicturesLocation(const QUrl &url)
85     {
86         writeUrl(QStringLiteral("XDG_PICTURES_DIR"), url);
87     }
88 
videosLocation() const89     QUrl videosLocation() const
90     {
91         return readUrl(QStringLiteral("XDG_VIDEOS_DIR"), m_settings->defaultVideosLocation());
92     }
93 
setVideosLocation(const QUrl & url)94     void setVideosLocation(const QUrl &url)
95     {
96         writeUrl(QStringLiteral("XDG_VIDEOS_DIR"), url);
97     }
98 
99 private:
readUrl(const QString & key,const QUrl & defaultValue) const100     QUrl readUrl(const QString &key, const QUrl &defaultValue) const
101     {
102         KConfigGroup group(m_settings->config(), QString());
103         const auto path = group.readPathEntry(key, QString());
104         if (path.isEmpty()) {
105             return defaultValue;
106         } else {
107             return QUrl::fromLocalFile(path.mid(1, path.length() - 2));
108         }
109     }
110 
writeUrl(const QString & key,const QUrl & url)111     void writeUrl(const QString &key, const QUrl &url)
112     {
113         KConfigGroup group(m_settings->config(), QString());
114         // HACK to benefit from path translation (thus unexpanding $HOME)
115         group.writePathEntry(key, url.toLocalFile());
116         const auto path = group.readEntryUntranslated(key, QString());
117         group.writeEntry(key, QString(QStringLiteral("\"") + path + QStringLiteral("\"")));
118     }
119 
120     DesktopPathsSettings *m_settings;
121 };
122 
DesktopPathsSettings(QObject * parent)123 DesktopPathsSettings::DesktopPathsSettings(QObject *parent)
124     : KCoreConfigSkeleton(userDirsConfig(), parent)
125     , m_xdgPathsStore(new XdgPathsSettingsStore(this))
126 {
127     addItemInternal("desktopLocation", defaultDesktopLocation());
128     addItemInternal("documentsLocation", defaultDocumentsLocation());
129     addItemInternal("downloadsLocation", defaultDownloadsLocation());
130     addItemInternal("musicLocation", defaultMusicLocation());
131     addItemInternal("picturesLocation", defaultPicturesLocation());
132     addItemInternal("videosLocation", defaultVideosLocation());
133 }
134 
addItemInternal(const QByteArray & propertyName,const QVariant & defaultValue)135 void DesktopPathsSettings::addItemInternal(const QByteArray &propertyName, const QVariant &defaultValue)
136 {
137     auto *item = new KPropertySkeletonItem(m_xdgPathsStore, propertyName, defaultValue);
138     item->setNotifyFunction([this] {
139         Q_EMIT this->widgetChanged();
140     });
141     addItem(item, propertyName);
142 }
143 
desktopLocation() const144 QUrl DesktopPathsSettings::desktopLocation() const
145 {
146     return findItem("desktopLocation")->property().toUrl();
147 }
148 
setDesktopLocation(const QUrl & url)149 void DesktopPathsSettings::setDesktopLocation(const QUrl &url)
150 {
151     findItem("desktopLocation")->setProperty(url);
152 }
153 
defaultDesktopLocation() const154 QUrl DesktopPathsSettings::defaultDesktopLocation() const
155 {
156     return QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/') + i18nd("xdg-user-dirs", "Desktop"));
157 }
158 
documentsLocation() const159 QUrl DesktopPathsSettings::documentsLocation() const
160 {
161     return findItem("documentsLocation")->property().toUrl();
162 }
163 
setDocumentsLocation(const QUrl & url)164 void DesktopPathsSettings::setDocumentsLocation(const QUrl &url)
165 {
166     findItem("documentsLocation")->setProperty(url);
167 }
168 
defaultDocumentsLocation() const169 QUrl DesktopPathsSettings::defaultDocumentsLocation() const
170 {
171     return QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/') + i18nd("xdg-user-dirs", "Documents"));
172 }
173 
downloadsLocation() const174 QUrl DesktopPathsSettings::downloadsLocation() const
175 {
176     return findItem("downloadsLocation")->property().toUrl();
177 }
178 
setDownloadsLocation(const QUrl & url)179 void DesktopPathsSettings::setDownloadsLocation(const QUrl &url)
180 {
181     findItem("downloadsLocation")->setProperty(url);
182 }
183 
defaultDownloadsLocation() const184 QUrl DesktopPathsSettings::defaultDownloadsLocation() const
185 {
186     return QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/') + i18nd("xdg-user-dirs", "Downloads"));
187 }
188 
musicLocation() const189 QUrl DesktopPathsSettings::musicLocation() const
190 {
191     return findItem("musicLocation")->property().toUrl();
192 }
193 
setMusicLocation(const QUrl & url)194 void DesktopPathsSettings::setMusicLocation(const QUrl &url)
195 {
196     findItem("musicLocation")->setProperty(url);
197 }
198 
defaultMusicLocation() const199 QUrl DesktopPathsSettings::defaultMusicLocation() const
200 {
201     return QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/') + i18nd("xdg-user-dirs", "Music"));
202 }
203 
picturesLocation() const204 QUrl DesktopPathsSettings::picturesLocation() const
205 {
206     return findItem("picturesLocation")->property().toUrl();
207 }
208 
setPicturesLocation(const QUrl & url)209 void DesktopPathsSettings::setPicturesLocation(const QUrl &url)
210 {
211     findItem("picturesLocation")->setProperty(url);
212 }
213 
defaultPicturesLocation() const214 QUrl DesktopPathsSettings::defaultPicturesLocation() const
215 {
216     return QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/') + i18nd("xdg-user-dirs", "Pictures"));
217 }
218 
videosLocation() const219 QUrl DesktopPathsSettings::videosLocation() const
220 {
221     return findItem("videosLocation")->property().toUrl();
222 }
223 
setVideosLocation(const QUrl & url)224 void DesktopPathsSettings::setVideosLocation(const QUrl &url)
225 {
226     findItem("videosLocation")->setProperty(url);
227 }
228 
defaultVideosLocation() const229 QUrl DesktopPathsSettings::defaultVideosLocation() const
230 {
231     return QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/') + i18nd("xdg-user-dirs", "Videos"));
232 }
233 
234 #include "desktoppathssettings.moc"
235