libtdepim

progressdialog.cpp
1 /*
2  * progressdialog.cpp
3  *
4  * Copyright (c) 2004 Till Adam <adam@kde.org>,
5  * David Faure <faure@kde.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * In addition, as a special exception, the copyright holders give
21  * permission to link the code of this program with any edition of
22  * the TQt library by Trolltech AS, Norway (or with modified versions
23  * of TQt that use the same license as TQt), and distribute linked
24  * combinations including the two. You must obey the GNU General
25  * Public License in all respects for all of the code used other than
26  * TQt. If you modify this file, you may extend this exception to
27  * your version of the file, but you are not obligated to do so. If
28  * you do not wish to do so, delete this exception statement from
29  * your version.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 #include <tqapplication.h>
37 #include <tqlayout.h>
38 #include <tqprogressbar.h>
39 #include <tqtimer.h>
40 #include <tqheader.h>
41 #include <tqobject.h>
42 #include <tqscrollview.h>
43 #include <tqtoolbutton.h>
44 #include <tqpushbutton.h>
45 #include <tqvbox.h>
46 #include <tqtooltip.h>
47 
48 #include <tdelocale.h>
49 #include <kdialog.h>
50 #include <kstdguiitem.h>
51 #include <kiconloader.h>
52 #include <kdebug.h>
53 
54 #include "progressdialog.h"
55 #include "progressmanager.h"
56 #include "ssllabel.h"
57 #include <tqwhatsthis.h>
58 
59 namespace KPIM {
60 
61 class TransactionItem;
62 
63 TransactionItemView::TransactionItemView( TQWidget * parent,
64  const char * name,
65  WFlags f )
66  : TQScrollView( parent, name, f ) {
67  setFrameStyle( NoFrame );
68  mBigBox = new TQVBox( viewport() );
69  mBigBox->setSpacing( 5 );
70  addChild( mBigBox );
71  setResizePolicy( TQScrollView::AutoOneFit ); // Fit so that the box expands horizontally
72 }
73 
74 TransactionItem* TransactionItemView::addTransactionItem( ProgressItem* item, bool first )
75 {
76  TransactionItem *ti = new TransactionItem( mBigBox, item, first );
77  ti->hide();
78  TQTimer::singleShot( 1000, ti, TQ_SLOT( show() ) );
79  return ti;
80 }
81 
82 void TransactionItemView::resizeContents( int w, int h )
83 {
84  // (handling of TQEvent::LayoutHint in TQScrollView calls this method)
85  //kdDebug(5300) << k_funcinfo << w << "," << h << endl;
86  TQScrollView::resizeContents( w, h );
87  // Tell the layout in the parent (progressdialog) that our size changed
88  updateGeometry();
89  // Resize the parent (progressdialog) - this works but resize horizontally too often
90  //parentWidget()->adjustSize();
91 
92  TQApplication::sendPostedEvents( 0, TQEvent::ChildInserted );
93  TQApplication::sendPostedEvents( 0, TQEvent::LayoutHint );
94  TQSize sz = parentWidget()->sizeHint();
95  int currentWidth = parentWidget()->width();
96  // Don't resize to sz.width() every time when it only reduces a little bit
97  if ( currentWidth < sz.width() || currentWidth > sz.width() + 100 )
98  currentWidth = sz.width();
99  parentWidget()->resize( currentWidth, sz.height() );
100 }
101 
102 TQSize TransactionItemView::sizeHint() const
103 {
104  return minimumSizeHint();
105 }
106 
107 TQSize TransactionItemView::minimumSizeHint() const
108 {
109  int f = 2 * frameWidth();
110  // Make room for a vertical scrollbar in all cases, to avoid a horizontal one
111  int vsbExt = verticalScrollBar()->sizeHint().width();
112  int minw = topLevelWidget()->width() / 3;
113  int maxh = topLevelWidget()->height() / 2;
114  TQSize sz( mBigBox->minimumSizeHint() );
115  sz.setWidth( TQMAX( sz.width(), minw ) + f + vsbExt );
116  sz.setHeight( TQMIN( sz.height(), maxh ) + f );
117  return sz;
118 }
119 
120 
121 void TransactionItemView::slotLayoutFirstItem()
122 {
123  /*
124  The below relies on some details in TQt's behaviour regarding deleting
125  objects. This slot is called from the destroyed signal of an item just
126  going away. That item is at that point still in the list of chilren, but
127  since the vtable is already gone, it will have type TQObject. The first
128  one with both the right name and the right class therefor is what will
129  be the first item very shortly. That's the one we want to remove the
130  hline for.
131  */
132  TQObject *o = mBigBox->child( "TransactionItem", "KPIM::TransactionItem" );
133  TransactionItem *ti = dynamic_cast<TransactionItem*>( o );
134  if ( ti ) {
135  ti->hideHLine();
136  }
137 }
138 
139 
140 // ----------------------------------------------------------------------------
141 
142 TransactionItem::TransactionItem( TQWidget* parent,
143  ProgressItem *item, bool first )
144  : TQVBox( parent, "TransactionItem" ), mCancelButton( 0 ), mItem( item )
145 
146 {
147  setSpacing( 2 );
148  setMargin( 2 );
149  setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
150 
151  mFrame = new TQFrame( this );
152  mFrame->setFrameShape( TQFrame::HLine );
153  mFrame->setFrameShadow( TQFrame::Raised );
154  mFrame->show();
155  setStretchFactor( mFrame, 3 );
156 
157  TQHBox *h = new TQHBox( this );
158  h->setSpacing( 5 );
159 
160  mItemLabel = new TQLabel( item->label(), h );
161  // always interpret the label text as RichText, but disable word wrapping
162  mItemLabel->setTextFormat( TQt::RichText );
163  mItemLabel->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::SingleLine );
164  h->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
165 
166  mProgress = new TQProgressBar( 100, h );
167  mProgress->setProgress( item->progress() );
168 
169  if ( item->canBeCanceled() ) {
170  mCancelButton = new TQPushButton( SmallIcon( "cancel" ), TQString(), h );
171  TQToolTip::add( mCancelButton, i18n("Cancel this operation.") );
172  connect ( mCancelButton, TQ_SIGNAL( clicked() ),
173  this, TQ_SLOT( slotItemCanceled() ));
174  }
175 
176  h = new TQHBox( this );
177  h->setSpacing( 5 );
178  h->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
179  mSSLLabel = new SSLLabel( h );
180  mSSLLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
181  mItemStatus = new TQLabel( item->status(), h );
182  // always interpret the status text as RichText, but disable word wrapping
183  mItemStatus->setTextFormat( TQt::RichText );
184  mItemStatus->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::SingleLine );
185  // richtext leads to sizeHint acting as if wrapping was enabled though,
186  // so make sure we only ever have the height of one line.
187  mItemStatus->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored ) );
188  mItemStatus->setFixedHeight( mItemLabel->sizeHint().height() );
189  setCrypto( item->usesCrypto() );
190  if( first ) hideHLine();
191 }
192 
193 TransactionItem::~TransactionItem()
194 {
195 }
196 
197 void TransactionItem::hideHLine()
198 {
199  mFrame->hide();
200 }
201 
202 void TransactionItem::setProgress( int progress )
203 {
204  mProgress->setProgress( progress );
205 }
206 
207 void TransactionItem::setLabel( const TQString& label )
208 {
209  mItemLabel->setText( label );
210 }
211 
212 void TransactionItem::setStatus( const TQString& status )
213 {
214  mItemStatus->setText( status );
215 }
216 
217 void TransactionItem::setCrypto( bool on )
218 {
219  if (on)
220  mSSLLabel->setEncrypted( true );
221  else
222  mSSLLabel->setEncrypted( false );
223 
224  mSSLLabel->setState( mSSLLabel->lastState() );
225 }
226 
227 void TransactionItem::setTotalSteps( int totalSteps )
228 {
229  mProgress->setTotalSteps( totalSteps );
230 }
231 
232 void TransactionItem::slotItemCanceled()
233 {
234  if ( mItem )
235  mItem->cancel();
236 }
237 
238 
239 void TransactionItem::addSubTransaction( ProgressItem* /*item*/ )
240 {
241 
242 }
243 
244 
245 // ---------------------------------------------------------------------------
246 
247 ProgressDialog::ProgressDialog( TQWidget* alignWidget, TQWidget* parent, const char* name )
248  : OverlayWidget( alignWidget, parent, name ), mWasLastShown( false )
249 {
250  setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); // TQFrame
251  setSpacing( 0 ); // TQHBox
252  setMargin( 1 );
253 
254  mScrollView = new TransactionItemView( this, "ProgressScrollView" );
255 
256  // No more close button for now, since there is no more autoshow
257  /*
258  TQVBox* rightBox = new TQVBox( this );
259  TQToolButton* pbClose = new TQToolButton( rightBox );
260  pbClose->setAutoRaise(true);
261  pbClose->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
262  pbClose->setFixedSize( 16, 16 );
263  pbClose->setIconSet( TDEGlobal::iconLoader()->loadIconSet( "window-close", TDEIcon::Small, 14 ) );
264  TQToolTip::add( pbClose, i18n( "Hide detailed progress window" ) );
265  connect(pbClose, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotClose()));
266  TQWidget* spacer = new TQWidget( rightBox ); // don't let the close button take up all the height
267  rightBox->setStretchFactor( spacer, 100 );
268  */
269 
270  /*
271  * Get the singleton ProgressManager item which will inform us of
272  * appearing and vanishing items.
273  */
274  ProgressManager *pm = ProgressManager::instance();
275  connect ( pm, TQ_SIGNAL( progressItemAdded( KPIM::ProgressItem* ) ),
276  this, TQ_SLOT( slotTransactionAdded( KPIM::ProgressItem* ) ) );
277  connect ( pm, TQ_SIGNAL( progressItemCompleted( KPIM::ProgressItem* ) ),
278  this, TQ_SLOT( slotTransactionCompleted( KPIM::ProgressItem* ) ) );
279  connect ( pm, TQ_SIGNAL( progressItemProgress( KPIM::ProgressItem*, unsigned int ) ),
280  this, TQ_SLOT( slotTransactionProgress( KPIM::ProgressItem*, unsigned int ) ) );
281  connect ( pm, TQ_SIGNAL( progressItemStatus( KPIM::ProgressItem*, const TQString& ) ),
282  this, TQ_SLOT( slotTransactionStatus( KPIM::ProgressItem*, const TQString& ) ) );
283  connect ( pm, TQ_SIGNAL( progressItemLabel( KPIM::ProgressItem*, const TQString& ) ),
284  this, TQ_SLOT( slotTransactionLabel( KPIM::ProgressItem*, const TQString& ) ) );
285  connect ( pm, TQ_SIGNAL( progressItemUsesCrypto(KPIM::ProgressItem*, bool) ),
286  this, TQ_SLOT( slotTransactionUsesCrypto( KPIM::ProgressItem*, bool ) ) );
287  connect ( pm, TQ_SIGNAL( progressItemUsesBusyIndicator(KPIM::ProgressItem*, bool) ),
288  this, TQ_SLOT( slotTransactionUsesBusyIndicator( KPIM::ProgressItem*, bool ) ) );
289  connect ( pm, TQ_SIGNAL( showProgressDialog() ),
290  this, TQ_SLOT( slotShow() ) );
291 }
292 
293 void ProgressDialog::closeEvent( TQCloseEvent* e )
294 {
295  e->accept();
296  hide();
297 }
298 
299 
300 /*
301  * Destructor
302  */
303 ProgressDialog::~ProgressDialog()
304 {
305  // no need to delete child widgets.
306 }
307 
308 void ProgressDialog::slotTransactionAdded( ProgressItem *item )
309 {
310  TransactionItem *parent = 0;
311  if ( item->parent() ) {
312  if ( mTransactionsToListviewItems.contains( item->parent() ) ) {
313  parent = mTransactionsToListviewItems[ item->parent() ];
314  parent->addSubTransaction( item );
315  }
316  } else {
317  const bool first = mTransactionsToListviewItems.empty();
318  TransactionItem *ti = mScrollView->addTransactionItem( item, first );
319  if ( ti )
320  mTransactionsToListviewItems.replace( item, ti );
321  if ( first && mWasLastShown )
322  TQTimer::singleShot( 1000, this, TQ_SLOT( slotShow() ) );
323 
324  }
325 }
326 
327 void ProgressDialog::slotTransactionCompleted( ProgressItem *item )
328 {
329  if ( mTransactionsToListviewItems.contains( item ) ) {
330  TransactionItem *ti = mTransactionsToListviewItems[ item ];
331  mTransactionsToListviewItems.remove( item );
332  ti->setItemComplete();
333  TQTimer::singleShot( 3000, ti, TQ_SLOT( deleteLater() ) );
334  // see the slot for comments as to why that works
335  connect ( ti, TQ_SIGNAL( destroyed() ),
336  mScrollView, TQ_SLOT( slotLayoutFirstItem() ) );
337  }
338  // This was the last item, hide.
339  if ( mTransactionsToListviewItems.empty() )
340  TQTimer::singleShot( 3000, this, TQ_SLOT( slotHide() ) );
341 }
342 
343 void ProgressDialog::slotTransactionCanceled( ProgressItem* )
344 {
345 }
346 
347 void ProgressDialog::slotTransactionProgress( ProgressItem *item,
348  unsigned int progress )
349 {
350  if ( mTransactionsToListviewItems.contains( item ) ) {
351  TransactionItem *ti = mTransactionsToListviewItems[ item ];
352  ti->setProgress( progress );
353  }
354 }
355 
356 void ProgressDialog::slotTransactionStatus( ProgressItem *item,
357  const TQString& status )
358 {
359  if ( mTransactionsToListviewItems.contains( item ) ) {
360  TransactionItem *ti = mTransactionsToListviewItems[ item ];
361  ti->setStatus( status );
362  }
363 }
364 
365 void ProgressDialog::slotTransactionLabel( ProgressItem *item,
366  const TQString& label )
367 {
368  if ( mTransactionsToListviewItems.contains( item ) ) {
369  TransactionItem *ti = mTransactionsToListviewItems[ item ];
370  ti->setLabel( label );
371  }
372 }
373 
374 
375 void ProgressDialog::slotTransactionUsesCrypto( ProgressItem *item,
376  bool value )
377 {
378  if ( mTransactionsToListviewItems.contains( item ) ) {
379  TransactionItem *ti = mTransactionsToListviewItems[ item ];
380  ti->setCrypto( value );
381  }
382 }
383 
384 void ProgressDialog::slotTransactionUsesBusyIndicator( KPIM::ProgressItem *item, bool value )
385 {
386  if ( mTransactionsToListviewItems.contains( item ) ) {
387  TransactionItem *ti = mTransactionsToListviewItems[ item ];
388  if ( value )
389  ti->setTotalSteps( 0 );
390  else
391  ti->setTotalSteps( 100 );
392  }
393 }
394 
395 void ProgressDialog::slotShow()
396 {
397  setVisible( true );
398 }
399 
400 void ProgressDialog::slotHide()
401 {
402  // check if a new item showed up since we started the timer. If not, hide
403  if ( mTransactionsToListviewItems.isEmpty() ) {
404  setVisible( false );
405  }
406 }
407 
408 void ProgressDialog::slotClose()
409 {
410  mWasLastShown = false;
411  setVisible( false );
412 }
413 
414 void ProgressDialog::setVisible( bool b )
415 {
416  if ( b )
417  show();
418  else
419  hide();
420  emit visibilityChanged( b );
421 }
422 
423 void ProgressDialog::slotToggleVisibility()
424 {
425  /* Since we are only hiding with a timeout, there is a short period of
426  * time where the last item is still visible, but clicking on it in
427  * the statusbarwidget should not display the dialog, because there
428  * are no items to be shown anymore. Guard against that.
429  */
430  mWasLastShown = !isShown();
431  if ( isShown() || !mTransactionsToListviewItems.isEmpty() )
432  setVisible( !isShown() );
433 }
434 
435 }
436 
437 #include "progressdialog.moc"
TDEPIM classes for drag and drop of mails.