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

0001 /*
0002  * SPDX-FileCopyrightText: 2022 Alvin Wong <alvin@alvinhc.com>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "KisRecentFilesManager.h"
0008 
0009 #include <QApplication>
0010 #include <QDir>
0011 #include <QFileInfo>
0012 #include <QThread>
0013 #include <QTimer>
0014 #include <QDebug>
0015 
0016 #include <kconfig.h>
0017 #include <kconfiggroup.h>
0018 #include <ksharedconfig.h>
0019 
0020 class KisRecentFilesManager::Private
0021 {
0022 public:
0023     KisRecentFilesManager *m_q;
0024     int m_maxItems {10};
0025     QVector<KisRecentFilesEntry> m_entries;
0026 
0027 private:
0028     QTimer m_saveOnIdleTimer;
0029 
0030 public:
0031     Private(KisRecentFilesManager *q);
0032 
0033     bool containsUrl(const QUrl &url) const;
0034     int indexOfUrl(const QUrl &url) const;
0035 
0036     void requestSaveOnNextTick();
0037 }; /* class KisRecentFilesEntry::Private */
0038 
0039 KisRecentFilesManager::Private::Private(KisRecentFilesManager *q)
0040     : m_q(q)
0041     , m_saveOnIdleTimer(q)
0042 {
0043     m_saveOnIdleTimer.setSingleShot(true);
0044     m_saveOnIdleTimer.setInterval(0);
0045     m_q->connect(&m_saveOnIdleTimer, &QTimer::timeout, [this]() {
0046         m_q->saveEntries(KSharedConfig::openConfig()->group("RecentFiles"));
0047     });
0048 }
0049 
0050 bool KisRecentFilesManager::Private::containsUrl(const QUrl &url) const
0051 {
0052     return indexOfUrl(url) >= 0;
0053 }
0054 
0055 int KisRecentFilesManager::Private::indexOfUrl(const QUrl &url) const
0056 {
0057     auto found = std::find_if(m_entries.constBegin(), m_entries.constEnd(), [url](const KisRecentFilesEntry &item) {
0058         return item.m_url == url;
0059     });
0060     if (found == m_entries.constEnd()) {
0061         return -1;
0062     } else {
0063         return found - m_entries.constBegin();
0064     }
0065 }
0066 
0067 void KisRecentFilesManager::Private::requestSaveOnNextTick()
0068 {
0069     // If multiple saves are requested within the same tick, they will be
0070     // consolidated by the timer.
0071     m_saveOnIdleTimer.start();
0072 }
0073 
0074 
0075 KisRecentFilesManager::KisRecentFilesManager()
0076     : m_d(new Private(this))
0077 {
0078     loadEntries(KSharedConfig::openConfig()->group("RecentFiles"));
0079 }
0080 
0081 KisRecentFilesManager::~KisRecentFilesManager()
0082 {
0083     delete m_d;
0084 }
0085 
0086 KisRecentFilesManager *KisRecentFilesManager::instance()
0087 {
0088     if (QThread::currentThread() != qApp->thread()) {
0089         qWarning() << "KisRecentFilesManager::instance() called from non-GUI thread!";
0090         return nullptr;
0091     }
0092     static KisRecentFilesManager s_instance;
0093     return &s_instance;
0094 }
0095 
0096 void KisRecentFilesManager::clear()
0097 {
0098     m_d->m_entries.clear();
0099     emit listRenewed();
0100     m_d->requestSaveOnNextTick();
0101 }
0102 
0103 void KisRecentFilesManager::remove(const QUrl &url)
0104 {
0105     int removeIndex = m_d->indexOfUrl(url);
0106     if (removeIndex >= 0) {
0107         m_d->m_entries.removeAt(removeIndex);
0108         emit fileRemoved(url);
0109         m_d->requestSaveOnNextTick();
0110     }
0111 }
0112 
0113 QVector<KisRecentFilesEntry> KisRecentFilesManager::recentFiles() const
0114 {
0115     return m_d->m_entries;
0116 }
0117 
0118 QList<QUrl> KisRecentFilesManager::recentUrlsLatestFirst() const
0119 {
0120     // switch order so last opened file is first
0121     QList<QUrl> sortedList;
0122     for (int i = m_d->m_entries.length() - 1; i >= 0; i--) {
0123         sortedList.append(m_d->m_entries[i].m_url);
0124     }
0125 
0126     return sortedList;
0127 }
0128 
0129 // The following file contains code copied and modified from LGPL-2.0-only
0130 // source:
0131 #include "KisRecentFilesManager_p.h"