libkdepim

statusbarprogresswidget.cpp

00001 /*
00002   statusbarprogresswidget.cpp
00003 
00004   This file is part of KMail, the KDE mail client.
00005 
00006   (C) 2004 KMail Authors
00007   Includes StatusbarProgressWidget which is based on KIOLittleProgressDlg
00008   by Matt Koss <koss@miesto.sk>
00009 
00010   KMail is free software; you can redistribute it and/or modify it
00011   under the terms of the GNU General Public License, version 2, as
00012   published by the Free Software Foundation.
00013 
00014   KMail is distributed in the hope that it will be useful, but
00015   WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   General Public License for more details.
00018 
00019   You should have received a copy of the GNU General Public License
00020   along with this program; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023   In addition, as a special exception, the copyright holders give
00024   permission to link the code of this program with any edition of
00025   the Qt library by Trolltech AS, Norway (or with modified versions
00026   of Qt that use the same license as Qt), and distribute linked
00027   combinations including the two.  You must obey the GNU General
00028   Public License in all respects for all of the code used other than
00029   Qt.  If you modify this file, you may extend this exception to
00030   your version of the file, but you are not obligated to do so.  If
00031   you do not wish to do so, delete this exception statement from
00032   your version.
00033 */
00034 
00035 
00036 #include "ssllabel.h"
00037 using KPIM::SSLLabel;
00038 #include "progressmanager.h"
00039 using KPIM::ProgressItem;
00040 using KPIM::ProgressManager;
00041 
00042 #include <kprogress.h>
00043 #include <kiconloader.h>
00044 #include <kdebug.h>
00045 
00046 #include <qtimer.h>
00047 #include <qlabel.h>
00048 #include <qpushbutton.h>
00049 #include <qtooltip.h>
00050 #include <klocale.h>
00051 #include <qlayout.h>
00052 #include <qwidgetstack.h>
00053 #include <qframe.h>
00054 
00055 #include "progressdialog.h"
00056 #include "statusbarprogresswidget.h"
00057 
00058 using namespace KPIM;
00059 
00060 //-----------------------------------------------------------------------------
00061 StatusbarProgressWidget::StatusbarProgressWidget( ProgressDialog* progressDialog, QWidget* parent, bool button )
00062   : QFrame( parent ), mCurrentItem( 0 ), mProgressDialog( progressDialog ),
00063     mDelayTimer( 0 ), mBusyTimer( 0 )
00064 {
00065   m_bShowButton = button;
00066   int w = fontMetrics().width( " 999.9 kB/s 00:00:01 " ) + 8;
00067   box = new QHBoxLayout( this, 0, 0 );
00068 
00069   m_pButton = new QPushButton( this );
00070   m_pButton->setSizePolicy( QSizePolicy( QSizePolicy::Minimum,
00071                                          QSizePolicy::Minimum ) );
00072   m_pButton->setPixmap( SmallIcon( "up" ) );
00073   box->addWidget( m_pButton  );
00074   stack = new QWidgetStack( this );
00075   stack->setMaximumHeight( fontMetrics().height() );
00076   box->addWidget( stack );
00077 
00078   m_sslLabel = new SSLLabel( this );
00079   box->addWidget( m_sslLabel );
00080 
00081   QToolTip::add( m_pButton, i18n("Open detailed progress dialog") );
00082 
00083   m_pProgressBar = new KProgress( this );
00084   m_pProgressBar->setLineWidth( 1 );
00085   m_pProgressBar->setFrameStyle( QFrame::Box );
00086   m_pProgressBar->installEventFilter( this );
00087   m_pProgressBar->setMinimumWidth( w );
00088   stack->addWidget( m_pProgressBar, 1 );
00089 
00090   m_pLabel = new QLabel( QString::null, this );
00091   m_pLabel->setAlignment( AlignHCenter | AlignVCenter );
00092   m_pLabel->installEventFilter( this );
00093   m_pLabel->setMinimumWidth( w );
00094   stack->addWidget( m_pLabel, 2 );
00095   m_pButton->setMaximumHeight( fontMetrics().height() );
00096   setMinimumWidth( minimumSizeHint().width() );
00097 
00098   mode = None;
00099   setMode();
00100 
00101   connect( m_pButton, SIGNAL( clicked() ),
00102            progressDialog, SLOT( slotToggleVisibility() ) );
00103 
00104   connect ( ProgressManager::instance(), SIGNAL( progressItemAdded( KPIM::ProgressItem * ) ),
00105             this, SLOT( slotProgressItemAdded( KPIM::ProgressItem * ) ) );
00106   connect ( ProgressManager::instance(), SIGNAL( progressItemCompleted( KPIM::ProgressItem * ) ),
00107             this, SLOT( slotProgressItemCompleted( KPIM::ProgressItem * ) ) );
00108 
00109   connect ( progressDialog, SIGNAL( visibilityChanged( bool )),
00110             this, SLOT( slotProgressDialogVisible( bool ) ) );
00111 
00112   mDelayTimer = new QTimer( this );
00113   connect ( mDelayTimer, SIGNAL( timeout() ),
00114             this, SLOT( slotShowItemDelayed() ) );
00115 }
00116 
00117 // There are three cases: no progressitem, one progressitem (connect to it directly),
00118 // or many progressitems (display busy indicator). Let's call them 0,1,N.
00119 // In slot..Added we can only end up in 1 or N.
00120 // In slot..Removed we can end up in 0, 1, or we can stay in N if we were already.
00121 
00122 void StatusbarProgressWidget::slotProgressItemAdded( ProgressItem *item )
00123 {
00124   if ( item->parent() ) return; // we are only interested in top level items
00125   connectSingleItem(); // if going to 1 item
00126   if ( mCurrentItem ) { // Exactly one item
00127     delete mBusyTimer;
00128     mBusyTimer = 0;
00129     mDelayTimer->start( 1000, true );
00130   }
00131   else { // N items
00132     if ( !mBusyTimer ) {
00133       mBusyTimer = new QTimer( this );
00134       connect( mBusyTimer, SIGNAL( timeout() ),
00135                this, SLOT( slotBusyIndicator() ) );
00136       mDelayTimer->start( 1000, true );
00137     }
00138   }
00139 }
00140 
00141 void StatusbarProgressWidget::slotProgressItemCompleted( ProgressItem *item )
00142 {
00143   if ( item->parent() ) return; // we are only interested in top level items
00144   connectSingleItem(); // if going back to 1 item
00145   if ( ProgressManager::instance()->isEmpty() ) { // No item
00146     // Done. In 5s the progress-widget will close, then we can clean up the statusbar
00147     QTimer::singleShot( 5000, this, SLOT( slotClean() ) );
00148   } else if ( mCurrentItem ) { // Exactly one item
00149     delete mBusyTimer;
00150     mBusyTimer = 0;
00151     activateSingleItemMode();
00152   }
00153 }
00154 
00155 void StatusbarProgressWidget::connectSingleItem()
00156 {
00157   if ( mCurrentItem ) {
00158     disconnect ( mCurrentItem, SIGNAL( progressItemProgress( KPIM::ProgressItem *, unsigned int ) ),
00159                  this, SLOT( slotProgressItemProgress( KPIM::ProgressItem *, unsigned int ) ) );
00160     mCurrentItem = 0;
00161   }
00162   mCurrentItem = ProgressManager::instance()->singleItem();
00163   if ( mCurrentItem ) {
00164     connect ( mCurrentItem, SIGNAL( progressItemProgress( KPIM::ProgressItem *, unsigned int ) ),
00165               this, SLOT( slotProgressItemProgress( KPIM::ProgressItem *, unsigned int ) ) );
00166   }
00167 }
00168 
00169 void StatusbarProgressWidget::activateSingleItemMode()
00170 {
00171   m_pProgressBar->setTotalSteps( 100 );
00172   m_pProgressBar->setProgress( mCurrentItem->progress() );
00173   m_pProgressBar->setPercentageVisible( true );
00174 }
00175 
00176 void StatusbarProgressWidget::slotShowItemDelayed()
00177 {
00178   bool noItems = ProgressManager::instance()->isEmpty();
00179   if ( mCurrentItem ) {
00180     activateSingleItemMode();
00181   } else if ( !noItems ) { // N items
00182     m_pProgressBar->setTotalSteps( 0 );
00183     m_pProgressBar->setPercentageVisible( false );
00184     Q_ASSERT( mBusyTimer );
00185     if ( mBusyTimer )
00186       mBusyTimer->start( 100 );
00187   }
00188 
00189   if ( !noItems && mode == None ) {
00190     mode = Progress;
00191     setMode();
00192   }
00193 }
00194 
00195 void StatusbarProgressWidget::slotBusyIndicator()
00196 {
00197   int p = m_pProgressBar->progress();
00198   m_pProgressBar->setProgress( p + 10 );
00199 }
00200 
00201 void StatusbarProgressWidget::slotProgressItemProgress( ProgressItem *item, unsigned int value )
00202 {
00203   Q_ASSERT( item == mCurrentItem); // the only one we should be connected to
00204   m_pProgressBar->setProgress( value );
00205 }
00206 
00207 void StatusbarProgressWidget::slotSetSSL( bool ssl )
00208 {
00209   m_sslLabel->setEncrypted( ssl );
00210 }
00211 
00212 void StatusbarProgressWidget::setMode() {
00213   switch ( mode ) {
00214   case None:
00215     if ( m_bShowButton ) {
00216       m_pButton->hide();
00217     }
00218     m_sslLabel->setState( SSLLabel::Done );
00219     // show the empty label in order to make the status bar look better
00220     stack->show();
00221     stack->raiseWidget( m_pLabel );
00222     break;
00223 
00224 #if 0
00225   case Label:
00226     if ( m_bShowButton ) {
00227       m_pButton->show();
00228     }
00229     m_sslLabel->setState( m_sslLabel->lastState() );
00230     stack->show();
00231     stack->raiseWidget( m_pLabel );
00232     break;
00233 #endif
00234 
00235   case Progress:
00236     stack->show();
00237     stack->raiseWidget( m_pProgressBar );
00238     if ( m_bShowButton ) {
00239       m_pButton->show();
00240     }
00241     m_sslLabel->setState( m_sslLabel->lastState() );
00242     break;
00243   }
00244 }
00245 
00246 void StatusbarProgressWidget::slotClean()
00247 {
00248   // check if a new item showed up since we started the timer. If not, clear
00249   if ( ProgressManager::instance()->isEmpty() ) {
00250     m_pProgressBar->setProgress( 0 );
00251     //m_pLabel->clear();
00252     mode = None;
00253     setMode();
00254   }
00255 }
00256 
00257 bool StatusbarProgressWidget::eventFilter( QObject *, QEvent *ev )
00258 {
00259   if ( ev->type() == QEvent::MouseButtonPress ) {
00260     QMouseEvent *e = (QMouseEvent*)ev;
00261 
00262     if ( e->button() == LeftButton && mode != None ) {    // toggle view on left mouse button
00263       // Consensus seems to be that we should show/hide the fancy dialog when the user
00264       // clicks anywhere in the small one.
00265       mProgressDialog->slotToggleVisibility();
00266       return true;
00267     }
00268   }
00269   return false;
00270 }
00271 
00272 void StatusbarProgressWidget::slotProgressDialogVisible( bool b )
00273 {
00274   // Update the hide/show button when the detailed one is shown/hidden
00275   if ( b ) {
00276     m_pButton->setPixmap( SmallIcon( "down" ) );
00277     QToolTip::remove( m_pButton );
00278     QToolTip::add( m_pButton, i18n("Hide detailed progress window") );
00279     setMode();
00280   } else {
00281     m_pButton->setPixmap( SmallIcon( "up" ) );
00282     QToolTip::remove( m_pButton );
00283     QToolTip::add( m_pButton, i18n("Show detailed progress window") );
00284   }
00285 }
00286 
00287 #include "statusbarprogresswidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys