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 }