File indexing completed on 2024-05-12 05:35:39

0001 /*
0002     SPDX-FileCopyrightText: 2020 Kevin Ottens <kevin.ottens@enioka.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "desktoppathssettings.h"
0008 
0009 #include <QDir>
0010 
0011 #include <KFilePlacesModel>
0012 #include <KLocalizedString>
0013 
0014 namespace
0015 {
0016 // save in XDG user-dirs.dirs config file, this is where KGlobalSettings/QDesktopServices reads from.
0017 KSharedConfig::Ptr userDirsConfig()
0018 {
0019     const QString userDirsFilePath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs");
0020     return KSharedConfig::openConfig(userDirsFilePath, KConfig::SimpleConfig);
0021 }
0022 }
0023 
0024 class XdgPathsSettingsStore : public QObject
0025 {
0026     Q_OBJECT
0027     Q_PROPERTY(QUrl desktopLocation READ desktopLocation WRITE setDesktopLocation)
0028     Q_PROPERTY(QUrl documentsLocation READ documentsLocation WRITE setDocumentsLocation)
0029     Q_PROPERTY(QUrl downloadsLocation READ downloadsLocation WRITE setDownloadsLocation)
0030     Q_PROPERTY(QUrl musicLocation READ musicLocation WRITE setMusicLocation)
0031     Q_PROPERTY(QUrl picturesLocation READ picturesLocation WRITE setPicturesLocation)
0032     Q_PROPERTY(QUrl videosLocation READ videosLocation WRITE setVideosLocation)
0033     Q_PROPERTY(QUrl publicLocation READ publicLocation WRITE setPublicLocation)
0034     Q_PROPERTY(QUrl templatesLocation READ templatesLocation WRITE setTemplatesLocation)
0035 public:
0036     XdgPathsSettingsStore(DesktopPathsSettings *parent = nullptr)
0037         : QObject(parent)
0038         , m_settings(parent)
0039     {
0040     }
0041 
0042     QUrl desktopLocation() const
0043     {
0044         return readUrl(QStringLiteral("XDG_DESKTOP_DIR"), m_settings->defaultDesktopLocation());
0045     }
0046 
0047     void setDesktopLocation(const QUrl &url)
0048     {
0049         writeUrl(QStringLiteral("XDG_DESKTOP_DIR"), url);
0050     }
0051 
0052     QUrl documentsLocation() const
0053     {
0054         return readUrl(QStringLiteral("XDG_DOCUMENTS_DIR"), m_settings->defaultDocumentsLocation());
0055     }
0056 
0057     void setDocumentsLocation(const QUrl &url)
0058     {
0059         writeUrl(QStringLiteral("XDG_DOCUMENTS_DIR"), url);
0060     }
0061 
0062     QUrl downloadsLocation() const
0063     {
0064         return readUrl(QStringLiteral("XDG_DOWNLOAD_DIR"), m_settings->defaultDownloadsLocation());
0065     }
0066 
0067     void setDownloadsLocation(const QUrl &url)
0068     {
0069         writeUrl(QStringLiteral("XDG_DOWNLOAD_DIR"), url);
0070     }
0071 
0072     QUrl musicLocation() const
0073     {
0074         return readUrl(QStringLiteral("XDG_MUSIC_DIR"), m_settings->defaultMusicLocation());
0075     }
0076 
0077     void setMusicLocation(const QUrl &url)
0078     {
0079         writeUrl(QStringLiteral("XDG_MUSIC_DIR"), url);
0080     }
0081 
0082     QUrl picturesLocation() const
0083     {
0084         return readUrl(QStringLiteral("XDG_PICTURES_DIR"), m_settings->defaultPicturesLocation());
0085     }
0086 
0087     void setPicturesLocation(const QUrl &url)
0088     {
0089         writeUrl(QStringLiteral("XDG_PICTURES_DIR"), url);
0090     }
0091 
0092     QUrl videosLocation() const
0093     {
0094         return readUrl(QStringLiteral("XDG_VIDEOS_DIR"), m_settings->defaultVideosLocation());
0095     }
0096 
0097     void setVideosLocation(const QUrl &url)
0098     {
0099         writeUrl(QStringLiteral("XDG_VIDEOS_DIR"), url);
0100     }
0101 
0102     QUrl publicLocation() const
0103     {
0104         return readUrl(QStringLiteral("XDG_PUBLICSHARE_DIR"), m_settings->defaultPublicLocation());
0105     }
0106 
0107     void setPublicLocation(const QUrl &url)
0108     {
0109         writeUrl(QStringLiteral("XDG_PUBLICSHARE_DIR"), url);
0110     }
0111 
0112     QUrl templatesLocation() const
0113     {
0114         return readUrl(QStringLiteral("XDG_TEMPLATES_DIR"), m_settings->defaultTemplatesLocation());
0115     }
0116 
0117     void setTemplatesLocation(const QUrl &url)
0118     {
0119         writeUrl(QStringLiteral("XDG_TEMPLATES_DIR"), url);
0120     }
0121 
0122 private:
0123     QUrl readUrl(const QString &key, const QUrl &defaultValue) const
0124     {
0125         KConfigGroup group(m_settings->config(), QString());
0126         const auto path = group.readPathEntry(key, QString());
0127         if (path.isEmpty()) {
0128             return defaultValue;
0129         } else {
0130             return QUrl::fromLocalFile(path.mid(1, path.length() - 2));
0131         }
0132     }
0133 
0134     void writeUrl(const QString &key, const QUrl &url)
0135     {
0136         const auto oldUrl = readUrl(key, QUrl());
0137 
0138         KConfigGroup group(m_settings->config(), QString());
0139         // HACK to benefit from path translation (thus unexpanding $HOME)
0140         group.writePathEntry(key, url.toLocalFile());
0141         const auto path = group.readEntryUntranslated(key, QString());
0142         group.writeEntry(key, QString(QStringLiteral("\"") + path + QStringLiteral("\"")));
0143 
0144         if (oldUrl.isValid() && oldUrl != url) {
0145             KFilePlacesModel placesModel;
0146 
0147             const auto &bookmark = placesModel.bookmarkForUrl(oldUrl);
0148             if (bookmark.isNull()) {
0149                 return;
0150             }
0151             const auto &matchedPlaces = placesModel.match(placesModel.index(0, 0), KFilePlacesModel::UrlRole, oldUrl, 1, Qt::MatchFixedString);
0152             if (matchedPlaces.count() == 1) {
0153                 placesModel.editPlace(matchedPlaces.at(0), url.fileName(), url, bookmark.icon(), bookmark.metaDataItem(QStringLiteral("OnlyInApp")));
0154             }
0155         }
0156     }
0157 
0158     DesktopPathsSettings *const m_settings;
0159 };
0160 
0161 DesktopPathsSettings::DesktopPathsSettings(QObject *parent)
0162     : KCoreConfigSkeleton(userDirsConfig(), parent)
0163     , m_xdgPathsStore(new XdgPathsSettingsStore(this))
0164 {
0165     addItemInternal("desktopLocation", defaultDesktopLocation(), [this] {
0166         Q_EMIT desktopLocationChanged();
0167     });
0168     addItemInternal("documentsLocation", defaultDocumentsLocation(), [this] {
0169         Q_EMIT documentsLocationChanged();
0170     });
0171     addItemInternal("downloadsLocation", defaultDownloadsLocation(), [this] {
0172         Q_EMIT downloadsLocationChanged();
0173     });
0174     addItemInternal("musicLocation", defaultMusicLocation(), [this] {
0175         Q_EMIT musicLocationChanged();
0176     });
0177     addItemInternal("picturesLocation", defaultPicturesLocation(), [this] {
0178         Q_EMIT picturesLocationChanged();
0179     });
0180     addItemInternal("videosLocation", defaultVideosLocation(), [this] {
0181         Q_EMIT videosLocationChanged();
0182     });
0183     addItemInternal("publicLocation", defaultPublicLocation(), [this] {
0184         Q_EMIT publicLocationChanged();
0185     });
0186     addItemInternal("templatesLocation", defaultTemplatesLocation(), [this] {
0187         Q_EMIT templatesLocationChanged();
0188     });
0189 }
0190 
0191 void DesktopPathsSettings::addItemInternal(const QByteArray &propertyName, const QVariant &defaultValue, const std::function<void()> &signal)
0192 {
0193     auto *item = new KPropertySkeletonItem(m_xdgPathsStore, propertyName, defaultValue);
0194     item->setNotifyFunction(signal);
0195     addItem(item, propertyName);
0196 }
0197 
0198 QUrl DesktopPathsSettings::desktopLocation() const
0199 {
0200     return findItem("desktopLocation")->property().toUrl();
0201 }
0202 
0203 void DesktopPathsSettings::setDesktopLocation(const QUrl &url)
0204 {
0205     findItem("desktopLocation")->setProperty(url);
0206 }
0207 
0208 QUrl DesktopPathsSettings::defaultDesktopLocation() const
0209 {
0210     const char *desktop = "Desktop";
0211     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", desktop));
0212 }
0213 
0214 QUrl DesktopPathsSettings::documentsLocation() const
0215 {
0216     return findItem("documentsLocation")->property().toUrl();
0217 }
0218 
0219 void DesktopPathsSettings::setDocumentsLocation(const QUrl &url)
0220 {
0221     findItem("documentsLocation")->setProperty(url);
0222 }
0223 
0224 QUrl DesktopPathsSettings::defaultDocumentsLocation() const
0225 {
0226     const char *documents = "Documents";
0227     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", documents));
0228 }
0229 
0230 QUrl DesktopPathsSettings::downloadsLocation() const
0231 {
0232     return findItem("downloadsLocation")->property().toUrl();
0233 }
0234 
0235 void DesktopPathsSettings::setDownloadsLocation(const QUrl &url)
0236 {
0237     findItem("downloadsLocation")->setProperty(url);
0238 }
0239 
0240 QUrl DesktopPathsSettings::defaultDownloadsLocation() const
0241 {
0242     const char *downloads = "Downloads";
0243     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", downloads));
0244 }
0245 
0246 QUrl DesktopPathsSettings::musicLocation() const
0247 {
0248     return findItem("musicLocation")->property().toUrl();
0249 }
0250 
0251 void DesktopPathsSettings::setMusicLocation(const QUrl &url)
0252 {
0253     findItem("musicLocation")->setProperty(url);
0254 }
0255 
0256 QUrl DesktopPathsSettings::defaultMusicLocation() const
0257 {
0258     const char *music = "Music";
0259     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", music));
0260 }
0261 
0262 QUrl DesktopPathsSettings::picturesLocation() const
0263 {
0264     return findItem("picturesLocation")->property().toUrl();
0265 }
0266 
0267 void DesktopPathsSettings::setPicturesLocation(const QUrl &url)
0268 {
0269     findItem("picturesLocation")->setProperty(url);
0270 }
0271 
0272 QUrl DesktopPathsSettings::defaultPicturesLocation() const
0273 {
0274     const char *pictures = "Pictures";
0275     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", pictures));
0276 }
0277 
0278 QUrl DesktopPathsSettings::videosLocation() const
0279 {
0280     return findItem("videosLocation")->property().toUrl();
0281 }
0282 
0283 void DesktopPathsSettings::setVideosLocation(const QUrl &url)
0284 {
0285     findItem("videosLocation")->setProperty(url);
0286 }
0287 
0288 QUrl DesktopPathsSettings::defaultVideosLocation() const
0289 {
0290     const char *videos = "Videos";
0291     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", videos));
0292 }
0293 
0294 QUrl DesktopPathsSettings::publicLocation() const
0295 {
0296     return findItem("publicLocation")->property().toUrl();
0297 }
0298 
0299 void DesktopPathsSettings::setPublicLocation(const QUrl &url)
0300 {
0301     findItem("publicLocation")->setProperty(url);
0302 }
0303 
0304 QUrl DesktopPathsSettings::defaultPublicLocation() const
0305 {
0306     const char *pub = "Public";
0307     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", pub));
0308 }
0309 
0310 QUrl DesktopPathsSettings::templatesLocation() const
0311 {
0312     return findItem("templatesLocation")->property().toUrl();
0313 }
0314 
0315 void DesktopPathsSettings::setTemplatesLocation(const QUrl &url)
0316 {
0317     findItem("templatesLocation")->setProperty(url);
0318 }
0319 
0320 QUrl DesktopPathsSettings::defaultTemplatesLocation() const
0321 {
0322     const char *templates = "Templates";
0323     return QUrl::fromLocalFile(QDir::homePath() + QDir::separator() + i18nd("xdg-user-dirs", templates));
0324 }
0325 
0326 #include "desktoppathssettings.moc"