File indexing completed on 2024-05-19 04:56:00
0001 /** 0002 * \file bidirfileproxymodeliterator.cpp 0003 * Birdirectional iterator for FileProxyModel. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 21-Feb-2014 0008 * 0009 * Copyright (C) 2014-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 "bidirfileproxymodeliterator.h" 0028 #include <QTimer> 0029 #include "fileproxymodel.h" 0030 0031 /** 0032 * Constructor. 0033 * 0034 * @param model file proxy model 0035 * @param parent parent object 0036 */ 0037 BiDirFileProxyModelIterator::BiDirFileProxyModelIterator(FileProxyModel* model, 0038 QObject *parent) 0039 : QObject(parent), m_model(model), m_backwards(false), 0040 m_aborted(false), m_suspended(false) 0041 { 0042 } 0043 0044 /** 0045 * Abort operation. 0046 */ 0047 void BiDirFileProxyModelIterator::abort() 0048 { 0049 m_aborted = true; 0050 } 0051 0052 /** 0053 * Check if operation is aborted. 0054 * 0055 * @return true if aborted. 0056 */ 0057 bool BiDirFileProxyModelIterator::isAborted() const 0058 { 0059 return m_aborted; 0060 } 0061 0062 /** 0063 * Clear state which is reported by isAborted(). 0064 */ 0065 void BiDirFileProxyModelIterator::clearAborted() 0066 { 0067 m_aborted = false; 0068 } 0069 0070 /** 0071 * Set root index of file proxy model. 0072 * 0073 * @param rootIdx index of root element 0074 */ 0075 void BiDirFileProxyModelIterator::setRootIndex( 0076 const QPersistentModelIndex& rootIdx) 0077 { 0078 m_rootIndex = rootIdx; 0079 } 0080 0081 /** 0082 * Set index of current file. 0083 * 0084 * @param index index of current file 0085 */ 0086 void BiDirFileProxyModelIterator::setCurrentIndex( 0087 const QPersistentModelIndex& index) 0088 { 0089 m_currentIndex = index; 0090 } 0091 0092 /** 0093 * Start iteration. 0094 */ 0095 void BiDirFileProxyModelIterator::start() 0096 { 0097 m_aborted = false; 0098 m_suspended = false; 0099 if (m_currentIndex.isValid()) { 0100 emit nextReady(m_currentIndex); 0101 } 0102 fetchNext(); 0103 } 0104 0105 /** 0106 * Fetch next index. 0107 */ 0108 void BiDirFileProxyModelIterator::fetchNext() 0109 { 0110 int count = 0; 0111 while (!m_aborted) { 0112 if (m_suspended) { 0113 return; 0114 } 0115 QModelIndex next; 0116 if (!m_backwards) { 0117 if (!m_currentIndex.isValid()) { 0118 m_currentIndex = m_rootIndex; 0119 } 0120 if (m_model->rowCount(m_currentIndex) > 0) { 0121 // to first child 0122 next = m_model->index(0, 0, m_currentIndex); 0123 } else { 0124 QModelIndex parent = m_currentIndex; 0125 while (!next.isValid() && parent.isValid()) { 0126 // to next sibling or next sibling of parent 0127 int row = parent.row(); 0128 if (parent == m_rootIndex) { 0129 // do not move beyond root index 0130 break; 0131 } 0132 parent = parent.parent(); 0133 if (row + 1 < m_model->rowCount(parent)) { 0134 // to next sibling 0135 next = m_model->index(row + 1, 0, parent); 0136 } 0137 } 0138 } 0139 } else { 0140 if (m_currentIndex.isValid()) { 0141 if (int row = m_currentIndex.row() - 1; row >= 0) { 0142 // to last leafnode of previous sibling 0143 next = m_currentIndex.sibling(row, 0); 0144 row = m_model->rowCount(next) - 1; 0145 while (row >= 0) { 0146 next = m_model->index(row, 0, next); 0147 row = m_model->rowCount(next) - 1; 0148 } 0149 } else { 0150 // to parent 0151 next = m_currentIndex.parent(); 0152 } 0153 if (next == m_rootIndex) 0154 next = QPersistentModelIndex(); 0155 } else { 0156 // to last node 0157 int row; 0158 QModelIndex last = m_rootIndex; 0159 while ((row = m_model->rowCount(last)) > 0 && 0160 (last = m_model->index(row - 1, 0, last)).isValid()) { 0161 next = last; 0162 } 0163 } 0164 } 0165 if (next.isValid()) { 0166 if (m_model->isDir(next) && m_model->canFetchMore(next)) { 0167 connect(m_model, &FileProxyModel::sortingFinished, 0168 this, &BiDirFileProxyModelIterator::onDirectoryLoaded); 0169 m_model->fetchMore(next); 0170 return; 0171 } 0172 if (++count >= 10) { 0173 // Avoid spinning too long to keep the GUI responsive. 0174 QTimer::singleShot(0, this, &BiDirFileProxyModelIterator::fetchNext); 0175 return; 0176 } 0177 m_currentIndex = next; 0178 emit nextReady(m_currentIndex); 0179 } else { 0180 break; 0181 } 0182 } 0183 m_currentIndex = QPersistentModelIndex(); 0184 emit nextReady(m_currentIndex); 0185 } 0186 0187 /** 0188 * Called when the gatherer thread has finished to load. 0189 */ 0190 void BiDirFileProxyModelIterator::onDirectoryLoaded() 0191 { 0192 disconnect(m_model, &FileProxyModel::sortingFinished, 0193 this, &BiDirFileProxyModelIterator::onDirectoryLoaded); 0194 fetchNext(); 0195 } 0196 0197 /** 0198 * Suspend iteration. 0199 * The iteration can be continued with resume(). 0200 */ 0201 void BiDirFileProxyModelIterator::suspend() 0202 { 0203 m_suspended = true; 0204 } 0205 0206 /** 0207 * Resume iteration which has been suspended with suspend(). 0208 */ 0209 void BiDirFileProxyModelIterator::resume() 0210 { 0211 m_suspended = false; 0212 fetchNext(); 0213 }