File indexing completed on 2024-05-12 16:02:29

0001 /*
0002     SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org>
0003     SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
0004     SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
0005     SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
0006     SPDX-FileCopyrightText: 2000 Michael Koch <koch@kde.org>
0007     SPDX-FileCopyrightText: 2001 Holger Freyther <freyther@kde.org>
0008     SPDX-FileCopyrightText: 2002 Ellis Whitehead <ellis@kde.org>
0009     SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org>
0010     SPDX-FileCopyrightText: 2003 Andras Mantia <amantia@kde.org>
0011     SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org>
0012     SPDX-FileCopyrightText: 2022 Alvin Wong <alvin@alvinhc.com>
0013 
0014     SPDX-License-Identifier: LGPL-2.0-only
0015 */
0016 
0017 /*
0018  * The functions in this file was refactored out of `krecentfilesaction.cpp`.
0019  *
0020  * `krecentfilesaction.cpp` was forked from KConfigWidgets. Due to historical
0021  * reasons, it was licensed under LGPL 2.0 only (not LGPL 2.1 or later). Until
0022  * the original file has been relicensed, keep these code snippets in a
0023  * separate file.
0024  *
0025  * The relicensing issue is tracked at https://invent.kde.org/teams/licensing/issues/-/issues/34
0026  */
0027 
0028 void KisRecentFilesManager::loadEntries(const KConfigGroup &_config)
0029 {
0030     m_d->m_entries.clear();
0031 
0032     KConfigGroup cg = _config;
0033     if (cg.name().isEmpty()) {
0034         cg = KConfigGroup(cg.config(), "RecentFiles");
0035     }
0036 
0037     m_d->m_maxItems = cg.readEntry("maxRecentFileItems", 100);
0038     
0039     for (int i = 0; i < m_d->m_maxItems; ++i) {
0040         const QString key = QString("File%1").arg(i+1);
0041         QString value;
0042 #ifdef Q_OS_ANDROID
0043         value = cg.readEntry(key, QString());
0044 #else
0045         value = cg.readPathEntry(key, QString());
0046 #endif
0047         if (value.isEmpty()) {
0048             continue;
0049         }
0050         QUrl url = QUrl::fromUserInput(value);
0051 
0052         if (url.isLocalFile()) {
0053             QString localFilePath = url.toLocalFile();
0054             QFileInfo fileInfo = QFileInfo(localFilePath);
0055 
0056             // Don't restore if file doesn't exist anymore
0057             if (!fileInfo.exists()) {
0058                 continue;
0059             }
0060 
0061             // When KConfigGroup substitutes $HOME, it may produce a path
0062             // with two consecutive forward slashes. This may cause duplicated
0063             // entries of the same file when opened using the file selector,
0064             // in which the path does not include this double slash.
0065             // `absoluteFilePath` replaces the double slash to a single slash.
0066             value = fileInfo.absoluteFilePath();
0067             url = QUrl::fromLocalFile(value);
0068         }
0069 
0070         // Don't restore where the url is already known (eg. broken config)
0071         if (m_d->containsUrl(url)) {
0072             continue;
0073         }
0074 
0075 #ifdef Q_OS_WIN
0076         // convert to backslashes
0077         if (url.isLocalFile()) {
0078             value = QDir::toNativeSeparators(value);
0079         }
0080 #endif
0081 
0082         const QString nameKey = QString("Name%1").arg(i+1);
0083         const QString nameValue = cg.readEntry(nameKey, url.fileName());
0084         m_d->m_entries.append(KisRecentFilesEntry {
0085             url, // m_url
0086             nameValue, // m_displayName
0087         });
0088     }
0089 
0090     emit listRenewed();
0091 }
0092 
0093 void KisRecentFilesManager::saveEntries(const KConfigGroup &_cg)
0094 {
0095     KConfigGroup cg = _cg;
0096     if (cg.name().isEmpty()) {
0097         cg = KConfigGroup(cg.config(), "RecentFiles");
0098     }
0099 
0100     cg.deleteGroup();
0101 
0102     cg.writeEntry("maxRecentFileItems", m_d->m_maxItems);
0103 
0104     // write file list
0105     for (int i = 0; i < m_d->m_entries.count(); ++i) {
0106         const QString key = QString("File%1").arg(i+1);
0107         QString value;
0108 #ifdef Q_OS_ANDROID
0109         value = m_d->m_entries[i].m_url.toDisplayString();
0110         cg.writeEntry(key, value);
0111 #else
0112         value = m_d->m_entries[i].m_url.toDisplayString(QUrl::PreferLocalFile);
0113         cg.writePathEntry(key, value);
0114 #endif
0115         const QString nameKey = QString("Name%1").arg(i+1);
0116         const QString nameValue = m_d->m_entries[i].m_displayName;
0117         cg.writeEntry(nameKey, nameValue);
0118     }
0119 }
0120 
0121 void KisRecentFilesManager::add(const QUrl &url)
0122 {
0123     const QString name; // Dummy
0124 
0125     if (m_d->m_maxItems <= 0) {
0126         return;
0127     }
0128 
0129     if (url.isLocalFile() && url.toLocalFile().startsWith(QDir::tempPath())) {
0130         return;
0131     }
0132     const QString tmpName = name.isEmpty() ? url.fileName() : name;
0133     const QString pathOrUrl(url.toDisplayString(QUrl::PreferLocalFile));
0134 
0135 #ifdef Q_OS_WIN
0136     const QString file = url.isLocalFile() ? QDir::toNativeSeparators(pathOrUrl) : pathOrUrl;
0137 #else
0138     const QString file = pathOrUrl;
0139 #endif
0140 
0141     // remove file if already in list
0142     {
0143         int removeIndex = m_d->indexOfUrl(url);
0144         if (removeIndex >= 0) {
0145             m_d->m_entries.removeAt(removeIndex);
0146             emit fileRemoved(url);
0147         }
0148     }
0149 
0150     // remove oldest item if already maxitems in list
0151     if (m_d->m_entries.count() >= m_d->m_maxItems) {
0152         // remove oldest added item
0153         m_d->m_entries.removeFirst();
0154     }
0155 
0156     m_d->m_entries.append(KisRecentFilesEntry {
0157         url, // m_url
0158         tmpName, // m_displayName
0159     });
0160     emit fileAdded(url);
0161     m_d->requestSaveOnNextTick();
0162 }