File indexing completed on 2024-05-12 04:38:17
0001 /* 0002 SPDX-FileCopyrightText: 2004 Till Adam <adam@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "progressmanager.h" 0008 #include "debug.h" 0009 0010 #include <KLocalizedString> 0011 0012 namespace KDevelop { 0013 0014 unsigned int KDevelop::ProgressManager::uID = 42; 0015 0016 ProgressItem::ProgressItem( ProgressItem *parent, const QString &id, 0017 const QString &label, const QString &status, 0018 bool canBeCanceled, bool usesCrypto ) 0019 : mId( id ), mLabel( label ), mStatus( status ), mParent( parent ), 0020 mCanBeCanceled( canBeCanceled ), mProgress( 0 ), mTotal( 0 ), 0021 mCompleted( 0 ), mWaitingForKids( false ), mCanceled( false ), 0022 mUsesCrypto( usesCrypto ), mUsesBusyIndicator( false ), mCompletedCalled( false ) 0023 { 0024 } 0025 0026 ProgressItem::~ProgressItem() 0027 { 0028 } 0029 0030 void ProgressItem::setComplete() 0031 { 0032 // qCDebug(SHELL) << label(); 0033 if ( mChildren.isEmpty() ) { 0034 if ( mCompletedCalled ) 0035 return; 0036 if ( !mCanceled ) { 0037 setProgress( 100 ); 0038 } 0039 mCompletedCalled = true; 0040 if ( parent() ) { 0041 parent()->removeChild( this ); 0042 } 0043 emit progressItemCompleted( this ); 0044 } else { 0045 mWaitingForKids = true; 0046 } 0047 } 0048 0049 void ProgressItem::addChild( ProgressItem *kiddo ) 0050 { 0051 mChildren.insert( kiddo, true ); 0052 } 0053 0054 void ProgressItem::removeChild( ProgressItem *kiddo ) 0055 { 0056 if ( mChildren.isEmpty() ) { 0057 mWaitingForKids = false; 0058 return; 0059 } 0060 0061 if ( mChildren.remove( kiddo ) == 0 ) { 0062 // do nothing if the specified item is not in the map 0063 return; 0064 } 0065 0066 // in case we were waiting for the last kid to go away, now is the time 0067 if ( mChildren.count() == 0 && mWaitingForKids ) { 0068 emit progressItemCompleted( this ); 0069 } 0070 } 0071 0072 void ProgressItem::cancel() 0073 { 0074 if ( mCanceled || !mCanBeCanceled ) { 0075 return; 0076 } 0077 0078 qCDebug(SHELL) << label(); 0079 mCanceled = true; 0080 // Cancel all children. 0081 const QList<ProgressItem*> kids = mChildren.keys(); 0082 for (ProgressItem* kid : kids) { 0083 if ( kid->canBeCanceled() ) { 0084 kid->cancel(); 0085 } 0086 } 0087 setStatus( i18nc("@info", "Aborting..." ) ); 0088 emit progressItemCanceled( this ); 0089 } 0090 0091 void ProgressItem::setProgress( unsigned int v ) 0092 { 0093 mProgress = v; 0094 // qCDebug(SHELL) << label() << " :" << v; 0095 emit progressItemProgress( this, mProgress ); 0096 } 0097 0098 void ProgressItem::setLabel( const QString &v ) 0099 { 0100 mLabel = v; 0101 emit progressItemLabel( this, mLabel ); 0102 } 0103 0104 void ProgressItem::setStatus( const QString &v ) 0105 { 0106 mStatus = v; 0107 emit progressItemStatus( this, mStatus ); 0108 } 0109 0110 void ProgressItem::setUsesCrypto( bool v ) 0111 { 0112 mUsesCrypto = v; 0113 emit progressItemUsesCrypto( this, v ); 0114 } 0115 0116 void ProgressItem::setUsesBusyIndicator( bool useBusyIndicator ) 0117 { 0118 mUsesBusyIndicator = useBusyIndicator; 0119 emit progressItemUsesBusyIndicator( this, useBusyIndicator ); 0120 } 0121 0122 // ====================================== 0123 0124 struct ProgressManagerPrivate { 0125 ProgressManager instance; 0126 }; 0127 0128 Q_GLOBAL_STATIC( ProgressManagerPrivate, progressManagerPrivate ) 0129 0130 ProgressManager::ProgressManager() 0131 : QObject() 0132 { 0133 0134 } 0135 0136 ProgressManager::~ProgressManager() 0137 { 0138 for (auto* item : mTransactions) 0139 delete item; 0140 } 0141 0142 ProgressManager *ProgressManager::instance() 0143 { 0144 return progressManagerPrivate.isDestroyed() ? nullptr : &progressManagerPrivate->instance ; 0145 } 0146 0147 ProgressItem *ProgressManager::createProgressItemImpl( ProgressItem *parent, 0148 const QString &id, 0149 const QString &label, 0150 const QString &status, 0151 bool cancellable, 0152 bool usesCrypto ) 0153 { 0154 ProgressItem *t = nullptr; 0155 if ( !mTransactions.value( id ) ) { 0156 t = new ProgressItem ( parent, id, label, status, cancellable, usesCrypto ); 0157 mTransactions.insert( id, t ); 0158 if ( parent ) { 0159 ProgressItem *p = mTransactions.value( parent->id() ); 0160 if ( p ) { 0161 p->addChild( t ); 0162 } 0163 } 0164 // connect all signals 0165 connect ( t, &ProgressItem::progressItemCompleted, 0166 this, &ProgressManager::slotTransactionCompleted ); 0167 connect ( t, &ProgressItem::progressItemProgress, 0168 this, &ProgressManager::progressItemProgress ); 0169 connect ( t, &ProgressItem::progressItemAdded, 0170 this, &ProgressManager::progressItemAdded ); 0171 connect ( t, &ProgressItem::progressItemCanceled, 0172 this, &ProgressManager::progressItemCanceled ); 0173 connect ( t, &ProgressItem::progressItemStatus, 0174 this, &ProgressManager::progressItemStatus ); 0175 connect ( t, &ProgressItem::progressItemLabel, 0176 this, &ProgressManager::progressItemLabel ); 0177 connect ( t, &ProgressItem::progressItemUsesCrypto, 0178 this, &ProgressManager::progressItemUsesCrypto ); 0179 connect ( t, &ProgressItem::progressItemUsesBusyIndicator, 0180 this, &ProgressManager::progressItemUsesBusyIndicator ); 0181 0182 emit progressItemAdded( t ); 0183 } else { 0184 // Hm, is this what makes the most sense? 0185 t = mTransactions.value( id ); 0186 } 0187 return t; 0188 } 0189 0190 ProgressItem *ProgressManager::createProgressItemImpl( const QString &parent, 0191 const QString &id, 0192 const QString &label, 0193 const QString &status, 0194 bool canBeCanceled, 0195 bool usesCrypto ) 0196 { 0197 ProgressItem *p = mTransactions.value( parent ); 0198 return createProgressItemImpl( p, id, label, status, canBeCanceled, usesCrypto ); 0199 } 0200 0201 void ProgressManager::emitShowProgressDialogImpl() 0202 { 0203 emit showProgressDialog(); 0204 } 0205 0206 // slots 0207 0208 void ProgressManager::slotTransactionCompleted( ProgressItem *item ) 0209 { 0210 mTransactions.remove( item->id() ); 0211 emit progressItemCompleted( item ); 0212 } 0213 0214 void ProgressManager::slotStandardCancelHandler( ProgressItem *item ) 0215 { 0216 item->setComplete(); 0217 } 0218 0219 ProgressItem *ProgressManager::singleItem() const 0220 { 0221 ProgressItem *item = nullptr; 0222 for (ProgressItem* transactionItem : mTransactions) { 0223 // No single item for progress possible, as one of them is a busy indicator one. 0224 if (transactionItem->usesBusyIndicator()) 0225 return nullptr; 0226 0227 if (!transactionItem->parent()) { // if it's a top level one, only those count 0228 if ( item ) { 0229 return nullptr; // we found more than one 0230 } else { 0231 item = transactionItem; 0232 } 0233 } 0234 } 0235 return item; 0236 } 0237 0238 void ProgressManager::slotAbortAll() 0239 { 0240 QHashIterator<QString, ProgressItem *> it(mTransactions); 0241 while (it.hasNext()) { 0242 it.next(); 0243 it.value()->cancel(); 0244 } 0245 0246 } 0247 0248 } // namespace 0249 0250 #include "moc_progressmanager.cpp"