File indexing completed on 2024-05-05 04:49:22
0001 /**************************************************************************************** 0002 * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #include "CompoundProgressBar.h" 0018 0019 #include "core/support/Debug.h" 0020 0021 #include <QIcon> 0022 #include <QMutexLocker> 0023 0024 #include <KLocalizedString> 0025 0026 0027 CompoundProgressBar::CompoundProgressBar( QWidget *parent ) 0028 : ProgressBar( parent ) 0029 , m_mutex( QMutex::Recursive ) 0030 { 0031 m_progressDetailsWidget = new PopupWidget(); 0032 m_progressDetailsWidget->hide(); 0033 0034 connect( cancelButton(), &QAbstractButton::clicked, this, &CompoundProgressBar::cancelAll ); 0035 } 0036 0037 CompoundProgressBar::~CompoundProgressBar() 0038 { 0039 delete m_progressDetailsWidget; 0040 m_progressDetailsWidget = nullptr; 0041 } 0042 0043 void CompoundProgressBar::addProgressBar( ProgressBar *childBar, QObject *owner ) 0044 { 0045 QMutexLocker locker( &m_mutex ); 0046 0047 m_progressMap.insert( owner, childBar ); 0048 m_progressDetailsWidget->layout()->addWidget( childBar ); 0049 if( m_progressDetailsWidget->width() < childBar->width() ) 0050 m_progressDetailsWidget->setMinimumWidth( childBar->width() ); 0051 0052 m_progressDetailsWidget->setMinimumHeight( childBar->height() * m_progressMap.count() + 8 ); 0053 0054 m_progressDetailsWidget->reposition(); 0055 0056 connect( childBar, &ProgressBar::percentageChanged, 0057 this, &CompoundProgressBar::childPercentageChanged ); 0058 connect( childBar, &ProgressBar::cancelled, 0059 this, &CompoundProgressBar::childBarCancelled ); 0060 connect( childBar, &ProgressBar::complete, 0061 this, &CompoundProgressBar::childBarComplete ); 0062 connect( owner, &QObject::destroyed, this, &CompoundProgressBar::slotObjectDestroyed ); 0063 0064 if( m_progressMap.count() == 1 ) 0065 { 0066 setDescription( childBar->descriptionLabel()->text() ); 0067 cancelButton()->setToolTip( i18n( "Abort" ) ); 0068 } 0069 else 0070 { 0071 setDescription( i18n( "Multiple background tasks running (click to show)" ) ); 0072 cancelButton()->setToolTip( i18n( "Abort all background tasks" ) ); 0073 } 0074 0075 cancelButton()->setHidden( false ); 0076 } 0077 0078 void CompoundProgressBar::endProgressOperation( QObject *owner ) 0079 { 0080 QMutexLocker locker( &m_mutex ); 0081 0082 if( !m_progressMap.contains( owner ) ) 0083 return ; 0084 0085 childBarComplete( m_progressMap.value( owner ) ); 0086 } 0087 0088 void 0089 CompoundProgressBar::slotIncrementProgress() 0090 { 0091 incrementProgress( sender() ); 0092 } 0093 0094 void CompoundProgressBar::incrementProgress( const QObject *owner ) 0095 { 0096 QMutexLocker locker( &m_mutex ); 0097 0098 if( !m_progressMap.contains( owner ) ) 0099 return ; 0100 0101 m_progressMap.value( owner )->setValue( m_progressMap.value( owner )->value() + 1 ); 0102 } 0103 0104 void CompoundProgressBar::setProgress( const QObject *owner, int steps ) 0105 { 0106 QMutexLocker locker( &m_mutex ); 0107 0108 if( !m_progressMap.contains( owner ) ) 0109 return ; 0110 0111 m_progressMap.value( owner )->setValue( steps ); 0112 } 0113 0114 void 0115 CompoundProgressBar::mousePressEvent( QMouseEvent *event ) 0116 { 0117 QMutexLocker locker( &m_mutex ); 0118 0119 if( m_progressDetailsWidget->isHidden() ) 0120 { 0121 if( m_progressMap.count() ) 0122 showDetails(); 0123 } 0124 else 0125 { 0126 hideDetails(); 0127 } 0128 0129 event->accept(); 0130 } 0131 0132 void CompoundProgressBar::setProgressTotalSteps( const QObject *owner, int value ) 0133 { 0134 QMutexLocker locker( &m_mutex ); 0135 0136 if( !m_progressMap.contains( owner ) ) 0137 return ; 0138 0139 m_progressMap.value( owner )->setMaximum( value ); 0140 } 0141 0142 void CompoundProgressBar::setProgressStatus( const QObject *owner, const QString &text ) 0143 { 0144 QMutexLocker locker( &m_mutex ); 0145 0146 if( !m_progressMap.contains( owner ) ) 0147 return ; 0148 0149 m_progressMap.value( owner )->setDescription( text ); 0150 } 0151 0152 void CompoundProgressBar::childPercentageChanged() 0153 { 0154 progressBar()->setValue( calcCompoundPercentage() ); 0155 } 0156 0157 void CompoundProgressBar::childBarCancelled( ProgressBar *childBar ) 0158 { 0159 childBarFinished( childBar ); 0160 } 0161 0162 void CompoundProgressBar::childBarComplete( ProgressBar *childBar ) 0163 { 0164 childBarFinished( childBar ); 0165 } 0166 0167 void CompoundProgressBar::slotObjectDestroyed( QObject *object ) 0168 { 0169 QMutexLocker locker( &m_mutex ); 0170 0171 if( m_progressMap.contains( object ) ) 0172 { 0173 childBarFinished( m_progressMap.value( object ) ); 0174 } 0175 } 0176 0177 void CompoundProgressBar::childBarFinished( ProgressBar *bar ) 0178 { 0179 QMutexLocker locker( &m_mutex ); 0180 0181 QObject *owner = const_cast<QObject *>( m_progressMap.key( bar ) ); 0182 owner->disconnect( this ); 0183 owner->disconnect( bar ); 0184 m_progressMap.remove( owner ); 0185 m_progressDetailsWidget->layout()->removeWidget( bar ); 0186 m_progressDetailsWidget->setFixedHeight( bar->height() * m_progressMap.count() + 8 ); 0187 m_progressDetailsWidget->reposition(); 0188 delete bar; 0189 0190 if( m_progressMap.count() == 1 ) 0191 { 0192 //only one job still running, so no need to use the details widget any more. 0193 //Also set the text to the description of 0194 //the job instead of the "Multiple background tasks running" text. 0195 setDescription( m_progressMap.values().at( 0 )->descriptionLabel()->text() ); 0196 cancelButton()->setToolTip( i18n( "Abort" ) ); 0197 hideDetails(); 0198 } 0199 else if( m_progressMap.empty() ) 0200 { 0201 progressBar()->setValue( 0 ); 0202 hideDetails(); 0203 Q_EMIT( allDone() ); 0204 return; 0205 } 0206 else 0207 { 0208 setDescription( i18n( "Multiple background tasks running (click to show)" ) ); 0209 cancelButton()->setToolTip( i18n( "Abort all background tasks" ) ); 0210 } 0211 0212 progressBar()->setValue( calcCompoundPercentage() ); 0213 } 0214 0215 int CompoundProgressBar::calcCompoundPercentage() 0216 { 0217 QMutexLocker locker( &m_mutex ); 0218 0219 int count = m_progressMap.count(); 0220 int total = 0; 0221 0222 foreach( ProgressBar *currentBar, m_progressMap ) 0223 total += currentBar->percentage(); 0224 0225 return count == 0 ? 0 : total / count; 0226 } 0227 0228 void CompoundProgressBar::cancelAll() 0229 { 0230 QMutexLocker locker( &m_mutex ); 0231 0232 foreach( ProgressBar *currentBar, m_progressMap ) 0233 currentBar->cancel(); 0234 } 0235 0236 void CompoundProgressBar::showDetails() 0237 { 0238 QMutexLocker locker( &m_mutex ); 0239 0240 m_progressDetailsWidget->raise(); 0241 0242 //Hack to make sure it has the right height first time it is shown... 0243 m_progressDetailsWidget->setFixedHeight( 0244 m_progressMap.values().at( 0 )->height() * m_progressMap.count() + 8 ); 0245 m_progressDetailsWidget->reposition(); 0246 m_progressDetailsWidget->show(); 0247 } 0248 0249 void CompoundProgressBar::hideDetails() 0250 { 0251 m_progressDetailsWidget->hide(); 0252 } 0253 0254 void CompoundProgressBar::toggleDetails() 0255 { 0256 if( m_progressDetailsWidget->isVisible() ) 0257 hideDetails(); 0258 else 0259 showDetails(); 0260 }