KDirStat – a graphical disk usage utility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

418 lines
7.0KB

  1. /*
  2. * File name: kdirtreeiterators.h
  3. * Summary: Support classes for KDirStat - KDirTree iterator classes
  4. * License: LGPL - See file COPYING.LIB for details.
  5. * Author: Stefan Hundhammer <sh@suse.de>
  6. *
  7. * Updated: 2003-01-07
  8. */
  9. #include "kdirtreeiterators.h"
  10. #include "kdirtree.h"
  11. using namespace KDirStat;
  12. KFileInfoIterator::KFileInfoIterator( KFileInfo * parent,
  13. KDotEntryPolicy dotEntryPolicy )
  14. {
  15. init( parent,
  16. dotEntryPolicy,
  17. true ); // callNext
  18. }
  19. KFileInfoIterator::KFileInfoIterator( KFileInfo * parent,
  20. KDotEntryPolicy dotEntryPolicy,
  21. bool callNext )
  22. {
  23. init( parent, dotEntryPolicy, callNext );
  24. }
  25. void
  26. KFileInfoIterator::init( KFileInfo * parent,
  27. KDotEntryPolicy dotEntryPolicy,
  28. bool callNext )
  29. {
  30. _parent = parent;
  31. _policy = dotEntryPolicy;
  32. _current = 0;
  33. _directChildrenProcessed = false;
  34. _dotEntryProcessed = false;
  35. _dotEntryChildrenProcessed = false;
  36. if ( callNext )
  37. next();
  38. }
  39. KFileInfoIterator::~KFileInfoIterator()
  40. {
  41. // NOP
  42. }
  43. void KFileInfoIterator::next()
  44. {
  45. if ( ! _directChildrenProcessed )
  46. {
  47. // Process direct children
  48. _current = _current ? _current->next() : _parent->firstChild();
  49. if ( ! _current )
  50. {
  51. _directChildrenProcessed = true;
  52. next();
  53. }
  54. else
  55. {
  56. // kdDebug() << k_funcinfo << " direct child " << _current << endl;
  57. }
  58. }
  59. else // _directChildrenProcessed
  60. {
  61. if ( ! _dotEntryProcessed )
  62. {
  63. // Process dot entry
  64. _current = _policy == KDotEntryAsSubDir ? _parent->dotEntry() : 0;
  65. _dotEntryProcessed = true;
  66. if ( ! _current )
  67. {
  68. next();
  69. }
  70. else
  71. {
  72. // kdDebug() << k_funcinfo << " dot entry " << _current << endl;
  73. }
  74. }
  75. else // Dot entry already processed or processing it not desired
  76. {
  77. if ( ! _dotEntryChildrenProcessed )
  78. {
  79. if ( _policy == KDotEntryTransparent )
  80. {
  81. // Process dot entry children
  82. _current = _current ?
  83. _current->next() :
  84. ( _parent->dotEntry() ? _parent->dotEntry()->firstChild() : 0 );
  85. if ( ! _current )
  86. {
  87. _dotEntryChildrenProcessed = true;
  88. }
  89. else
  90. {
  91. // kdDebug() << k_funcinfo << " dot entry child " << _current << endl;
  92. }
  93. }
  94. else // _policy != KDotEntryTransparent
  95. {
  96. _current = 0;
  97. _dotEntryChildrenProcessed = true;
  98. }
  99. }
  100. }
  101. }
  102. }
  103. int
  104. KFileInfoIterator::count()
  105. {
  106. int cnt = 0;
  107. // Count direct children
  108. KFileInfo *child = _parent->firstChild();
  109. while ( child )
  110. {
  111. cnt++;
  112. child = child->next();
  113. }
  114. // Handle the dot entry
  115. switch ( _policy )
  116. {
  117. case KDotEntryTransparent: // Count the dot entry's children as well.
  118. if ( _parent->dotEntry() )
  119. {
  120. child = _parent->dotEntry()->firstChild();
  121. while ( child )
  122. {
  123. cnt++;
  124. child = child->next();
  125. }
  126. }
  127. break;
  128. case KDotEntryAsSubDir: // The dot entry counts as one item.
  129. if ( _parent->dotEntry() )
  130. cnt++;
  131. break;
  132. case KDotEntryIgnore: // We're done.
  133. break;
  134. }
  135. return cnt;
  136. }
  137. KFileInfoSortedIterator::KFileInfoSortedIterator( KFileInfo * parent,
  138. KDotEntryPolicy dotEntryPolicy,
  139. KFileInfoSortOrder sortOrder,
  140. bool ascending )
  141. : KFileInfoIterator( parent, dotEntryPolicy, false )
  142. {
  143. _sortOrder = sortOrder;
  144. _ascending = ascending;
  145. _initComplete = false;
  146. _childrenList = 0;
  147. _current = 0;
  148. }
  149. void
  150. KFileInfoSortedIterator::delayedInit()
  151. {
  152. _childrenList = new KFileInfoList( _sortOrder, _ascending );
  153. TQ_CHECK_PTR( _childrenList );
  154. if ( _sortOrder == KSortByName )
  155. {
  156. makeDefaultOrderChildrenList();
  157. }
  158. else
  159. {
  160. makeChildrenList();
  161. }
  162. _current = _childrenList->first();
  163. _initComplete = true;
  164. }
  165. KFileInfoSortedIterator::~KFileInfoSortedIterator()
  166. {
  167. if ( _childrenList )
  168. delete _childrenList;
  169. }
  170. void KFileInfoSortedIterator::makeDefaultOrderChildrenList()
  171. {
  172. // Fill children list with direct children
  173. KFileInfo *child = _parent->firstChild();
  174. while ( child )
  175. {
  176. _childrenList->append( child );
  177. child = child->next();
  178. }
  179. _childrenList->sort();
  180. if ( _policy == KDotEntryAsSubDir && _parent->dotEntry() )
  181. {
  182. // Append dot entry to the children list
  183. _childrenList->append( _parent->dotEntry() );
  184. }
  185. // Append the dot entry's children to the children list
  186. if ( _policy == KDotEntryTransparent && _parent->dotEntry() )
  187. {
  188. // Create a temporary list for the dot entry children
  189. KFileInfoList dotEntryChildrenList( _sortOrder, _ascending );
  190. child = _parent->dotEntry()->firstChild();
  191. while ( child )
  192. {
  193. dotEntryChildrenList.append( child );
  194. child = child->next();
  195. }
  196. dotEntryChildrenList.sort();
  197. // Now append all of this dot entry children list to the children list
  198. child = dotEntryChildrenList.first();
  199. while ( child )
  200. {
  201. _childrenList->append( child );
  202. child = dotEntryChildrenList.next();
  203. }
  204. }
  205. }
  206. void
  207. KFileInfoSortedIterator::makeChildrenList()
  208. {
  209. KFileInfoIterator it( _parent, _policy );
  210. while ( *it )
  211. {
  212. _childrenList->append( *it );
  213. ++it;
  214. }
  215. _childrenList->sort();
  216. }
  217. KFileInfo *
  218. KFileInfoSortedIterator::current()
  219. {
  220. if ( ! _initComplete )
  221. delayedInit();
  222. return _current;
  223. }
  224. void KFileInfoSortedIterator::next()
  225. {
  226. if ( ! _initComplete )
  227. delayedInit();
  228. _current = _childrenList->next();
  229. }
  230. bool
  231. KFileInfoSortedIterator::finished()
  232. {
  233. if ( ! _initComplete )
  234. delayedInit();
  235. return _current == 0;
  236. }
  237. KFileInfoSortedBySizeIterator::KFileInfoSortedBySizeIterator( KFileInfo * parent,
  238. KFileSize minSize,
  239. KDotEntryPolicy dotEntryPolicy,
  240. bool ascending )
  241. : KFileInfoSortedIterator( parent, dotEntryPolicy, KSortByTotalSize, ascending )
  242. , _minSize( minSize )
  243. {
  244. }
  245. void
  246. KFileInfoSortedBySizeIterator::makeChildrenList()
  247. {
  248. KFileInfoIterator it( _parent, _policy );
  249. while ( *it )
  250. {
  251. if ( (*it)->totalSize() >= _minSize )
  252. _childrenList->append( *it );
  253. ++it;
  254. }
  255. _childrenList->sort();
  256. }
  257. KFileInfoList::KFileInfoList( KFileInfoSortOrder sortOrder, bool ascending )
  258. : TQPtrList<KFileInfo>()
  259. {
  260. _sortOrder = sortOrder;
  261. _ascending = ascending;
  262. }
  263. KFileInfoList::~KFileInfoList()
  264. {
  265. // NOP
  266. }
  267. KFileSize
  268. KFileInfoList::sumTotalSizes()
  269. {
  270. KFileSize sum = 0;
  271. KFileInfoListIterator it( *this );
  272. while ( *it )
  273. {
  274. sum += (*it)->totalSize();
  275. ++it;
  276. }
  277. return sum;
  278. }
  279. int
  280. KFileInfoList::compareItems( TQPtrCollection::Item it1, TQPtrCollection::Item it2 )
  281. {
  282. if ( it1 == it2 )
  283. return 0;
  284. KFileInfo *file1 = (KFileInfo *) it1;
  285. KFileInfo *file2 = (KFileInfo *) it2;
  286. int result = 0;
  287. switch ( _sortOrder )
  288. {
  289. case KUnsorted:
  290. return 1;
  291. case KSortByName:
  292. result = TQString::compare( file1->name(), file2->name() );
  293. break;
  294. case KSortByTotalSize:
  295. result = compare<KFileSize>( file1->totalSize(), file2->totalSize() );
  296. break;
  297. case KSortByLatestMtime:
  298. result = compare<time_t>( file1->latestMtime(), file2->latestMtime() );
  299. break;
  300. }
  301. return _ascending ? result : -result;
  302. }
  303. // EOF