File indexing completed on 2024-05-12 09:11:34
0001 /*************************************************************************** 0002 Copyright (C) 2005-2009 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "progressmanager.h" 0026 #include "tellico_debug.h" 0027 0028 #include <QTimer> 0029 0030 using Tellico::ProgressItem; 0031 using Tellico::ProgressManager; 0032 ProgressManager* ProgressManager::s_self = nullptr; 0033 0034 template<typename T> 0035 inline 0036 uint qHash(const QPointer<T>& pointer_) { 0037 return qHash(pointer_.data()); 0038 } 0039 0040 ProgressItem::Done::Done(QObject* obj) : m_object(obj) { 0041 // myDebug() << "**Done Item for" << m_object->metaObject()->className(); 0042 } 0043 0044 ProgressItem::Done::~Done() { 0045 // m_object might have been deleted, so check for existence 0046 if(m_object) { 0047 ProgressManager::self()->setDone(m_object); 0048 } 0049 } 0050 0051 /* *********************************************** */ 0052 0053 ProgressItem::ProgressItem(const QString& label_, bool canCancel_) 0054 : m_label(label_) 0055 , m_canCancel(canCancel_) 0056 , m_progress(0) 0057 , m_total(0) 0058 , m_cancelled(false) 0059 , m_done(false) { 0060 } 0061 0062 ProgressItem::~ProgressItem() { 0063 } 0064 0065 void ProgressItem::setProgress(qulonglong steps_) { 0066 if(m_done) { 0067 myDebug() << "Setting progress on item already done"; 0068 return; 0069 } 0070 m_progress = steps_; 0071 emit signalProgress(this); 0072 0073 if(m_progress >= m_total) { 0074 setDone(); 0075 } 0076 } 0077 0078 void ProgressItem::setTotalSteps(qulonglong steps_) { 0079 m_total = steps_; 0080 emit signalTotalSteps(this); 0081 } 0082 0083 void ProgressItem::setDone() { 0084 if(!m_cancelled) { 0085 m_progress = m_total; 0086 } 0087 if(m_done) { 0088 myDebug() << "ProgressItem::setDone() - Progress item is already done"; 0089 } else { 0090 m_done = true; 0091 emit signalDone(this); 0092 } 0093 // make sure the deleting doesn't interfere with anything 0094 QTimer::singleShot(3000, this, &QObject::deleteLater); 0095 } 0096 0097 void ProgressItem::cancel() { 0098 if(!m_canCancel || m_cancelled) { 0099 return; 0100 } 0101 0102 m_cancelled = true; 0103 emit signalCancelled(this); 0104 } 0105 0106 /* *********************************************** */ 0107 0108 ProgressManager::ProgressManager() : QObject() { 0109 } 0110 0111 ProgressManager::~ProgressManager() { 0112 } 0113 0114 void ProgressManager::setProgress(QObject* owner_, qulonglong steps_) { 0115 Q_ASSERT(owner_); 0116 if(!owner_ || !m_items.contains(owner_)) { 0117 return; 0118 } 0119 0120 m_items[owner_] ->setProgress(steps_); 0121 // slotUpdateTotalProgress(); // called in ProgressItem::setProgress() 0122 // emit signalItemProgress(m_items[owner_]); 0123 } 0124 0125 void ProgressManager::setTotalSteps(QObject* owner_, qulonglong steps_) { 0126 Q_ASSERT(owner_); 0127 if(!owner_ || !m_items.contains(owner_)) { 0128 return; 0129 } 0130 0131 m_items[owner_]->setTotalSteps(steps_); 0132 // updateTotalProgress(); // called in ProgressItem::setTotalSteps() 0133 } 0134 0135 void ProgressManager::setDone(QObject* owner_) { 0136 Q_ASSERT(owner_); 0137 if(!owner_ || !m_items.contains(owner_)) { 0138 return; 0139 } 0140 setDone(m_items[owner_]); 0141 } 0142 0143 void ProgressManager::setDone(ProgressItem* item_) { 0144 if(!item_) { 0145 myDebug() << "null ProgressItem!"; 0146 return; 0147 } 0148 item_->setDone(); 0149 } 0150 0151 void ProgressManager::slotItemDone(ProgressItem* item_) { 0152 for(ProgressMap::Iterator it = m_items.begin(); it != m_items.end(); ++it) { 0153 if(it.value() == item_) { 0154 m_items.erase(it); 0155 break; 0156 } 0157 } 0158 slotUpdateTotalProgress(); 0159 } 0160 0161 ProgressItem& ProgressManager::newProgressItemImpl(QObject* owner_, 0162 const QString& label_, 0163 bool canCancel_) { 0164 Q_ASSERT(owner_); 0165 // myDebug() << "Progress Item for" << owner_->metaObject()->className() << ":" << label_; 0166 if(m_items.contains(owner_)) { 0167 return *m_items[owner_]; 0168 } 0169 0170 ProgressItem* item = new ProgressItem(label_, canCancel_); 0171 m_items.insert(owner_, item); 0172 0173 connect(item, &Tellico::ProgressItem::signalTotalSteps, 0174 this, &Tellico::ProgressManager::slotUpdateTotalProgress); 0175 connect(item, &Tellico::ProgressItem::signalProgress, 0176 this, &Tellico::ProgressManager::slotUpdateTotalProgress); 0177 connect(item, &Tellico::ProgressItem::signalDone, 0178 this, &Tellico::ProgressManager::slotItemDone); 0179 0180 return *item; 0181 } 0182 0183 void ProgressManager::slotUpdateTotalProgress() { 0184 qulonglong progress = 0; 0185 qulonglong total = 0; 0186 0187 for(ProgressMap::ConstIterator it = m_items.constBegin(); it != m_items.constEnd(); ++it) { 0188 if(it.value()) { 0189 progress += (*it)->progress(); 0190 total += (*it)->totalSteps(); 0191 } 0192 } 0193 0194 if(total == 0) { 0195 if(!m_items.isEmpty()) { 0196 emit signalTotalProgress(100); 0197 } 0198 return; 0199 } 0200 0201 emit signalTotalProgress(100*progress/total); 0202 } 0203 0204 void ProgressManager::slotCancelAll() { 0205 for(ProgressMap::Iterator it = m_items.begin(), end = m_items.end(); it != end; ++it) { 0206 if(it.value()) { 0207 it.value()->cancel(); 0208 } 0209 } 0210 } 0211 0212 bool ProgressManager::anyCanBeCancelled() const { 0213 for(ProgressMap::ConstIterator it = m_items.constBegin(), end = m_items.constEnd(); it != end; ++it) { 0214 if(it.value() && it.value()->canCancel()) { 0215 return true; 0216 } 0217 } 0218 return false; 0219 }