File indexing completed on 2024-04-21 05:48:32
0001 /*********************************************************************** 0002 * SPDX-FileCopyrightText: 2003-2004 Max Howell <max.howell@methylblue.com> 0003 * SPDX-FileCopyrightText: 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org> 0004 * SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 ***********************************************************************/ 0008 0009 #include "remoteLister.h" 0010 #include "filelight_debug.h" 0011 #include "scan.h" 0012 0013 #include <QList> 0014 0015 #include <kio_version.h> 0016 0017 namespace Filelight 0018 { 0019 0020 // You need to use a single DirLister. 0021 // One per folder breaks KIO (seemingly) and also uses un-godly amounts of memory! 0022 0023 struct Store { 0024 /// location of the folder 0025 const QUrl url; 0026 /// the folder on which we are operating 0027 std::shared_ptr<Folder> folder; 0028 /// so we can reference the parent store 0029 const std::shared_ptr<Store> parent = nullptr; 0030 /// directories in this folder that need to be scanned before we can propagate() 0031 QList<std::shared_ptr<Store>> stores; 0032 0033 Store(const QUrl &url_, const QString &name, const std::shared_ptr<Store> &parentStore) 0034 : url(url_) 0035 , folder(std::make_shared<Folder>((name + QLatin1Char('/')).toUtf8().constData())) 0036 , parent(parentStore) 0037 { 0038 } 0039 ~Store() = default; 0040 0041 private: 0042 Q_DISABLE_COPY_MOVE(Store) 0043 }; 0044 0045 std::shared_ptr<Store> propagate(Store *store, const std::shared_ptr<Store> &root) 0046 { 0047 /// returns the next store available for scanning (or the root itself) 0048 0049 while (store->parent) { 0050 qCDebug(FILELIGHT_LOG) << "propagate: " << store->url; 0051 store->parent->folder->append(store->folder); 0052 if (!store->parent->stores.isEmpty()) { 0053 return store->parent; 0054 } 0055 store = store->parent.get(); 0056 } 0057 0058 return root; 0059 } 0060 0061 RemoteLister::RemoteLister(const QUrl &url, ScanManager *parent) 0062 : KDirLister(parent) 0063 , m_root(std::make_shared<Store>(url, url.url(), nullptr)) 0064 , m_store(m_root) 0065 , m_manager(parent) 0066 { 0067 setShowHiddenFiles(true); 0068 0069 // Use SIGNAL(result(KIO::Job*)) instead and then use Job::error() 0070 connect(this, static_cast<void (KCoreDirLister::*)()>(&KCoreDirLister::completed), this, &RemoteLister::onCompleted); 0071 connect(this, static_cast<void (KCoreDirLister::*)()>(&KCoreDirLister::canceled), this, &RemoteLister::onCanceled); 0072 } 0073 0074 void RemoteLister::onCanceled() 0075 { 0076 qCDebug(FILELIGHT_LOG) << "Canceled"; 0077 Q_EMIT branchCompleted(nullptr); 0078 } 0079 0080 void RemoteLister::onCompleted() 0081 { 0082 // m_folder is set to the folder we should operate on 0083 0084 const KFileItemList items = KDirLister::items(); 0085 for (const auto &item : items) { 0086 if (item.isDir()) { 0087 m_store->stores << std::make_shared<Store>(item.url(), item.name(), m_store); 0088 } else { 0089 m_store->folder->append(item.name().toUtf8().constData(), item.size()); 0090 m_manager->m_totalSize += item.size(); 0091 } 0092 0093 m_manager->m_files++; 0094 } 0095 0096 if (m_store->stores.isEmpty()) { 0097 // no directories to scan, so we need to append ourselves to the parent folder 0098 // propagate() will return the next ancestor that has stores left to be 0099 // scanned, or root if we are done 0100 if (auto newStore = propagate(m_store.get(), m_root); newStore != m_store) { 0101 // We need to clean up old stores 0102 m_store = newStore; 0103 } 0104 } 0105 0106 if (!m_store->stores.isEmpty()) { 0107 // we should operate with this store next time this function is called 0108 m_store = m_store->stores.takeFirst(); 0109 0110 const auto url = m_store->url; 0111 qCDebug(FILELIGHT_LOG) << "scanning: " << url; 0112 openUrl(url); 0113 return; 0114 } 0115 0116 qCDebug(FILELIGHT_LOG) << "I think we're done"; 0117 Q_ASSERT(m_root == m_store); 0118 Q_EMIT branchCompleted(m_store->folder); 0119 } 0120 0121 RemoteLister::~RemoteLister() 0122 { 0123 stop(); 0124 } 0125 0126 } // namespace Filelight