libtdepim

kfoldertree.cpp
1 #include "kfoldertree.h"
2 #include <tdeversion.h>
3 #include <tdelocale.h>
4 #include <tdeio/global.h>
5 #include <kiconloader.h>
6 #include <kdebug.h>
7 #include <kstringhandler.h>
8 #include <tqpainter.h>
9 #include <tqapplication.h>
10 #include <tqheader.h>
11 #include <tqstyle.h>
12 
13 //-----------------------------------------------------------------------------
14 KFolderTreeItem::KFolderTreeItem( KFolderTree *parent, const TQString & label,
15  Protocol protocol, Type type )
16  : TDEListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
17  mUnread(-1), mTotal(0), mSize(0), mFolderIsCloseToQuota( false )
18 {
19 }
20 
21 //-----------------------------------------------------------------------------
22 KFolderTreeItem::KFolderTreeItem( KFolderTreeItem *parent,
23  const TQString & label, Protocol protocol, Type type,
24  int unread, int total )
25  : TDEListViewItem( parent, label ), mProtocol( protocol ), mType( type ),
26  mUnread( unread ), mTotal( total ), mSize(0), mFolderIsCloseToQuota( false )
27 {
28 }
29 
30 //-----------------------------------------------------------------------------
31 int KFolderTreeItem::protocolSortingKey() const
32 {
33  // protocol dependant sorting order:
34  // local < imap < news < search < other
35  switch ( mProtocol ) {
36  case Local:
37  return 1;
38  case CachedImap:
39  case Imap:
40  return 2;
41  case News:
42  return 3;
43  case Search:
44  return 4;
45  default:
46  return 42;
47  }
48 }
49 
50 //-----------------------------------------------------------------------------
51 int KFolderTreeItem::typeSortingKey() const
52 {
53  // type dependant sorting order:
54  // inbox < outbox < sent-mail < trash < drafts
55  // < calendar < contacts < notes < tasks
56  // < normal folders
57  switch ( mType ) {
58  case Inbox:
59  return 1;
60  case Outbox:
61  return 2;
62  case SentMail:
63  return 3;
64  case Trash:
65  return 4;
66  case Drafts:
67  return 5;
68  case Templates:
69  return 6;
70  case Calendar:
71  return 7;
72  case Contacts:
73  return 8;
74  case Notes:
75  return 9;
76  case Tasks:
77  return 10;
78  default:
79  return 42;
80  }
81 }
82 
83 //-----------------------------------------------------------------------------
84 int KFolderTreeItem::compare( TQListViewItem * i, int col, bool ) const
85 {
86  KFolderTreeItem* other = static_cast<KFolderTreeItem*>( i );
87 
88  if (col == 0)
89  {
90  // sort by folder
91 
92  // local root-folder
93  if ( depth() == 0 && mProtocol == NONE )
94  return -1;
95  if ( other->depth() == 0 && other->protocol() == NONE )
96  return 1;
97 
98  // first compare by protocol
99  int thisKey = protocolSortingKey();
100  int thatKey = other->protocolSortingKey();
101  if ( thisKey < thatKey )
102  return -1;
103  if ( thisKey > thatKey )
104  return 1;
105 
106  // then compare by type
107  thisKey = typeSortingKey();
108  thatKey = other->typeSortingKey();
109  if ( thisKey < thatKey )
110  return -1;
111  if ( thisKey > thatKey )
112  return 1;
113 
114  // and finally compare by name
115  return text( 0 ).localeAwareCompare( other->text( 0 ) );
116  }
117  else
118  {
119  // sort by unread or total-column
120  TQ_INT64 a = 0, b = 0;
121  if (col == static_cast<KFolderTree*>(listView())->unreadIndex())
122  {
123  a = mUnread;
124  b = other->unreadCount();
125  }
126  else if (col == static_cast<KFolderTree*>(listView())->totalIndex())
127  {
128  a = mTotal;
129  b = other->totalCount();
130  }
131  else if (col == static_cast<KFolderTree*>(listView())->sizeIndex())
132  {
133  a = mSize;
134  b = other->folderSize();
135  }
136 
137  if ( a == b )
138  return 0;
139  else
140  return (a < b ? -1 : 1);
141  }
142 }
143 
144 //-----------------------------------------------------------------------------
145 void KFolderTreeItem::setUnreadCount( int aUnread )
146 {
147  if ( aUnread < 0 ) return;
148 
149  mUnread = aUnread;
150 
151  TQString unread = TQString();
152  if (mUnread == 0)
153  unread = "- ";
154  else {
155  unread.setNum(mUnread);
156  unread += " ";
157  }
158 
159  setText( static_cast<KFolderTree*>(listView())->unreadIndex(),
160  unread );
161 }
162 
163 //-----------------------------------------------------------------------------
164 void KFolderTreeItem::setTotalCount( int aTotal )
165 {
166  if ( aTotal < 0 ) return;
167 
168  mTotal = aTotal;
169 
170  TQString total = TQString();
171  if (mTotal == 0)
172  total = "- ";
173  else {
174  total.setNum(mTotal);
175  total += " ";
176  }
177 
178  setText( static_cast<KFolderTree*>(listView())->totalIndex(),
179  total );
180 }
181 
182 //-----------------------------------------------------------------------------
183 void KFolderTreeItem::setFolderSize( TQ_INT64 aSize )
184 {
185  if ( aSize < 0 ) return; // we need to update even if nothing changed, kids ...
186 
187  mSize = aSize;
188 
189  TQString size;
190  if (mType != Root) {
191  if (mSize == 0 && (childCount() == 0 || isOpen() ) )
192  size = "- ";
193  else
194  size = TDEIO::convertSize(mSize);
195  }
196  if ( childCount() > 0 && !isOpen() ) {
197  TQ_INT64 recursiveSize = recursiveFolderSize();
198  if ( recursiveSize != mSize ) {
199  if ( mType != Root )
200  size += TQString::fromLatin1(" + %1").arg( TDEIO::convertSize( recursiveSize - mSize ) );
201  else
202  size = TDEIO::convertSize( recursiveSize );
203  }
204  }
205  size += " ";
206 
207  setText( static_cast<KFolderTree*>(listView())->sizeIndex(), size );
208 }
209 
210 //-----------------------------------------------------------------------------
211 TQ_INT64 KFolderTreeItem::recursiveFolderSize() const
212 {
213  TQ_INT64 size = mSize;
214 
215  for ( TQListViewItem *item = firstChild() ;
216  item ; item = item->nextSibling() )
217  {
218  size += static_cast<KFolderTreeItem*>(item)->recursiveFolderSize();
219  }
220  return size;
221 }
222 
223 
224 
225 //-----------------------------------------------------------------------------
226 int KFolderTreeItem::countUnreadRecursive()
227 {
228  int count = (mUnread > 0) ? mUnread : 0;
229 
230  for ( TQListViewItem *item = firstChild() ;
231  item ; item = item->nextSibling() )
232  {
233  count += static_cast<KFolderTreeItem*>(item)->countUnreadRecursive();
234  }
235 
236  return count;
237 }
238 
239 //-----------------------------------------------------------------------------
240 void KFolderTreeItem::paintCell( TQPainter * p, const TQColorGroup & cg,
241  int column, int width, int align )
242 {
243  KFolderTree *ft = static_cast<KFolderTree*>(listView());
244 
245  const int unreadRecursiveCount = countUnreadRecursive();
246  const int unreadCount = ( mUnread > 0 ) ? mUnread : 0;
247 
248 
249  // use a special color for folders which are close to their quota
250  TQColorGroup mycg = cg;
251  if ( ( column == 0 || column == ft->sizeIndex() ) && folderIsCloseToQuota() )
252  {
253  mycg.setColor( TQColorGroup::Text, ft->paintInfo().colCloseToQuota );
254  }
255 
256  // use a bold-font for the folder- and the unread-columns
257  if ( (column == 0 || column == ft->unreadIndex())
258  && ( unreadCount > 0
259  || ( !isOpen() && unreadRecursiveCount > 0 ) ) )
260  {
261  TQFont f = p->font();
262  f.setWeight(TQFont::Bold);
263  p->setFont(f);
264  }
265 
266 
267  // most cells can be handled by TDEListView::paintCell, we only need to
268  // deal with the folder column if the unread column is not shown
269 
270  /* The below is exceedingly silly, but Ingo insists that the unread
271  * count that is shown in parenthesis after the folder name must
272  * be configurable in color. That means that paintCell needs to do
273  * two painting passes which flickers. Since that flicker is not
274  * needed when there is the unread column, special case that. */
275  if ( ft->isUnreadActive() || column != 0 ) {
276  TDEListViewItem::paintCell( p, mycg, column, width, align );
277  } else {
278  TQListView *lv = listView();
279  TQString oldText = text(column);
280 
281  // set an empty text so that we can have our own implementation (see further down)
282  // but still benefit from TDEListView::paintCell
283  setText( column, "" );
284 
285  TDEListViewItem::paintCell( p, mycg, column, width, align );
286 
287  const TQPixmap *icon = pixmap( column );
288  int marg = lv ? lv->itemMargin() : 1;
289  int r = marg;
290 
291  setText( column, oldText );
292  if ( isSelected() )
293  p->setPen( mycg.highlightedText() );
294  else
295  p->setPen( mycg.color( TQColorGroup::Text ) );
296 
297  if ( icon ) {
298  r += icon->width() + marg;
299  }
300  TQString t = text( column );
301  if (t.isEmpty())
302  return;
303 
304  // draw the unread-count if the unread-column is not active
305  TQString unread;
306 
307  if ( unreadCount > 0 || ( !isOpen() && unreadRecursiveCount > 0 ) ) {
308  if ( isOpen() )
309  unread = " (" + TQString::number( unreadCount ) + ")";
310  else if ( unreadRecursiveCount == unreadCount || mType == Root )
311  unread = " (" + TQString::number( unreadRecursiveCount ) + ")";
312  else
313  unread = " (" + TQString::number( unreadCount ) + " + " +
314  TQString::number( unreadRecursiveCount-unreadCount ) + ")";
315  }
316 
317  // check if the text needs to be squeezed
318  TQFontMetrics fm( p->fontMetrics() );
319  int unreadWidth = fm.width( unread );
320  if ( fm.width( t ) + marg + r + unreadWidth > width )
321  t = squeezeFolderName( t, fm, width - marg - r - unreadWidth );
322 
323  TQRect br;
324  p->drawText( r, 0, width-marg-r, height(),
325  align | AlignVCenter, t, -1, &br );
326 
327  if ( !unread.isEmpty() ) {
328  if (!isSelected())
329  p->setPen( ft->paintInfo().colUnread );
330  p->drawText( br.right(), 0, width-marg-br.right(), height(),
331  align | AlignVCenter, unread );
332  }
333  }
334 }
335 
336 
337 TQString KFolderTreeItem::squeezeFolderName( const TQString &text,
338  const TQFontMetrics &fm,
339  uint width ) const
340 {
341  return KStringHandler::rPixelSqueeze( text, fm, width );
342 }
343 
344 bool KFolderTreeItem::folderIsCloseToQuota() const
345 {
346  return mFolderIsCloseToQuota;
347 }
348 
349 void KFolderTreeItem::setFolderIsCloseToQuota( bool v )
350 {
351  if ( mFolderIsCloseToQuota != v) {
352  mFolderIsCloseToQuota = v;
353  repaint();
354  }
355 }
356 
357 
358 //=============================================================================
359 
360 
361 KFolderTree::KFolderTree( TQWidget *parent, const char* name )
362  : TDEListView( parent, name ), mUnreadIndex(-1), mTotalIndex(-1), mSizeIndex(-1)
363 {
364  // GUI-options
365  setStyleDependantFrameWidth();
366  setAcceptDrops(true);
367  setDropVisualizer(false);
368  setAllColumnsShowFocus(true);
369  setShowSortIndicator(true);
370  setUpdatesEnabled(true);
371  setItemsRenameable(false);
372  setRootIsDecorated(true);
373  setSelectionModeExt(Extended);
374  setAlternateBackground(TQColor());
375 #if KDE_IS_VERSION( 3, 3, 90 )
376  setShadeSortColumn ( false );
377 #endif
378  setFullWidth(true);
379  disableAutoSelection();
380  setColumnWidth( 0, 120 ); //reasonable default size
381 
382  disconnect( header(), TQ_SIGNAL( sizeChange( int, int, int ) ) );
383  connect( header(), TQ_SIGNAL( sizeChange( int, int, int ) ),
384  TQ_SLOT( slotSizeChanged( int, int, int ) ) );
385 }
386 
387 //-----------------------------------------------------------------------------
388 void KFolderTree::setStyleDependantFrameWidth()
389 {
390  // set the width of the frame to a reasonable value for the current GUI style
391  int frameWidth;
392  if( style().isA("KeramikStyle") )
393  frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
394  else
395  frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
396  if ( frameWidth < 0 )
397  frameWidth = 0;
398  if ( frameWidth != lineWidth() )
399  setLineWidth( frameWidth );
400 }
401 
402 //-----------------------------------------------------------------------------
403 void KFolderTree::styleChange( TQStyle& oldStyle )
404 {
405  setStyleDependantFrameWidth();
406  TDEListView::styleChange( oldStyle );
407 }
408 
409 //-----------------------------------------------------------------------------
410 void KFolderTree::drawContentsOffset( TQPainter * p, int ox, int oy,
411  int cx, int cy, int cw, int ch )
412 {
413  bool oldUpdatesEnabled = isUpdatesEnabled();
414  setUpdatesEnabled(false);
415  TDEListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
416  setUpdatesEnabled(oldUpdatesEnabled);
417 }
418 
419 //-----------------------------------------------------------------------------
420 void KFolderTree::contentsMousePressEvent( TQMouseEvent *e )
421 {
422  setSelectionModeExt(Single);
423  TDEListView::contentsMousePressEvent(e);
424 }
425 
426 //-----------------------------------------------------------------------------
427 void KFolderTree::contentsMouseReleaseEvent( TQMouseEvent *e )
428 {
429  TDEListView::contentsMouseReleaseEvent(e);
430  setSelectionModeExt(Extended);
431 }
432 
433 //-----------------------------------------------------------------------------
434 void KFolderTree::addAcceptableDropMimetype( const char *mimeType, bool outsideOk )
435 {
436  int oldSize = mAcceptableDropMimetypes.size();
437  mAcceptableDropMimetypes.resize(oldSize+1);
438  mAcceptOutside.resize(oldSize+1);
439 
440  mAcceptableDropMimetypes.at(oldSize) = mimeType;
441  mAcceptOutside.setBit(oldSize, outsideOk);
442 }
443 
444 //-----------------------------------------------------------------------------
445 bool KFolderTree::acceptDrag( TQDropEvent* event ) const
446 {
447  TQListViewItem* item = itemAt(contentsToViewport(event->pos()));
448 
449  for (uint i = 0; i < mAcceptableDropMimetypes.size(); i++)
450  {
451  if (event->provides(mAcceptableDropMimetypes[i]))
452  {
453  if (item)
454  return (static_cast<KFolderTreeItem*>(item))->acceptDrag(event);
455  else
456  return mAcceptOutside[i];
457  }
458  }
459  return false;
460 }
461 
462 //-----------------------------------------------------------------------------
463 void KFolderTree::addUnreadColumn( const TQString & name, int width )
464 {
465  mUnreadIndex = addColumn( name, width );
466  setColumnAlignment( mUnreadIndex, tqApp->reverseLayout() ? TQt::AlignLeft : TQt::AlignRight );
467  header()->adjustHeaderSize();
468 }
469 
470 //-----------------------------------------------------------------------------
471 void KFolderTree::addTotalColumn( const TQString & name, int width )
472 {
473  mTotalIndex = addColumn( name, width );
474  setColumnAlignment( mTotalIndex, tqApp->reverseLayout() ? TQt::AlignLeft : TQt::AlignRight );
475  header()->adjustHeaderSize();
476 }
477 
478 //-----------------------------------------------------------------------------
479 void KFolderTree::removeUnreadColumn()
480 {
481  if ( !isUnreadActive() ) return;
482  removeColumn( mUnreadIndex );
483  if ( isTotalActive() && mTotalIndex > mUnreadIndex )
484  mTotalIndex--;
485  if ( isSizeActive() && mSizeIndex > mUnreadIndex )
486  mSizeIndex--;
487 
488  mUnreadIndex = -1;
489  header()->adjustHeaderSize();
490 }
491 
492 //-----------------------------------------------------------------------------
493 void KFolderTree::removeTotalColumn()
494 {
495  if ( !isTotalActive() ) return;
496  removeColumn( mTotalIndex );
497  if ( isUnreadActive() && mTotalIndex < mUnreadIndex )
498  mUnreadIndex--;
499  if ( isSizeActive() && mTotalIndex < mSizeIndex )
500  mSizeIndex--;
501  mTotalIndex = -1;
502  header()->adjustHeaderSize();
503 }
504 
505 //-----------------------------------------------------------------------------
506 void KFolderTree::addSizeColumn( const TQString & name, int width )
507 {
508  mSizeIndex = addColumn( name, width );
509  setColumnAlignment( mSizeIndex, tqApp->reverseLayout() ? TQt::AlignLeft : TQt::AlignRight );
510  header()->adjustHeaderSize();
511 }
512 
513 //-----------------------------------------------------------------------------
514 void KFolderTree::removeSizeColumn()
515 {
516  if ( !isSizeActive() ) return;
517  removeColumn( mSizeIndex );
518  if ( isUnreadActive() && mSizeIndex < mUnreadIndex )
519  mUnreadIndex--;
520  if ( isTotalActive() && mSizeIndex < mTotalIndex )
521  mTotalIndex--;
522  mSizeIndex = -1;
523  header()->adjustHeaderSize();
524 }
525 
526 
527 //-----------------------------------------------------------------------------
528 void KFolderTree::setFullWidth( bool fullWidth )
529 {
530  if (fullWidth)
531  header()->setStretchEnabled( true, 0 );
532 }
533 
534 //-----------------------------------------------------------------------------
535 void KFolderTree::slotSizeChanged( int section, int, int newSize )
536 {
537  viewport()->repaint(
538  header()->sectionPos(section), 0, newSize, visibleHeight(), false );
539 }
540 
541 #include "kfoldertree.moc"