File indexing completed on 2024-05-19 04:56:02
0001 /** 0002 * \file fileproxymodeliterator.cpp 0003 * Iterator for FileProxyModel. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 03-Feb-2013 0008 * 0009 * Copyright (C) 2013-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #include "fileproxymodeliterator.h" 0028 #include <QTimer> 0029 #include "fileproxymodel.h" 0030 0031 /** 0032 * Constructor. 0033 * 0034 * @param model file proxy model 0035 */ 0036 FileProxyModelIterator::FileProxyModelIterator(FileProxyModel* model) 0037 : QObject(model), m_model(model), m_numDone(0), m_aborted(false) 0038 { 0039 } 0040 0041 /** 0042 * Abort operation. 0043 */ 0044 void FileProxyModelIterator::abort() 0045 { 0046 m_aborted = true; 0047 } 0048 0049 /** 0050 * Check if operation is aborted. 0051 * 0052 * @return true if aborted. 0053 */ 0054 bool FileProxyModelIterator::isAborted() const 0055 { 0056 return m_aborted; 0057 } 0058 0059 /** 0060 * Clear state which is reported by isAborted(). 0061 */ 0062 void FileProxyModelIterator::clearAborted() 0063 { 0064 m_aborted = false; 0065 } 0066 0067 /** 0068 * Start iteration. 0069 * 0070 * @param rootIdx index of root element 0071 */ 0072 void FileProxyModelIterator::start(const QPersistentModelIndex& rootIdx) 0073 { 0074 m_nodes.clear(); 0075 m_rootIndexes.clear(); 0076 m_rootIndexes.append(rootIdx); 0077 m_numDone = 0; 0078 m_aborted = false; 0079 fetchNext(); 0080 } 0081 0082 /** 0083 * Start iteration. 0084 * 0085 * @param indexes indexes of root directories 0086 */ 0087 void FileProxyModelIterator::start(const QList<QPersistentModelIndex>& indexes) 0088 { 0089 m_nodes.clear(); 0090 m_rootIndexes = indexes; 0091 m_numDone = 0; 0092 m_aborted = false; 0093 fetchNext(); 0094 } 0095 0096 /** 0097 * Fetch next index. 0098 */ 0099 void FileProxyModelIterator::fetchNext() 0100 { 0101 int count = 0; 0102 while (!m_aborted) { 0103 if (m_nodes.isEmpty()) { 0104 if (m_rootIndexes.isEmpty()) { 0105 break; 0106 } 0107 m_nodes.push(m_rootIndexes.takeFirst()); 0108 } 0109 m_nextIdx = m_nodes.top(); 0110 if (m_nextIdx.isValid()) { 0111 if (m_model->isDir(m_nextIdx) && m_model->canFetchMore(m_nextIdx)) { 0112 connect(m_model, &FileProxyModel::sortingFinished, 0113 this, &FileProxyModelIterator::onDirectoryLoaded); 0114 m_model->fetchMore(m_nextIdx); 0115 return; 0116 } 0117 if (++count >= 10) { 0118 // Avoid spinning too long to keep the GUI responsive. 0119 QTimer::singleShot(0, this, &FileProxyModelIterator::fetchNext); 0120 return; 0121 } 0122 m_nodes.pop(); 0123 ++m_numDone; 0124 const int numRows = m_model->rowCount(m_nextIdx); 0125 QStack<QPersistentModelIndex> childNodes; 0126 childNodes.reserve(numRows); 0127 for (int row = numRows - 1; row >= 0; --row) { 0128 childNodes.push(m_model->index(row, 0, m_nextIdx)); 0129 } 0130 std::stable_sort(childNodes.begin(), childNodes.end(), 0131 [](const QPersistentModelIndex& lhs, 0132 const QPersistentModelIndex& rhs) { 0133 return lhs.data().toString().compare(rhs.data().toString()) > 0; 0134 }); 0135 m_nodes += childNodes; 0136 emit nextReady(m_nextIdx); 0137 } else { 0138 m_nodes.pop(); 0139 } 0140 } 0141 m_nodes.clear(); 0142 m_rootIndexes.clear(); 0143 m_nextIdx = QPersistentModelIndex(); 0144 emit nextReady(m_nextIdx); 0145 } 0146 0147 /** 0148 * Called when the gatherer thread has finished to load. 0149 */ 0150 void FileProxyModelIterator::onDirectoryLoaded() 0151 { 0152 disconnect(m_model, &FileProxyModel::sortingFinished, 0153 this, &FileProxyModelIterator::onDirectoryLoaded); 0154 fetchNext(); 0155 }