summaryrefslogtreecommitdiffstats
path: root/libkdepim/progressdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkdepim/progressdialog.cpp')
-rw-r--r--libkdepim/progressdialog.cpp419
1 files changed, 419 insertions, 0 deletions
diff --git a/libkdepim/progressdialog.cpp b/libkdepim/progressdialog.cpp
new file mode 100644
index 000000000..10a0b868d
--- /dev/null
+++ b/libkdepim/progressdialog.cpp
@@ -0,0 +1,419 @@
+/** -*- c++ -*-
+ * progressdialog.cpp
+ *
+ * Copyright (c) 2004 Till Adam <[email protected]>,
+ * David Faure <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of this program with any edition of
+ * the Qt library by Trolltech AS, Norway (or with modified versions
+ * of Qt that use the same license as Qt), and distribute linked
+ * combinations including the two. You must obey the GNU General
+ * Public License in all respects for all of the code used other than
+ * Qt. If you modify this file, you may extend this exception to
+ * your version of the file, but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from
+ * your version.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qprogressbar.h>
+#include <qtimer.h>
+#include <qheader.h>
+#include <qobject.h>
+#include <qscrollview.h>
+#include <qtoolbutton.h>
+#include <qpushbutton.h>
+#include <qvbox.h>
+#include <qtooltip.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <kstdguiitem.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include "progressdialog.h"
+#include "progressmanager.h"
+#include "ssllabel.h"
+#include <qwhatsthis.h>
+
+namespace KPIM {
+
+class TransactionItem;
+
+TransactionItemView::TransactionItemView( QWidget * parent,
+ const char * name,
+ WFlags f )
+ : QScrollView( parent, name, f ) {
+ setFrameStyle( NoFrame );
+ mBigBox = new QVBox( viewport() );
+ mBigBox->setSpacing( 5 );
+ addChild( mBigBox );
+ setResizePolicy( QScrollView::AutoOneFit ); // Fit so that the box expands horizontally
+}
+
+TransactionItem* TransactionItemView::addTransactionItem( ProgressItem* item, bool first )
+{
+ TransactionItem *ti = new TransactionItem( mBigBox, item, first );
+ ti->hide();
+ QTimer::singleShot( 1000, ti, SLOT( show() ) );
+ return ti;
+}
+
+void TransactionItemView::resizeContents( int w, int h )
+{
+ // (handling of QEvent::LayoutHint in QScrollView calls this method)
+ //kdDebug(5300) << k_funcinfo << w << "," << h << endl;
+ QScrollView::resizeContents( w, h );
+ // Tell the layout in the parent (progressdialog) that our size changed
+ updateGeometry();
+ // Resize the parent (progressdialog) - this works but resize horizontally too often
+ //parentWidget()->adjustSize();
+
+ QApplication::sendPostedEvents( 0, QEvent::ChildInserted );
+ QApplication::sendPostedEvents( 0, QEvent::LayoutHint );
+ QSize sz = parentWidget()->sizeHint();
+ int currentWidth = parentWidget()->width();
+ // Don't resize to sz.width() every time when it only reduces a little bit
+ if ( currentWidth < sz.width() || currentWidth > sz.width() + 100 )
+ currentWidth = sz.width();
+ parentWidget()->resize( currentWidth, sz.height() );
+}
+
+QSize TransactionItemView::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+QSize TransactionItemView::minimumSizeHint() const
+{
+ int f = 2 * frameWidth();
+ // Make room for a vertical scrollbar in all cases, to avoid a horizontal one
+ int vsbExt = verticalScrollBar()->sizeHint().width();
+ int minw = topLevelWidget()->width() / 3;
+ int maxh = topLevelWidget()->height() / 2;
+ QSize sz( mBigBox->minimumSizeHint() );
+ sz.setWidth( QMAX( sz.width(), minw ) + f + vsbExt );
+ sz.setHeight( QMIN( sz.height(), maxh ) + f );
+ return sz;
+}
+
+
+void TransactionItemView::slotLayoutFirstItem()
+{
+ /*
+ The below relies on some details in Qt's behaviour regarding deleting
+ objects. This slot is called from the destroyed signal of an item just
+ going away. That item is at that point still in the list of chilren, but
+ since the vtable is already gone, it will have type QObject. The first
+ one with both the right name and the right class therefor is what will
+ be the first item very shortly. That's the one we want to remove the
+ hline for.
+ */
+ QObject *o = mBigBox->child( "TransactionItem", "KPIM::TransactionItem" );
+ TransactionItem *ti = dynamic_cast<TransactionItem*>( o );
+ if ( ti ) {
+ ti->hideHLine();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+
+TransactionItem::TransactionItem( QWidget* parent,
+ ProgressItem *item, bool first )
+ : QVBox( parent, "TransactionItem" ), mCancelButton( 0 ), mItem( item )
+
+{
+ setSpacing( 2 );
+ setMargin( 2 );
+ setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+
+ mFrame = new QFrame( this );
+ mFrame->setFrameShape( QFrame::HLine );
+ mFrame->setFrameShadow( QFrame::Raised );
+ mFrame->show();
+ setStretchFactor( mFrame, 3 );
+
+ QHBox *h = new QHBox( this );
+ h->setSpacing( 5 );
+
+ mItemLabel = new QLabel( item->label(), h );
+ // always interpret the label text as RichText, but disable word wrapping
+ mItemLabel->setTextFormat( Qt::RichText );
+ mItemLabel->setAlignment( Qt::AlignAuto | Qt::AlignVCenter | Qt::SingleLine );
+ h->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+
+ mProgress = new QProgressBar( 100, h );
+ mProgress->setProgress( item->progress() );
+
+ if ( item->canBeCanceled() ) {
+ mCancelButton = new QPushButton( SmallIcon( "cancel" ), QString::null, h );
+ QToolTip::add( mCancelButton, i18n("Cancel this operation.") );
+ connect ( mCancelButton, SIGNAL( clicked() ),
+ this, SLOT( slotItemCanceled() ));
+ }
+
+ h = new QHBox( this );
+ h->setSpacing( 5 );
+ h->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+ mSSLLabel = new SSLLabel( h );
+ mSSLLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
+ mItemStatus = new QLabel( item->status(), h );
+ // always interpret the status text as RichText, but disable word wrapping
+ mItemStatus->setTextFormat( Qt::RichText );
+ mItemStatus->setAlignment( Qt::AlignAuto | Qt::AlignVCenter | Qt::SingleLine );
+ // richtext leads to sizeHint acting as if wrapping was enabled though,
+ // so make sure we only ever have the height of one line.
+ mItemStatus->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored ) );
+ mItemStatus->setFixedHeight( mItemLabel->sizeHint().height() );
+ setCrypto( item->usesCrypto() );
+ if( first ) hideHLine();
+}
+
+TransactionItem::~TransactionItem()
+{
+}
+
+void TransactionItem::hideHLine()
+{
+ mFrame->hide();
+}
+
+void TransactionItem::setProgress( int progress )
+{
+ mProgress->setProgress( progress );
+}
+
+void TransactionItem::setLabel( const QString& label )
+{
+ mItemLabel->setText( label );
+}
+
+void TransactionItem::setStatus( const QString& status )
+{
+ mItemStatus->setText( status );
+}
+
+void TransactionItem::setCrypto( bool on )
+{
+ if (on)
+ mSSLLabel->setEncrypted( true );
+ else
+ mSSLLabel->setEncrypted( false );
+
+ mSSLLabel->setState( mSSLLabel->lastState() );
+}
+
+void TransactionItem::slotItemCanceled()
+{
+ if ( mItem )
+ mItem->cancel();
+}
+
+
+void TransactionItem::addSubTransaction( ProgressItem* /*item*/ )
+{
+
+}
+
+
+// ---------------------------------------------------------------------------
+
+ProgressDialog::ProgressDialog( QWidget* alignWidget, QWidget* parent, const char* name )
+ : OverlayWidget( alignWidget, parent, name ), mWasLastShown( false )
+{
+ setFrameStyle( QFrame::Panel | QFrame::Sunken ); // QFrame
+ setSpacing( 0 ); // QHBox
+ setMargin( 1 );
+
+ mScrollView = new TransactionItemView( this, "ProgressScrollView" );
+
+ // No more close button for now, since there is no more autoshow
+ /*
+ QVBox* rightBox = new QVBox( this );
+ QToolButton* pbClose = new QToolButton( rightBox );
+ pbClose->setAutoRaise(true);
+ pbClose->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
+ pbClose->setFixedSize( 16, 16 );
+ pbClose->setIconSet( KGlobal::iconLoader()->loadIconSet( "fileclose", KIcon::Small, 14 ) );
+ QToolTip::add( pbClose, i18n( "Hide detailed progress window" ) );
+ connect(pbClose, SIGNAL(clicked()), this, SLOT(slotClose()));
+ QWidget* spacer = new QWidget( rightBox ); // don't let the close button take up all the height
+ rightBox->setStretchFactor( spacer, 100 );
+ */
+
+ /*
+ * Get the singleton ProgressManager item which will inform us of
+ * appearing and vanishing items.
+ */
+ ProgressManager *pm = ProgressManager::instance();
+ connect ( pm, SIGNAL( progressItemAdded( KPIM::ProgressItem* ) ),
+ this, SLOT( slotTransactionAdded( KPIM::ProgressItem* ) ) );
+ connect ( pm, SIGNAL( progressItemCompleted( KPIM::ProgressItem* ) ),
+ this, SLOT( slotTransactionCompleted( KPIM::ProgressItem* ) ) );
+ connect ( pm, SIGNAL( progressItemProgress( KPIM::ProgressItem*, unsigned int ) ),
+ this, SLOT( slotTransactionProgress( KPIM::ProgressItem*, unsigned int ) ) );
+ connect ( pm, SIGNAL( progressItemStatus( KPIM::ProgressItem*, const QString& ) ),
+ this, SLOT( slotTransactionStatus( KPIM::ProgressItem*, const QString& ) ) );
+ connect ( pm, SIGNAL( progressItemLabel( KPIM::ProgressItem*, const QString& ) ),
+ this, SLOT( slotTransactionLabel( KPIM::ProgressItem*, const QString& ) ) );
+ connect ( pm, SIGNAL( progressItemUsesCrypto(KPIM::ProgressItem*, bool) ),
+ this, SLOT( slotTransactionUsesCrypto( KPIM::ProgressItem*, bool ) ) );
+ connect ( pm, SIGNAL( showProgressDialog() ),
+ this, SLOT( slotShow() ) );
+}
+
+void ProgressDialog::closeEvent( QCloseEvent* e )
+{
+ e->accept();
+ hide();
+}
+
+
+/*
+ * Destructor
+ */
+ProgressDialog::~ProgressDialog()
+{
+ // no need to delete child widgets.
+}
+
+void ProgressDialog::slotTransactionAdded( ProgressItem *item )
+{
+ TransactionItem *parent = 0;
+ if ( item->parent() ) {
+ if ( mTransactionsToListviewItems.contains( item->parent() ) ) {
+ parent = mTransactionsToListviewItems[ item->parent() ];
+ parent->addSubTransaction( item );
+ }
+ } else {
+ const bool first = mTransactionsToListviewItems.empty();
+ TransactionItem *ti = mScrollView->addTransactionItem( item, first );
+ if ( ti )
+ mTransactionsToListviewItems.replace( item, ti );
+ if ( first && mWasLastShown )
+ QTimer::singleShot( 1000, this, SLOT( slotShow() ) );
+
+ }
+}
+
+void ProgressDialog::slotTransactionCompleted( ProgressItem *item )
+{
+ if ( mTransactionsToListviewItems.contains( item ) ) {
+ TransactionItem *ti = mTransactionsToListviewItems[ item ];
+ mTransactionsToListviewItems.remove( item );
+ ti->setItemComplete();
+ QTimer::singleShot( 3000, ti, SLOT( deleteLater() ) );
+ // see the slot for comments as to why that works
+ connect ( ti, SIGNAL( destroyed() ),
+ mScrollView, SLOT( slotLayoutFirstItem() ) );
+ }
+ // This was the last item, hide.
+ if ( mTransactionsToListviewItems.empty() )
+ QTimer::singleShot( 3000, this, SLOT( slotHide() ) );
+}
+
+void ProgressDialog::slotTransactionCanceled( ProgressItem* )
+{
+}
+
+void ProgressDialog::slotTransactionProgress( ProgressItem *item,
+ unsigned int progress )
+{
+ if ( mTransactionsToListviewItems.contains( item ) ) {
+ TransactionItem *ti = mTransactionsToListviewItems[ item ];
+ ti->setProgress( progress );
+ }
+}
+
+void ProgressDialog::slotTransactionStatus( ProgressItem *item,
+ const QString& status )
+{
+ if ( mTransactionsToListviewItems.contains( item ) ) {
+ TransactionItem *ti = mTransactionsToListviewItems[ item ];
+ ti->setStatus( status );
+ }
+}
+
+void ProgressDialog::slotTransactionLabel( ProgressItem *item,
+ const QString& label )
+{
+ if ( mTransactionsToListviewItems.contains( item ) ) {
+ TransactionItem *ti = mTransactionsToListviewItems[ item ];
+ ti->setLabel( label );
+ }
+}
+
+
+void ProgressDialog::slotTransactionUsesCrypto( ProgressItem *item,
+ bool value )
+{
+ if ( mTransactionsToListviewItems.contains( item ) ) {
+ TransactionItem *ti = mTransactionsToListviewItems[ item ];
+ ti->setCrypto( value );
+ }
+}
+
+void ProgressDialog::slotShow()
+{
+ setVisible( true );
+}
+
+void ProgressDialog::slotHide()
+{
+ // check if a new item showed up since we started the timer. If not, hide
+ if ( mTransactionsToListviewItems.isEmpty() ) {
+ setVisible( false );
+ }
+}
+
+void ProgressDialog::slotClose()
+{
+ mWasLastShown = false;
+ setVisible( false );
+}
+
+void ProgressDialog::setVisible( bool b )
+{
+ if ( b )
+ show();
+ else
+ hide();
+ emit visibilityChanged( b );
+}
+
+void ProgressDialog::slotToggleVisibility()
+{
+ /* Since we are only hiding with a timeout, there is a short period of
+ * time where the last item is still visible, but clicking on it in
+ * the statusbarwidget should not display the dialog, because there
+ * are no items to be shown anymore. Guard against that.
+ */
+ mWasLastShown = !isShown();
+ if ( isShown() || !mTransactionsToListviewItems.isEmpty() )
+ setVisible( !isShown() );
+}
+
+}
+
+#include "progressdialog.moc"