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