libkdepim

progressdialog.cpp

00001 
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 
00036 #include <qapplication.h>
00037 #include <qlayout.h>
00038 #include <qprogressbar.h>
00039 #include <qtimer.h>
00040 #include <qheader.h>
00041 #include <qobject.h>
00042 #include <qscrollview.h>
00043 #include <qtoolbutton.h>
00044 #include <qpushbutton.h>
00045 #include <qvbox.h>
00046 #include <qtooltip.h>
00047 
00048 #include <klocale.h>
00049 #include <kdialog.h>
00050 #include <kstdguiitem.h>
00051 #include <kiconloader.h>
00052 #include <kdebug.h>
00053 
00054 #include "progressdialog.h"
00055 #include "progressmanager.h"
00056 #include "ssllabel.h"
00057 #include <qwhatsthis.h>
00058 
00059 namespace KPIM {
00060 
00061 class TransactionItem;
00062 
00063 TransactionItemView::TransactionItemView( QWidget * parent,
00064                                           const char * name,
00065                                           WFlags f )
00066     : QScrollView( parent, name, f ) {
00067   setFrameStyle( NoFrame );
00068   mBigBox = new QVBox( viewport() );
00069   mBigBox->setSpacing( 5 );
00070   addChild( mBigBox );
00071   setResizePolicy( QScrollView::AutoOneFit ); // Fit so that the box expands horizontally
00072 }
00073 
00074 TransactionItem* TransactionItemView::addTransactionItem( ProgressItem* item, bool first )
00075 {
00076    TransactionItem *ti = new TransactionItem( mBigBox, item, first );
00077    ti->hide();
00078    QTimer::singleShot( 1000, ti, SLOT( show() ) );
00079    return ti;
00080 }
00081 
00082 void TransactionItemView::resizeContents( int w, int h )
00083 {
00084   //kdDebug(5300) << k_funcinfo << w << "," << h << endl;
00085   QScrollView::resizeContents( w, h );
00086   // Tell the layout in the parent (progressdialog) that our size changed
00087   updateGeometry();
00088   // Resize the parent (progressdialog) - this works but resize horizontally too often
00089   //parentWidget()->adjustSize();
00090 
00091   QApplication::sendPostedEvents( 0, QEvent::ChildInserted );
00092   QApplication::sendPostedEvents( 0, QEvent::LayoutHint );
00093   QSize sz = parentWidget()->sizeHint();
00094   int currentWidth = parentWidget()->width();
00095   // Don't resize to sz.width() every time when it only reduces a little bit
00096   if ( currentWidth < sz.width() || currentWidth > sz.width() + 100 )
00097     currentWidth = sz.width();
00098   parentWidget()->resize( currentWidth, sz.height() );
00099 }
00100 
00101 QSize TransactionItemView::sizeHint() const
00102 {
00103   return minimumSizeHint();
00104 }
00105 
00106 QSize TransactionItemView::minimumSizeHint() const
00107 {
00108   int f = 2 * frameWidth();
00109   // Make room for a vertical scrollbar in all cases, to avoid a horizontal one
00110   int vsbExt = verticalScrollBar()->sizeHint().width();
00111   int minw = topLevelWidget()->width() / 3;
00112   int maxh = topLevelWidget()->height() / 2;
00113   QSize sz( mBigBox->minimumSizeHint() );
00114   sz.setWidth( QMAX( sz.width(), minw ) + f + vsbExt );
00115   sz.setHeight( QMIN( sz.height(), maxh ) + f );
00116   return sz;
00117 }
00118 
00119 
00120 void TransactionItemView::slotLayoutFirstItem()
00121 {
00122   /*
00123      The below relies on some details in Qt's behaviour regarding deleting
00124      objects. This slot is called from the destroyed signal of an item just
00125      going away. That item is at that point still in the  list of chilren, but
00126      since the vtable is already gone, it will have type QObject. The first
00127      one with both the right name and the right class therefor is what will
00128      be the first item very shortly. That's the one we want to remove the
00129      hline for.
00130   */
00131   QObject *o = mBigBox->child( "TransactionItem", "KPIM::TransactionItem" );
00132   TransactionItem *ti = dynamic_cast<TransactionItem*>( o );
00133   if ( ti ) {
00134     ti->hideHLine();
00135   }
00136 }
00137 
00138 
00139 // ----------------------------------------------------------------------------
00140 
00141 TransactionItem::TransactionItem( QWidget* parent,
00142                                   ProgressItem *item, bool first )
00143   : QVBox( parent, "TransactionItem" ), mCancelButton( 0 ), mItem( item )
00144 
00145 {
00146   setSpacing( 2 );
00147   setMargin( 2 );
00148   setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00149 
00150   mFrame = new QFrame( this );
00151   mFrame->setFrameShape( QFrame::HLine );
00152   mFrame->setFrameShadow( QFrame::Raised );
00153   mFrame->show();
00154   setStretchFactor( mFrame, 3 );
00155 
00156   QHBox *h = new QHBox( this );
00157   h->setSpacing( 5 );
00158 
00159   mItemLabel = new QLabel( item->label(), h );
00160   h->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00161 
00162   mProgress = new QProgressBar( 100, h );
00163   mProgress->setProgress( item->progress() );
00164 
00165   if ( item->canBeCanceled() ) {
00166     mCancelButton = new QPushButton( SmallIcon( "cancel" ), QString::null, h );
00167     QToolTip::add( mCancelButton, i18n("Cancel this operation.") );
00168     connect ( mCancelButton, SIGNAL( clicked() ),
00169               this, SLOT( slotItemCanceled() ));
00170   }
00171   
00172   h = new QHBox( this );
00173   h->setSpacing( 5 );
00174   h->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00175   mSSLLabel = new SSLLabel( h );
00176   mSSLLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
00177   mItemStatus =  new QLabel( item->status(), h );
00178   setCrypto( item->usesCrypto() );
00179   if( first ) hideHLine();
00180 }
00181 
00182 TransactionItem::~TransactionItem()
00183 {
00184 }
00185 
00186 void TransactionItem::hideHLine()
00187 {
00188     mFrame->hide();
00189 }
00190 
00191 void TransactionItem::setProgress( int progress )
00192 {
00193   mProgress->setProgress( progress );
00194 }
00195 
00196 void TransactionItem::setLabel( const QString& label )
00197 {
00198   mItemLabel->setText( label );
00199 }
00200 
00201 void TransactionItem::setStatus( const QString& status )
00202 {
00203   mItemStatus->setText( status );
00204 }
00205 
00206 void TransactionItem::setCrypto( bool on )
00207 {
00208   if (on)
00209     mSSLLabel->setEncrypted( true );
00210   else
00211     mSSLLabel->setEncrypted( false );
00212 
00213   mSSLLabel->setState( mSSLLabel->lastState() );
00214 }
00215 
00216 void TransactionItem::slotItemCanceled()
00217 {
00218   if ( mItem )
00219     mItem->cancel();
00220 }
00221 
00222 
00223 void TransactionItem::addSubTransaction( ProgressItem* /*item*/ )
00224 {
00225 
00226 }
00227 
00228 
00229 // ---------------------------------------------------------------------------
00230 
00231 ProgressDialog::ProgressDialog( QWidget* alignWidget, QWidget* parent, const char* name )
00232     : OverlayWidget( alignWidget, parent, name ), mWasLastShown( false )
00233 {
00234     setFrameStyle( QFrame::Panel | QFrame::Sunken ); // QFrame
00235     setSpacing( 0 ); // QHBox
00236     setMargin( 1 );
00237 
00238     mScrollView = new TransactionItemView( this, "ProgressScrollView" );
00239 
00240     // No more close button for now, since there is no more autoshow
00241     /*
00242     QVBox* rightBox = new QVBox( this );
00243     QToolButton* pbClose = new QToolButton( rightBox );
00244     pbClose->setAutoRaise(true);
00245     pbClose->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
00246     pbClose->setFixedSize( 16, 16 );
00247     pbClose->setIconSet( KGlobal::iconLoader()->loadIconSet( "fileclose", KIcon::Small, 14 ) );
00248     QToolTip::add( pbClose, i18n( "Hide detailed progress window" ) );
00249     connect(pbClose, SIGNAL(clicked()), this, SLOT(slotClose()));
00250     QWidget* spacer = new QWidget( rightBox ); // don't let the close button take up all the height
00251     rightBox->setStretchFactor( spacer, 100 );
00252     */
00253 
00254     /*
00255      * Get the singleton ProgressManager item which will inform us of
00256      * appearing and vanishing items.
00257      */
00258     ProgressManager *pm = ProgressManager::instance();
00259     connect ( pm, SIGNAL( progressItemAdded( KPIM::ProgressItem* ) ),
00260               this, SLOT( slotTransactionAdded( KPIM::ProgressItem* ) ) );
00261     connect ( pm, SIGNAL( progressItemCompleted( KPIM::ProgressItem* ) ),
00262               this, SLOT( slotTransactionCompleted( KPIM::ProgressItem* ) ) );
00263     connect ( pm, SIGNAL( progressItemProgress( KPIM::ProgressItem*, unsigned int ) ),
00264               this, SLOT( slotTransactionProgress( KPIM::ProgressItem*, unsigned int ) ) );
00265     connect ( pm, SIGNAL( progressItemStatus( KPIM::ProgressItem*, const QString& ) ),
00266               this, SLOT( slotTransactionStatus( KPIM::ProgressItem*, const QString& ) ) );
00267     connect ( pm, SIGNAL( progressItemLabel( KPIM::ProgressItem*, const QString& ) ),
00268               this, SLOT( slotTransactionLabel( KPIM::ProgressItem*, const QString& ) ) );
00269     connect ( pm, SIGNAL( progressItemUsesCrypto(KPIM::ProgressItem*, bool) ),
00270               this, SLOT( slotTransactionUsesCrypto( KPIM::ProgressItem*, bool ) ) );
00271     connect ( pm, SIGNAL( showProgressDialog() ),
00272               this, SLOT( slotShow() ) );
00273 }
00274 
00275 void ProgressDialog::closeEvent( QCloseEvent* e )
00276 {
00277   e->accept();
00278   hide();
00279 }
00280 
00281 
00282 /*
00283  *  Destructor
00284  */
00285 ProgressDialog::~ProgressDialog()
00286 {
00287     // no need to delete child widgets.
00288 }
00289 
00290 void ProgressDialog::slotTransactionAdded( ProgressItem *item )
00291 {
00292    TransactionItem *parent = 0;
00293    if ( item->parent() ) {
00294      if ( mTransactionsToListviewItems.contains( item->parent() ) ) {
00295        parent = mTransactionsToListviewItems[ item->parent() ];
00296        parent->addSubTransaction( item );
00297      }
00298    } else {
00299      const bool first = mTransactionsToListviewItems.empty();
00300      TransactionItem *ti = mScrollView->addTransactionItem( item, first );
00301      if ( ti )
00302        mTransactionsToListviewItems.replace( item, ti );
00303      if ( first && mWasLastShown )
00304        QTimer::singleShot( 1000, this, SLOT( slotShow() ) );
00305 
00306    }
00307 }
00308 
00309 void ProgressDialog::slotTransactionCompleted( ProgressItem *item )
00310 {
00311    if ( mTransactionsToListviewItems.contains( item ) ) {
00312      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00313      mTransactionsToListviewItems.remove( item );
00314      ti->setItemComplete();
00315      QTimer::singleShot( 3000, ti, SLOT( deleteLater() ) );
00316      // see the slot for comments as to why that works
00317      connect ( ti, SIGNAL( destroyed() ),
00318                mScrollView, SLOT( slotLayoutFirstItem() ) );
00319    }
00320    // This was the last item, hide.
00321    if ( mTransactionsToListviewItems.empty() )
00322      QTimer::singleShot( 3000, this, SLOT( slotHide() ) );
00323 }
00324 
00325 void ProgressDialog::slotTransactionCanceled( ProgressItem* )
00326 {
00327 }
00328 
00329 void ProgressDialog::slotTransactionProgress( ProgressItem *item,
00330                                               unsigned int progress )
00331 {
00332    if ( mTransactionsToListviewItems.contains( item ) ) {
00333      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00334      ti->setProgress( progress );
00335    }
00336 }
00337 
00338 void ProgressDialog::slotTransactionStatus( ProgressItem *item,
00339                                             const QString& status )
00340 {
00341    if ( mTransactionsToListviewItems.contains( item ) ) {
00342      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00343      ti->setStatus( status );
00344    }
00345 }
00346 
00347 void ProgressDialog::slotTransactionLabel( ProgressItem *item,
00348                                            const QString& label )
00349 {
00350    if ( mTransactionsToListviewItems.contains( item ) ) {
00351      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00352      ti->setLabel( label );
00353    }
00354 }
00355 
00356 
00357 void ProgressDialog::slotTransactionUsesCrypto( ProgressItem *item,
00358                                                 bool value )
00359 {
00360    if ( mTransactionsToListviewItems.contains( item ) ) {
00361      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00362      ti->setCrypto( value );
00363    }
00364 }
00365 
00366 void ProgressDialog::slotShow()
00367 {
00368    setVisible( true );
00369 }
00370 
00371 void ProgressDialog::slotHide()
00372 {
00373   // check if a new item showed up since we started the timer. If not, hide
00374   if ( mTransactionsToListviewItems.isEmpty() ) {
00375     setVisible( false );
00376   }
00377 }
00378 
00379 void ProgressDialog::slotClose()
00380 {
00381   mWasLastShown = false;
00382   setVisible( false );
00383 }
00384 
00385 void ProgressDialog::setVisible( bool b )
00386 {
00387   if ( b )
00388     show();
00389   else
00390     hide();
00391   emit visibilityChanged( b );
00392 }
00393 
00394 void ProgressDialog::slotToggleVisibility()
00395 {
00396   /* Since we are only hiding with a timeout, there is a short period of
00397    * time where the last item is still visible, but clicking on it in
00398    * the statusbarwidget should not display the dialog, because there
00399    * are no items to be shown anymore. Guard against that.
00400    */
00401   mWasLastShown = !isShown();
00402   if ( isShown() || !mTransactionsToListviewItems.isEmpty() )
00403     setVisible( !isShown() );
00404 }
00405 
00406 }
00407 
00408 #include "progressdialog.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys