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   // always interpret the label text as RichText, but disable word wrapping
00161   mItemLabel->setTextFormat( Qt::RichText );
00162   mItemLabel->setAlignment( Qt::AlignAuto | Qt::AlignVCenter | Qt::SingleLine );
00163   h->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00164 
00165   mProgress = new QProgressBar( 100, h );
00166   mProgress->setProgress( item->progress() );
00167 
00168   if ( item->canBeCanceled() ) {
00169     mCancelButton = new QPushButton( SmallIcon( "cancel" ), QString::null, h );
00170     QToolTip::add( mCancelButton, i18n("Cancel this operation.") );
00171     connect ( mCancelButton, SIGNAL( clicked() ),
00172               this, SLOT( slotItemCanceled() ));
00173   }
00174   
00175   h = new QHBox( this );
00176   h->setSpacing( 5 );
00177   h->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00178   mSSLLabel = new SSLLabel( h );
00179   mSSLLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
00180   mItemStatus = new QLabel( item->status(), h );
00181   // always interpret the status text as RichText, but disable word wrapping
00182   mItemStatus->setTextFormat( Qt::RichText );
00183   mItemStatus->setAlignment( Qt::AlignAuto | Qt::AlignVCenter | Qt::SingleLine );
00184   setCrypto( item->usesCrypto() );
00185   if( first ) hideHLine();
00186 }
00187 
00188 TransactionItem::~TransactionItem()
00189 {
00190 }
00191 
00192 void TransactionItem::hideHLine()
00193 {
00194     mFrame->hide();
00195 }
00196 
00197 void TransactionItem::setProgress( int progress )
00198 {
00199   mProgress->setProgress( progress );
00200 }
00201 
00202 void TransactionItem::setLabel( const QString& label )
00203 {
00204   mItemLabel->setText( label );
00205 }
00206 
00207 void TransactionItem::setStatus( const QString& status )
00208 {
00209   mItemStatus->setText( status );
00210 }
00211 
00212 void TransactionItem::setCrypto( bool on )
00213 {
00214   if (on)
00215     mSSLLabel->setEncrypted( true );
00216   else
00217     mSSLLabel->setEncrypted( false );
00218 
00219   mSSLLabel->setState( mSSLLabel->lastState() );
00220 }
00221 
00222 void TransactionItem::slotItemCanceled()
00223 {
00224   if ( mItem )
00225     mItem->cancel();
00226 }
00227 
00228 
00229 void TransactionItem::addSubTransaction( ProgressItem* /*item*/ )
00230 {
00231 
00232 }
00233 
00234 
00235 // ---------------------------------------------------------------------------
00236 
00237 ProgressDialog::ProgressDialog( QWidget* alignWidget, QWidget* parent, const char* name )
00238     : OverlayWidget( alignWidget, parent, name ), mWasLastShown( false )
00239 {
00240     setFrameStyle( QFrame::Panel | QFrame::Sunken ); // QFrame
00241     setSpacing( 0 ); // QHBox
00242     setMargin( 1 );
00243 
00244     mScrollView = new TransactionItemView( this, "ProgressScrollView" );
00245 
00246     // No more close button for now, since there is no more autoshow
00247     /*
00248     QVBox* rightBox = new QVBox( this );
00249     QToolButton* pbClose = new QToolButton( rightBox );
00250     pbClose->setAutoRaise(true);
00251     pbClose->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
00252     pbClose->setFixedSize( 16, 16 );
00253     pbClose->setIconSet( KGlobal::iconLoader()->loadIconSet( "fileclose", KIcon::Small, 14 ) );
00254     QToolTip::add( pbClose, i18n( "Hide detailed progress window" ) );
00255     connect(pbClose, SIGNAL(clicked()), this, SLOT(slotClose()));
00256     QWidget* spacer = new QWidget( rightBox ); // don't let the close button take up all the height
00257     rightBox->setStretchFactor( spacer, 100 );
00258     */
00259 
00260     /*
00261      * Get the singleton ProgressManager item which will inform us of
00262      * appearing and vanishing items.
00263      */
00264     ProgressManager *pm = ProgressManager::instance();
00265     connect ( pm, SIGNAL( progressItemAdded( KPIM::ProgressItem* ) ),
00266               this, SLOT( slotTransactionAdded( KPIM::ProgressItem* ) ) );
00267     connect ( pm, SIGNAL( progressItemCompleted( KPIM::ProgressItem* ) ),
00268               this, SLOT( slotTransactionCompleted( KPIM::ProgressItem* ) ) );
00269     connect ( pm, SIGNAL( progressItemProgress( KPIM::ProgressItem*, unsigned int ) ),
00270               this, SLOT( slotTransactionProgress( KPIM::ProgressItem*, unsigned int ) ) );
00271     connect ( pm, SIGNAL( progressItemStatus( KPIM::ProgressItem*, const QString& ) ),
00272               this, SLOT( slotTransactionStatus( KPIM::ProgressItem*, const QString& ) ) );
00273     connect ( pm, SIGNAL( progressItemLabel( KPIM::ProgressItem*, const QString& ) ),
00274               this, SLOT( slotTransactionLabel( KPIM::ProgressItem*, const QString& ) ) );
00275     connect ( pm, SIGNAL( progressItemUsesCrypto(KPIM::ProgressItem*, bool) ),
00276               this, SLOT( slotTransactionUsesCrypto( KPIM::ProgressItem*, bool ) ) );
00277     connect ( pm, SIGNAL( showProgressDialog() ),
00278               this, SLOT( slotShow() ) );
00279 }
00280 
00281 void ProgressDialog::closeEvent( QCloseEvent* e )
00282 {
00283   e->accept();
00284   hide();
00285 }
00286 
00287 
00288 /*
00289  *  Destructor
00290  */
00291 ProgressDialog::~ProgressDialog()
00292 {
00293     // no need to delete child widgets.
00294 }
00295 
00296 void ProgressDialog::slotTransactionAdded( ProgressItem *item )
00297 {
00298    TransactionItem *parent = 0;
00299    if ( item->parent() ) {
00300      if ( mTransactionsToListviewItems.contains( item->parent() ) ) {
00301        parent = mTransactionsToListviewItems[ item->parent() ];
00302        parent->addSubTransaction( item );
00303      }
00304    } else {
00305      const bool first = mTransactionsToListviewItems.empty();
00306      TransactionItem *ti = mScrollView->addTransactionItem( item, first );
00307      if ( ti )
00308        mTransactionsToListviewItems.replace( item, ti );
00309      if ( first && mWasLastShown )
00310        QTimer::singleShot( 1000, this, SLOT( slotShow() ) );
00311 
00312    }
00313 }
00314 
00315 void ProgressDialog::slotTransactionCompleted( ProgressItem *item )
00316 {
00317    if ( mTransactionsToListviewItems.contains( item ) ) {
00318      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00319      mTransactionsToListviewItems.remove( item );
00320      ti->setItemComplete();
00321      QTimer::singleShot( 3000, ti, SLOT( deleteLater() ) );
00322      // see the slot for comments as to why that works
00323      connect ( ti, SIGNAL( destroyed() ),
00324                mScrollView, SLOT( slotLayoutFirstItem() ) );
00325    }
00326    // This was the last item, hide.
00327    if ( mTransactionsToListviewItems.empty() )
00328      QTimer::singleShot( 3000, this, SLOT( slotHide() ) );
00329 }
00330 
00331 void ProgressDialog::slotTransactionCanceled( ProgressItem* )
00332 {
00333 }
00334 
00335 void ProgressDialog::slotTransactionProgress( ProgressItem *item,
00336                                               unsigned int progress )
00337 {
00338    if ( mTransactionsToListviewItems.contains( item ) ) {
00339      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00340      ti->setProgress( progress );
00341    }
00342 }
00343 
00344 void ProgressDialog::slotTransactionStatus( ProgressItem *item,
00345                                             const QString& status )
00346 {
00347    if ( mTransactionsToListviewItems.contains( item ) ) {
00348      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00349      ti->setStatus( status );
00350    }
00351 }
00352 
00353 void ProgressDialog::slotTransactionLabel( ProgressItem *item,
00354                                            const QString& label )
00355 {
00356    if ( mTransactionsToListviewItems.contains( item ) ) {
00357      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00358      ti->setLabel( label );
00359    }
00360 }
00361 
00362 
00363 void ProgressDialog::slotTransactionUsesCrypto( ProgressItem *item,
00364                                                 bool value )
00365 {
00366    if ( mTransactionsToListviewItems.contains( item ) ) {
00367      TransactionItem *ti = mTransactionsToListviewItems[ item ];
00368      ti->setCrypto( value );
00369    }
00370 }
00371 
00372 void ProgressDialog::slotShow()
00373 {
00374    setVisible( true );
00375 }
00376 
00377 void ProgressDialog::slotHide()
00378 {
00379   // check if a new item showed up since we started the timer. If not, hide
00380   if ( mTransactionsToListviewItems.isEmpty() ) {
00381     setVisible( false );
00382   }
00383 }
00384 
00385 void ProgressDialog::slotClose()
00386 {
00387   mWasLastShown = false;
00388   setVisible( false );
00389 }
00390 
00391 void ProgressDialog::setVisible( bool b )
00392 {
00393   if ( b )
00394     show();
00395   else
00396     hide();
00397   emit visibilityChanged( b );
00398 }
00399 
00400 void ProgressDialog::slotToggleVisibility()
00401 {
00402   /* Since we are only hiding with a timeout, there is a short period of
00403    * time where the last item is still visible, but clicking on it in
00404    * the statusbarwidget should not display the dialog, because there
00405    * are no items to be shown anymore. Guard against that.
00406    */
00407   mWasLastShown = !isShown();
00408   if ( isShown() || !mTransactionsToListviewItems.isEmpty() )
00409     setVisible( !isShown() );
00410 }
00411 
00412 }
00413 
00414 #include "progressdialog.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys