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( TQMAX( sz.width(), minw ) + f + vsbExt ); 00116 sz.setHeight( TQMIN( sz.height(), maxh ) + f ); 00117 return sz; 00118 } 00119 00120 00121 void TransactionItemView::slotLayoutFirstItem() 00122 { 00123 /* 00124 The below relies on some details in TQt'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( TQt::RichText ); 00163 mItemLabel->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::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(), 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( TQt::RichText ); 00184 mItemStatus->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::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 ); // TQFrame 00251 setSpacing( 0 ); // TQHBox 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"