libkdepim

progressdialog.cpp

00001 
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 
00036 #include <tqapplication.h>
00037 #include <tqlayout.h>
00038 #include <tqprogressbar.h>
00039 #include <tqtimer.h>
00040 #include <tqheader.h>
00041 #include <tqobject.h>
00042 #include <tqscrollview.h>
00043 #include <tqtoolbutton.h>
00044 #include <tqpushbutton.h>
00045 #include <tqvbox.h>
00046 #include <tqtooltip.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 <tqwhatsthis.h>
00058 
00059 namespace KPIM {
00060 
00061 class TransactionItem;
00062 
00063 TransactionItemView::TransactionItemView( TQWidget * parent,
00064                                           const char * name,
00065                                           WFlags f )
00066     : TQScrollView( parent, name, f ) {
00067   setFrameStyle( NoFrame );
00068   mBigBox = new TQVBox( viewport() );
00069   mBigBox->setSpacing( 5 );
00070   addChild( mBigBox );
00071   setResizePolicy( TQScrollView::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    TQTimer::singleShot( 1000, ti, TQT_SLOT( show() ) );
00079    return ti;
00080 }
00081 
00082 void TransactionItemView::resizeContents( int w, int h )
00083 {
00084   // (handling of TQEvent::LayoutHint in TQScrollView calls this method)
00085   //kdDebug(5300) << k_funcinfo << w << "," << h << endl;
00086   TQScrollView::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   TQApplication::sendPostedEvents( 0, TQEvent::ChildInserted );
00093   TQApplication::sendPostedEvents( 0, TQEvent::LayoutHint );
00094   TQSize 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 TQSize TransactionItemView::sizeHint() const
00103 {
00104   return minimumSizeHint();
00105 }
00106 
00107 TQSize 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   TQSize 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 TQObject. 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   TQObject *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( TQWidget* parent,
00143                                   ProgressItem *item, bool first )
00144   : TQVBox( parent, "TransactionItem" ), mCancelButton( 0 ), mItem( item )
00145 
00146 {
00147   setSpacing( 2 );
00148   setMargin( 2 );
00149   setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
00150 
00151   mFrame = new TQFrame( this );
00152   mFrame->setFrameShape( TQFrame::HLine );
00153   mFrame->setFrameShadow( TQFrame::Raised );
00154   mFrame->show();
00155   setStretchFactor( mFrame, 3 );
00156 
00157   TQHBox *h = new TQHBox( this );
00158   h->setSpacing( 5 );
00159 
00160   mItemLabel = new TQLabel( 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( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
00165 
00166   mProgress = new TQProgressBar( 100, h );
00167   mProgress->setProgress( item->progress() );
00168 
00169   if ( item->canBeCanceled() ) {
00170     mCancelButton = new TQPushButton( SmallIcon( "cancel" ), TQString::null, h );
00171     TQToolTip::add( mCancelButton, i18n("Cancel this operation.") );
00172     connect ( mCancelButton, TQT_SIGNAL( clicked() ),
00173               this, TQT_SLOT( slotItemCanceled() ));
00174   }
00175 
00176   h = new TQHBox( this );
00177   h->setSpacing( 5 );
00178   h->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
00179   mSSLLabel = new SSLLabel( h );
00180   mSSLLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
00181   mItemStatus = new TQLabel( 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( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::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 TQString& label )
00208 {
00209   mItemLabel->setText( label );
00210 }
00211 
00212 void TransactionItem::setStatus( const TQString& 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::setTotalSteps( int totalSteps )
00228 {
00229   mProgress->setTotalSteps( totalSteps );
00230 }
00231 
00232 void TransactionItem::slotItemCanceled()
00233 {
00234   if ( mItem )
00235     mItem->cancel();
00236 }
00237 
00238 
00239 void TransactionItem::addSubTransaction( ProgressItem* /*item*/ )
00240 {
00241 
00242 }
00243 
00244 
00245 // ---------------------------------------------------------------------------
00246 
00247 ProgressDialog::ProgressDialog( TQWidget* alignWidget, TQWidget* parent, const char* name )
00248     : OverlayWidget( alignWidget, parent, name ), mWasLastShown( false )
00249 {
00250     setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); // QFrame
00251     setSpacing( 0 ); // QHBox
00252     setMargin( 1 );
00253 
00254     mScrollView = new TransactionItemView( this, "ProgressScrollView" );
00255 
00256     // No more close button for now, since there is no more autoshow
00257     /*
00258     TQVBox* rightBox = new TQVBox( this );
00259     TQToolButton* pbClose = new TQToolButton( rightBox );
00260     pbClose->setAutoRaise(true);
00261     pbClose->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
00262     pbClose->setFixedSize( 16, 16 );
00263     pbClose->setIconSet( KGlobal::iconLoader()->loadIconSet( "fileclose", KIcon::Small, 14 ) );
00264     TQToolTip::add( pbClose, i18n( "Hide detailed progress window" ) );
00265     connect(pbClose, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotClose()));
00266     TQWidget* spacer = new TQWidget( rightBox ); // don't let the close button take up all the height
00267     rightBox->setStretchFactor( spacer, 100 );
00268     */
00269 
00270     /*
00271      * Get the singleton ProgressManager item which will inform us of
00272      * appearing and vanishing items.
00273      */
00274     ProgressManager *pm = ProgressManager::instance();
00275     connect ( pm, TQT_SIGNAL( progressItemAdded( KPIM::ProgressItem* ) ),
00276               this, TQT_SLOT( slotTransactionAdded( KPIM::ProgressItem* ) ) );
00277     connect ( pm, TQT_SIGNAL( progressItemCompleted( KPIM::ProgressItem* ) ),
00278               this, TQT_SLOT( slotTransactionCompleted( KPIM::ProgressItem* ) ) );
00279     connect ( pm, TQT_SIGNAL( progressItemProgress( KPIM::ProgressItem*, unsigned int ) ),
00280               this, TQT_SLOT( slotTransactionProgress( KPIM::ProgressItem*, unsigned int ) ) );
00281     connect ( pm, TQT_SIGNAL( progressItemStatus( KPIM::ProgressItem*, const TQString& ) ),
00282               this, TQT_SLOT( slotTransactionStatus( KPIM::ProgressItem*, const TQString& ) ) );
00283     connect ( pm, TQT_SIGNAL( progressItemLabel( KPIM::ProgressItem*, const TQString& ) ),
00284               this, TQT_SLOT( slotTransactionLabel( KPIM::ProgressItem*, const TQString& ) ) );
00285     connect ( pm, TQT_SIGNAL( progressItemUsesCrypto(KPIM::ProgressItem*, bool) ),
00286               this, TQT_SLOT( slotTransactionUsesCrypto( KPIM::ProgressItem*, bool ) ) );
00287     connect ( pm, TQT_SIGNAL( progressItemUsesBusyIndicator(KPIM::ProgressItem*, bool) ),
00288               this, TQT_SLOT( slotTransactionUsesBusyIndicator( KPIM::ProgressItem*, bool ) ) );
00289     connect ( pm, TQT_SIGNAL( showProgressDialog() ),
00290               this, TQT_SLOT( slotShow() ) );
00291 }
00292 
00293 void ProgressDialog::closeEvent( TQCloseEvent* e )
00294 {
00295   e->accept();
00296   hide();
00297 }
00298 
00299 
00300 /*
00301  *  Destructor
00302  */
00303 ProgressDialog::~ProgressDialog()
00304 {
00305     // no need to delete child widgets.
00306 }
00307 
00308 void ProgressDialog::slotTransactionAdded( ProgressItem *item )
00309 {
00310    TransactionItem *parent = 0;
00311    if ( item->parent() ) {
00312      if ( mTransactionsToListviewItems.contains( item->parent() ) ) {
00313        parent = mTransactionsToListviewItems[ item->parent() ];
00314        parent->addSubTransaction( item );
00315      }
00316    } else {
00317      const bool first = mTransactionsToListviewItems.empty();
00318      TransactionItem *ti = mScrollView->addTransactionItem( item, first );
00319      if ( ti )
00320        mTransactionsToListviewItems.replace( item, ti );
00321      if ( first && mWasLastShown )
00322        TQTimer::singleShot( 1000, this, TQT_SLOT( slotShow() ) );
00323 
00324    }
00325 }
00326 
00327 void ProgressDialog::slotTransactionCompleted( ProgressItem *item )
00328 {
00329    if ( mTransactionsToListviewItems.contains( item ) ) {
00330      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00331      mTransactionsToListviewItems.remove( item );
00332      ti->setItemComplete();
00333      TQTimer::singleShot( 3000, ti, TQT_SLOT( deleteLater() ) );
00334      // see the slot for comments as to why that works
00335      connect ( ti, TQT_SIGNAL( destroyed() ),
00336                mScrollView, TQT_SLOT( slotLayoutFirstItem() ) );
00337    }
00338    // This was the last item, hide.
00339    if ( mTransactionsToListviewItems.empty() )
00340      TQTimer::singleShot( 3000, this, TQT_SLOT( slotHide() ) );
00341 }
00342 
00343 void ProgressDialog::slotTransactionCanceled( ProgressItem* )
00344 {
00345 }
00346 
00347 void ProgressDialog::slotTransactionProgress( ProgressItem *item,
00348                                               unsigned int progress )
00349 {
00350    if ( mTransactionsToListviewItems.contains( item ) ) {
00351      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00352      ti->setProgress( progress );
00353    }
00354 }
00355 
00356 void ProgressDialog::slotTransactionStatus( ProgressItem *item,
00357                                             const TQString& status )
00358 {
00359    if ( mTransactionsToListviewItems.contains( item ) ) {
00360      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00361      ti->setStatus( status );
00362    }
00363 }
00364 
00365 void ProgressDialog::slotTransactionLabel( ProgressItem *item,
00366                                            const TQString& label )
00367 {
00368    if ( mTransactionsToListviewItems.contains( item ) ) {
00369      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00370      ti->setLabel( label );
00371    }
00372 }
00373 
00374 
00375 void ProgressDialog::slotTransactionUsesCrypto( ProgressItem *item,
00376                                                 bool value )
00377 {
00378    if ( mTransactionsToListviewItems.contains( item ) ) {
00379      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00380      ti->setCrypto( value );
00381    }
00382 }
00383 
00384 void ProgressDialog::slotTransactionUsesBusyIndicator( KPIM::ProgressItem *item, bool value )
00385 {
00386   if ( mTransactionsToListviewItems.contains( item ) ) {
00387      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00388      if ( value )
00389        ti->setTotalSteps( 0 );
00390      else
00391        ti->setTotalSteps( 100 );
00392   }
00393 }
00394 
00395 void ProgressDialog::slotShow()
00396 {
00397    setVisible( true );
00398 }
00399 
00400 void ProgressDialog::slotHide()
00401 {
00402   // check if a new item showed up since we started the timer. If not, hide
00403   if ( mTransactionsToListviewItems.isEmpty() ) {
00404     setVisible( false );
00405   }
00406 }
00407 
00408 void ProgressDialog::slotClose()
00409 {
00410   mWasLastShown = false;
00411   setVisible( false );
00412 }
00413 
00414 void ProgressDialog::setVisible( bool b )
00415 {
00416   if ( b )
00417     show();
00418   else
00419     hide();
00420   emit visibilityChanged( b );
00421 }
00422 
00423 void ProgressDialog::slotToggleVisibility()
00424 {
00425   /* Since we are only hiding with a timeout, there is a short period of
00426    * time where the last item is still visible, but clicking on it in
00427    * the statusbarwidget should not display the dialog, because there
00428    * are no items to be shown anymore. Guard against that.
00429    */
00430   mWasLastShown = !isShown();
00431   if ( isShown() || !mTransactionsToListviewItems.isEmpty() )
00432     setVisible( !isShown() );
00433 }
00434 
00435 }
00436 
00437 #include "progressdialog.moc"