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.

1440 lines
41KB

  1. /*
  2. * File name: kdirtree.h
  3. * Summary: Support classes for KDirStat
  4. * License: LGPL - See file COPYING.LIB for details.
  5. * Author: Stefan Hundhammer <sh@suse.de>
  6. *
  7. * Updated: 2005-01-07
  8. */
  9. #ifndef KDirTree_h
  10. #define KDirTree_h
  11. #ifdef HAVE_CONFIG_H
  12. # include <config.h>
  13. #endif
  14. #include <sys/types.h>
  15. #include <limits.h>
  16. #include <dirent.h>
  17. #include <tqptrqueue.h>
  18. #include <kdebug.h>
  19. #include <tdefileitem.h>
  20. #include <tdeio/jobclasses.h>
  21. #ifndef NOT_USED
  22. # define NOT_USED(PARAM) ( (void) (PARAM) )
  23. #endif
  24. // Open a new name space since KDE's name space is pretty much cluttered
  25. // already - all names that would even remotely match are already used up,
  26. // yet the resprective classes don't quite fit the purposes required here.
  27. namespace KDirStat
  28. {
  29. // With today's hard disks, the 2 GB we could sum up with 'long' (or 4 GB
  30. // with 'unsigned long') are definitely not enough. So we have to go for
  31. // something larger:
  32. typedef long long KFileSize;
  33. // Taken from Linux <limits.h> (the Alpha definition - 64 Bit long!).
  34. // This is how much bytes this program can handle.
  35. #define KFileSizeMax 9223372036854775807LL
  36. // Forward declarations
  37. class KDirInfo;
  38. class KDirTree;
  39. class KDirReadJob;
  40. class KDirTreeView;
  41. /**
  42. * Status of a directory read job.
  43. **/
  44. typedef enum
  45. {
  46. KDirQueued, // Waiting in the directory read queue
  47. KDirReading, // Reading in progress
  48. KDirFinished, // Reading finished and OK
  49. KDirOnRequestOnly, // Will be read upon explicit request only (mount points)
  50. KDirAborted, // Reading aborted upon user request
  51. KDirError // Error while reading
  52. } KDirReadState;
  53. /**
  54. * Directory read methods.
  55. **/
  56. typedef enum
  57. {
  58. KDirReadUnknown, // Unknown (yet)
  59. KDirReadLocal, // Use opendir() and lstat()
  60. KDirReadKIO // Use KDE 2.x's TDEIO network transparent methods
  61. } KDirReadMethod;
  62. /**
  63. * The most basic building block of a @ref KDirTree:
  64. *
  65. * Information about one single directory entry. This is the type of info
  66. * typically obtained by stat() / lstat() or similar calls. Most of this
  67. * can also be obtained by @ref TDEIO::KDirListJob, but not all: The device
  68. * this file resides on is something none of TDEIO's many classes will tell
  69. * (since of course this only makes sense for local files) - yet this had
  70. * been _the_ single most requested feature of KDirStat <1.0: Stay on one
  71. * filesystem. To facilitate this, information about the device is
  72. * required, thus we'll do lstat() sys calls ourselves for local
  73. * files. This is what the classes in this file are all about.
  74. *
  75. * This class is tuned for size rather than speed: A typical Linux system
  76. * easily has 150,000+ file system objects, and at least one entry of this
  77. * sort is required for each of them.
  78. *
  79. * This class provides stubs for children management, yet those stubs all
  80. * are default implementations that don't really deal with children.
  81. * Derived classes need to take care of that.
  82. *
  83. * @short Basic file information (like obtained by the lstat() sys call)
  84. **/
  85. class KFileInfo
  86. {
  87. public:
  88. /**
  89. * Default constructor.
  90. **/
  91. KFileInfo( KDirTree * tree,
  92. KDirInfo * parent = 0,
  93. const char * name = 0 );
  94. /**
  95. * Constructor from a stat buffer (i.e. based on an lstat() call).
  96. **/
  97. KFileInfo( const TQString & filenameWithoutPath,
  98. struct stat * statInfo,
  99. KDirTree * tree,
  100. KDirInfo * parent = 0 );
  101. /**
  102. * Constructor from a KFileItem, i.e. from a @ref TDEIO::StatJob
  103. **/
  104. KFileInfo( const KFileItem * fileItem,
  105. KDirTree * tree,
  106. KDirInfo * parent = 0 );
  107. /**
  108. * Destructor.
  109. *
  110. * Don't forget to call @ref KFileInfo::unlinkChild() when deleting
  111. * objects of this class!
  112. **/
  113. virtual ~KFileInfo();
  114. /**
  115. * Returns whether or not this is a local file (protocol "file:").
  116. * It might as well be a remote file ("ftp:", "smb:" etc.).
  117. **/
  118. bool isLocalFile() const { return _isLocalFile; }
  119. /**
  120. * Returns the file or directory name without path, i.e. only the last
  121. * path name component (i.e. "printcap" rather than "/etc/printcap").
  122. *
  123. * If a directory scan doesn't begin at the root directory and this is
  124. * the top entry of this directory scan it will also contain the base
  125. * path and maybe the protocol (for remote files),
  126. * i.e. "/usr/share/man" rather than just "man" if a scan was requested
  127. * for "/usr/share/man". Notice, however, that the entry for
  128. * "/usr/share/man/man1" will only return "man1" in this example.
  129. **/
  130. TQString name() const { return _name; }
  131. /**
  132. * Returns the full URL of this object with full path and protocol
  133. * (unless the protocol is "file:").
  134. *
  135. * This is a (somewhat) expensive operation since it will recurse up
  136. * to the top of the tree.
  137. **/
  138. TQString url() const;
  139. /**
  140. * Very much like @ref KFileInfo::url(), but with "/<Files>" appended
  141. * if this is a dot entry. Useful for debugging.
  142. * Notice: You can simply use the @ref kdbgstream operator<< to
  143. * output exactly this:
  144. *
  145. * kdDebug() << "Found fileInfo " << info << endl;
  146. **/
  147. TQString debugUrl() const;
  148. /**
  149. * Returns part no. "level" of this object's URL, i.e. traverses up the
  150. * tree until this tree level is reached and returns this predecessor's
  151. * @ref name() . This is useful for tree searches in symmetrical trees
  152. * to find an item's counterpart in the other tree.
  153. **/
  154. TQString urlPart( int level ) const;
  155. /**
  156. * Returns the major and minor device numbers of the device this file
  157. * resides on or 0 if this is a remote file.
  158. **/
  159. dev_t device() const { return _device; }
  160. /**
  161. * The file permissions and object type as returned by lstat().
  162. * You might want to use the repective convenience methods instead:
  163. * @ref isDir(), @ref isFile(), ...
  164. **/
  165. mode_t mode() const { return _mode; }
  166. /**
  167. * The number of hard links to this file. Relevant for size summaries
  168. * to avoid counting one file several times.
  169. **/
  170. nlink_t links() const { return _links; }
  171. /**
  172. * The file size in bytes. This does not take unused space in the last
  173. * disk block (cluster) into account, yet it is the only size all kinds
  174. * of info functions can obtain. This is also what most file system
  175. * utilities (like "ls -l") display.
  176. **/
  177. KFileSize byteSize() const { return _size; }
  178. /**
  179. * The number of bytes actually allocated on the file system. Usually
  180. * this will be more than @ref byteSize() since the last few bytes of a
  181. * file usually consume an additional cluster on the file system.
  182. *
  183. * In the case of sparse files, however, this might as well be
  184. * considerably less than @ref byteSize() - this means that this file
  185. * has "holes", i.e. large portions filled with zeros. This is typical
  186. * for large core dumps for example. The only way to create such a file
  187. * is to lseek() far ahead of the previous file size and then writing
  188. * data. Most file system utilities will however disregard the fact
  189. * that files are sparse files and simply allocate the holes as well,
  190. * thus greatly increasing the disk space consumption of such a
  191. * file. Only some few file system utilities like "cp", "rsync", "tar"
  192. * have options to handle this more graciously - but usually only when
  193. * specifically requested. See the respective man pages.
  194. **/
  195. KFileSize allocatedSize() const;
  196. /**
  197. * The file size, taking into account multiple links for plain files or
  198. * the true allocated size for sparse files. For plain files with
  199. * multiple links this will be size/no_links, for sparse files it is
  200. * the number of bytes actually allocated.
  201. **/
  202. KFileSize size() const;
  203. /**
  204. * The file size in 512 byte blocks.
  205. **/
  206. KFileSize blocks() const { return _blocks; }
  207. /**
  208. * The size of one single block that @ref blocks() returns.
  209. * Notice: This is _not_ the blocksize that lstat() returns!
  210. **/
  211. KFileSize blockSize() const { return 512L; }
  212. /**
  213. * The modification time of the file (not the inode).
  214. **/
  215. time_t mtime() const { return _mtime; }
  216. /**
  217. * Returns the total size in bytes of this subtree.
  218. * Derived classes that have children should overwrite this.
  219. **/
  220. virtual KFileSize totalSize() { return size(); }
  221. /**
  222. * Returns the total size in blocks of this subtree.
  223. * Derived classes that have children should overwrite this.
  224. **/
  225. virtual KFileSize totalBlocks() { return _blocks; }
  226. /**
  227. * Returns the total number of children in this subtree, excluding this item.
  228. * Derived classes that have children should overwrite this.
  229. **/
  230. virtual int totalItems() { return 0; }
  231. /**
  232. * Returns the total number of subdirectories in this subtree,
  233. * excluding this item. Dot entries and "." or ".." are not counted.
  234. * Derived classes that have children should overwrite this.
  235. **/
  236. virtual int totalSubDirs() { return 0; }
  237. /**
  238. * Returns the total number of plain file children in this subtree,
  239. * excluding this item.
  240. * Derived classes that have children should overwrite this.
  241. **/
  242. virtual int totalFiles() { return 0; }
  243. /**
  244. * Returns the latest modification time of this subtree.
  245. * Derived classes that have children should overwrite this.
  246. **/
  247. virtual time_t latestMtime() { return _mtime; }
  248. /**
  249. * Returns whether or not this is a mount point.
  250. * Derived classes may want to overwrite this.
  251. **/
  252. virtual bool isMountPoint() { return false; }
  253. /**
  254. * Sets the mount point state, i.e. whether or not this is a mount
  255. * point.
  256. *
  257. * This default implementation silently ignores the value passed and
  258. * does nothing. Derived classes may want to overwrite this.
  259. **/
  260. virtual void setMountPoint( bool isMountPoint = true )
  261. { ((void) isMountPoint); return; }
  262. /**
  263. * Returns true if this subtree is finished reading.
  264. *
  265. * This default implementation always returns 'true';
  266. * derived classes should overwrite this.
  267. **/
  268. virtual bool isFinished() { return true; }
  269. /**
  270. * Returns true if this subtree is busy, i.e. it is not finished
  271. * reading yet.
  272. *
  273. * This default implementation always returns 'false';
  274. * derived classes should overwrite this.
  275. **/
  276. virtual bool isBusy() { return false; }
  277. /**
  278. * Returns the number of pending read jobs in this subtree. When this
  279. * number reaches zero, the entire subtree is done.
  280. * Derived classes that have children should overwrite this.
  281. **/
  282. virtual int pendingReadJobs() { return 0; }
  283. //
  284. // Tree management
  285. //
  286. /**
  287. * Returns a pointer to the @ref KDirTree this entry belongs to.
  288. **/
  289. KDirTree * tree() const { return _tree; }
  290. /**
  291. * Returns a pointer to this entry's parent entry or 0 if there is
  292. * none.
  293. **/
  294. KDirInfo * parent() const { return _parent; }
  295. /**
  296. * Set the "parent" pointer.
  297. **/
  298. void setParent( KDirInfo *newParent ) { _parent = newParent; }
  299. /**
  300. * Returns a pointer to the next entry on the same level
  301. * or 0 if there is none.
  302. **/
  303. KFileInfo * next() const { return _next; }
  304. /**
  305. * Set the "next" pointer.
  306. **/
  307. void setNext( KFileInfo *newNext ) { _next = newNext; }
  308. /**
  309. * Returns the first child of this item or 0 if there is none.
  310. * Use the child's next() method to get the next child.
  311. *
  312. * This default implementation always returns 0.
  313. **/
  314. virtual KFileInfo * firstChild() const { return 0; }
  315. /**
  316. * Set this entry's first child.
  317. * Use this method only if you know exactly what you are doing.
  318. *
  319. * This default implementation does nothing.
  320. * Derived classes might want to overwrite this.
  321. **/
  322. virtual void setFirstChild( KFileInfo *newFirstChild )
  323. { NOT_USED( newFirstChild ); }
  324. /**
  325. * Returns true if this entry has any children.
  326. **/
  327. virtual bool hasChildren() const;
  328. /**
  329. * Returns true if this entry is in subtree 'subtree', i.e. if this is
  330. * a child or grandchild etc. of 'subtree'.
  331. **/
  332. bool isInSubtree( const KFileInfo *subtree ) const;
  333. /**
  334. * Locate a child somewhere in this subtree whose URL (i.e. complete
  335. * path) matches the URL passed. Returns 0 if there is no such child.
  336. *
  337. * Notice: This is a very expensive operation since the entire subtree
  338. * is searched recursively.
  339. *
  340. * Derived classes might or might not wish to overwrite this method;
  341. * it's only advisable to do so if a derived class comes up with a
  342. * different method than brute-force search all children.
  343. *
  344. * 'findDotEntries' specifies if locating "dot entries" (".../<Files>")
  345. * is desired.
  346. **/
  347. virtual KFileInfo * locate( TQString url, bool findDotEntries = false );
  348. /**
  349. * Insert a child into the children list.
  350. *
  351. * The order of children in this list is absolutely undefined;
  352. * don't rely on any implementation-specific order.
  353. *
  354. * This default implementation does nothing.
  355. **/
  356. virtual void insertChild( KFileInfo *newChild ) { NOT_USED( newChild ); }
  357. /**
  358. * Return the "Dot Entry" for this node if there is one (or 0
  359. * otherwise): This is a pseudo entry that directory nodes use to store
  360. * non-directory children separately from directories. This way the end
  361. * user can easily tell which summary fields belong to the directory
  362. * itself and which are the accumulated values of the entire subtree.
  363. *
  364. * This default implementation always returns 0.
  365. **/
  366. virtual KFileInfo *dotEntry() const { return 0; }
  367. /**
  368. * Set a "Dot Entry". This makes sense for directories only.
  369. *
  370. * This default implementation does nothing.
  371. **/
  372. virtual void setDotEntry( KFileInfo *newDotEntry ) { NOT_USED( newDotEntry ); }
  373. /**
  374. * Returns true if this is a "Dot Entry".
  375. * See @ref dotEntry() for details.
  376. *
  377. * This default implementation always returns false.
  378. **/
  379. virtual bool isDotEntry() const { return false; }
  380. /**
  381. * Returns the tree level (depth) of this item.
  382. * The topmost level is 0.
  383. *
  384. * This is a (somewhat) expensive operation since it will recurse up
  385. * to the top of the tree.
  386. **/
  387. int treeLevel() const;
  388. /**
  389. * Notification that a child has been added somewhere in the subtree.
  390. *
  391. * This default implementation does nothing.
  392. **/
  393. virtual void childAdded( KFileInfo *newChild ) { NOT_USED( newChild ); }
  394. /**
  395. * Remove a child from the children list.
  396. *
  397. * IMPORTANT: This MUST be called just prior to deleting an object of
  398. * this class. Regrettably, this cannot simply be moved to the
  399. * destructor: Important parts of the object might already be destroyed
  400. * (e.g., the virtual table - no more virtual methods).
  401. *
  402. * This default implementation does nothing.
  403. * Derived classes that can handle children should overwrite this.
  404. **/
  405. virtual void unlinkChild( KFileInfo *deletedChild ) { NOT_USED( deletedChild ); }
  406. /**
  407. * Notification that a child is about to be deleted somewhere in the
  408. * subtree.
  409. **/
  410. virtual void deletingChild( KFileInfo *deletedChild ) { NOT_USED( deletedChild ); }
  411. /**
  412. * Get the current state of the directory reading process:
  413. *
  414. * This default implementation always returns KDirFinished.
  415. * Derived classes should overwrite this.
  416. **/
  417. virtual KDirReadState readState() const { return KDirFinished; }
  418. /**
  419. * Returns true if this is a @ref KDirInfo object.
  420. *
  421. * Don't confuse this with @ref isDir() which tells whether or not this
  422. * is a disk directory! Both should return the same, but you'll never
  423. * know - better be safe than sorry!
  424. *
  425. * This default implementation always returns 'false'. Derived classes
  426. * (in particular, those derived from @ref KDirInfo) should overwrite this.
  427. **/
  428. virtual bool isDirInfo() const { return false; }
  429. /**
  430. * Returns true if this is a sparse file, i.e. if this file has
  431. * actually fewer disk blocks allocated than its byte size would call
  432. * for.
  433. *
  434. * This is a cheap operation since it relies on a cached flag that is
  435. * calculated in the constructor rather than doing repeated
  436. * calculations and comparisons.
  437. *
  438. * Please not that @ref size() already takes this into account.
  439. **/
  440. bool isSparseFile() const { return _isSparseFile; }
  441. //
  442. // File type / mode convenience methods.
  443. // These are simply shortcuts to the respective macros from
  444. // <sys/stat.h>.
  445. //
  446. /**
  447. * Returns true if this is a directory.
  448. **/
  449. bool isDir() const { return S_ISDIR( _mode ) ? true : false; }
  450. /**
  451. * Returns true if this is a regular file.
  452. **/
  453. bool isFile() const { return S_ISREG( _mode ) ? true : false; }
  454. /**
  455. * Returns true if this is a symbolic link.
  456. **/
  457. bool isSymLink() const { return S_ISLNK( _mode ) ? true : false; }
  458. /**
  459. * Returns true if this is a (block or character) device.
  460. **/
  461. bool isDevice() const { return ( S_ISBLK ( _mode ) ||
  462. S_ISCHR ( _mode ) ) ? true : false; }
  463. /**
  464. * Returns true if this is a block device.
  465. **/
  466. bool isBlockDevice() const { return S_ISBLK ( _mode ) ? true : false; }
  467. /**
  468. * Returns true if this is a block device.
  469. **/
  470. bool isCharDevice() const { return S_ISCHR ( _mode ) ? true : false; }
  471. /**
  472. * Returns true if this is a "special" file, i.e. a (block or character)
  473. * device, a FIFO (named pipe) or a socket.
  474. **/
  475. bool isSpecial() const { return ( S_ISBLK ( _mode ) ||
  476. S_ISCHR ( _mode ) ||
  477. S_ISFIFO( _mode ) ||
  478. S_ISSOCK( _mode ) ) ? true : false; }
  479. protected:
  480. // Data members.
  481. //
  482. // Keep this short in order to use as little memory as possible -
  483. // there will be a _lot_ of entries of this kind!
  484. TQString _name; // the file name (without path!)
  485. bool _isLocalFile :1; // flag: local or remote file?
  486. bool _isSparseFile :1; // (cache) flag: sparse file (file with "holes")?
  487. dev_t _device; // device this object resides on
  488. mode_t _mode; // file permissions + object type
  489. nlink_t _links; // number of links
  490. KFileSize _size; // size in bytes
  491. KFileSize _blocks; // 512 bytes blocks
  492. time_t _mtime; // modification time
  493. KDirInfo * _parent; // pointer to the parent entry
  494. KFileInfo * _next; // pointer to the next entry
  495. KDirTree * _tree; // pointer to the parent tree
  496. }; // class KFileInfo
  497. /**
  498. * A more specialized version of @ref KFileInfo: This class can actually
  499. * manage children. The base class (@ref KFileInfo) has only stubs for the
  500. * respective methods to integrate seamlessly with the abstraction of a
  501. * file / directory tree; this class fills those stubs with life.
  502. *
  503. * @short directory item within a @ref KDirTree.
  504. **/
  505. class KDirInfo: public KFileInfo
  506. {
  507. public:
  508. /**
  509. * Default constructor.
  510. *
  511. * If "asDotEntry" is set, this will be used as the parent's
  512. * "dot entry", i.e. the pseudo directory that holds all the parent's
  513. * non-directory children. This is the only way to create a "dot
  514. * entry"!
  515. **/
  516. KDirInfo( KDirTree * tree,
  517. KDirInfo * parent = 0,
  518. bool asDotEntry = false );
  519. /**
  520. * Constructor from a stat buffer (i.e. based on an lstat() call).
  521. **/
  522. KDirInfo( const TQString & filenameWithoutPath,
  523. struct stat * statInfo,
  524. KDirTree * tree,
  525. KDirInfo * parent = 0 );
  526. /**
  527. * Constructor from a KFileItem, i.e. from a @ref TDEIO::StatJob
  528. **/
  529. KDirInfo( const KFileItem * fileItem,
  530. KDirTree * tree,
  531. KDirInfo * parent = 0 );
  532. /**
  533. * Destructor.
  534. **/
  535. virtual ~KDirInfo();
  536. /**
  537. * Returns the total size in bytes of this subtree.
  538. *
  539. * Reimplemented - inherited from @ref KFileInfo.
  540. **/
  541. virtual KFileSize totalSize();
  542. /**
  543. * Returns the total size in blocks of this subtree.
  544. *
  545. * Reimplemented - inherited from @ref KFileInfo.
  546. **/
  547. virtual KFileSize totalBlocks();
  548. /**
  549. * Returns the total number of children in this subtree, excluding this item.
  550. *
  551. * Reimplemented - inherited from @ref KFileInfo.
  552. **/
  553. virtual int totalItems();
  554. /**
  555. * Returns the total number of subdirectories in this subtree,
  556. * excluding this item. Dot entries and "." or ".." are not counted.
  557. *
  558. * Reimplemented - inherited from @ref KFileInfo.
  559. **/
  560. virtual int totalSubDirs();
  561. /**
  562. * Returns the total number of plain file children in this subtree,
  563. * excluding this item.
  564. *
  565. * Reimplemented - inherited from @ref KFileInfo.
  566. **/
  567. virtual int totalFiles();
  568. /**
  569. * Returns the latest modification time of this subtree.
  570. *
  571. * Reimplemented - inherited from @ref KFileInfo.
  572. **/
  573. virtual time_t latestMtime();
  574. /**
  575. * Returns whether or not this is a mount point.
  576. *
  577. * This will return 'false' only if this information can be obtained at
  578. * all, i.e. if local directory reading methods are used.
  579. *
  580. * Reimplemented - inherited from @ref KFileInfo.
  581. **/
  582. virtual bool isMountPoint() { return _isMountPoint; }
  583. /**
  584. * Sets the mount point state, i.e. whether or not this is a mount
  585. * point.
  586. *
  587. * Reimplemented - inherited from @ref KFileInfo.
  588. **/
  589. virtual void setMountPoint( bool isMountPoint = true );
  590. /**
  591. * Returns true if this subtree is finished reading.
  592. *
  593. * Reimplemented - inherited from @ref KFileInfo.
  594. **/
  595. virtual bool isFinished();
  596. /**
  597. * Returns true if this subtree is busy, i.e. it is not finished
  598. * reading yet.
  599. *
  600. * Reimplemented - inherited from @ref KFileInfo.
  601. **/
  602. virtual bool isBusy();
  603. /**
  604. * Returns the number of pending read jobs in this subtree. When this
  605. * number reaches zero, the entire subtree is done.
  606. *
  607. * Reimplemented - inherited from @ref KFileInfo.
  608. **/
  609. virtual int pendingReadJobs() { return _pendingReadJobs; }
  610. /**
  611. * Returns the first child of this item or 0 if there is none.
  612. * Use the child's next() method to get the next child.
  613. **/
  614. virtual KFileInfo * firstChild() const { return _firstChild; }
  615. /**
  616. * Set this entry's first child.
  617. * Use this method only if you know exactly what you are doing.
  618. *
  619. * Reimplemented - inherited from @ref KFileInfo.
  620. **/
  621. virtual void setFirstChild( KFileInfo *newfirstChild )
  622. { _firstChild = newfirstChild; }
  623. /**
  624. * Insert a child into the children list.
  625. *
  626. * The order of children in this list is absolutely undefined;
  627. * don't rely on any implementation-specific order.
  628. **/
  629. virtual void insertChild( KFileInfo *newChild );
  630. /**
  631. * Get the "Dot Entry" for this node if there is one (or 0 otherwise):
  632. * This is a pseudo entry that directory nodes use to store
  633. * non-directory children separately from directories. This way the end
  634. * user can easily tell which summary fields belong to the directory
  635. * itself and which are the accumulated values of the entire subtree.
  636. **/
  637. virtual KFileInfo * dotEntry() const { return _dotEntry; }
  638. /**
  639. * Set a "Dot Entry". This makes sense for directories only.
  640. **/
  641. virtual void setDotEntry( KFileInfo *newDotEntry ) { _dotEntry = newDotEntry; }
  642. /**
  643. * Returns true if this is a "Dot Entry". See @ref dotEntry() for
  644. * details.
  645. *
  646. * Reimplemented - inherited from @ref KFileInfo.
  647. **/
  648. virtual bool isDotEntry() const { return _isDotEntry; }
  649. /**
  650. * Notification that a child has been added somewhere in the subtree.
  651. *
  652. * Reimplemented - inherited from @ref KFileInfo.
  653. **/
  654. virtual void childAdded( KFileInfo *newChild );
  655. /**
  656. * Remove a child from the children list.
  657. *
  658. * IMPORTANT: This MUST be called just prior to deleting an object of
  659. * this class. Regrettably, this cannot simply be moved to the
  660. * destructor: Important parts of the object might already be destroyed
  661. * (e.g., the virtual table - no more virtual methods).
  662. *
  663. * Reimplemented - inherited from @ref KFileInfo.
  664. **/
  665. virtual void unlinkChild( KFileInfo *deletedChild );
  666. /**
  667. * Notification that a child is about to be deleted somewhere in the
  668. * subtree.
  669. *
  670. * Reimplemented - inherited from @ref KFileInfo.
  671. **/
  672. virtual void deletingChild( KFileInfo *deletedChild );
  673. /**
  674. * Notification of a new directory read job somewhere in the subtree.
  675. **/
  676. void readJobAdded();
  677. /**
  678. * Notification of a finished directory read job somewhere in the
  679. * subtree.
  680. **/
  681. void readJobFinished();
  682. /**
  683. * Notification of an aborted directory read job somewhere in the
  684. * subtree.
  685. **/
  686. void readJobAborted();
  687. /**
  688. * Finalize this directory level after reading it is completed.
  689. * This does _not_ mean reading reading all subdirectories is completed
  690. * as well!
  691. *
  692. * Clean up unneeded dot entries.
  693. **/
  694. virtual void finalizeLocal();
  695. /**
  696. * Get the current state of the directory reading process:
  697. *
  698. * KDirQueued waiting in the directory read queue
  699. * KDirReading reading in progress
  700. * KDirFinished reading finished and OK
  701. * KDirAborted reading aborted upon user request
  702. * KDirError error while reading
  703. *
  704. * Reimplemented - inherited from @ref KFileInfo.
  705. **/
  706. virtual KDirReadState readState() const;
  707. /**
  708. * Set the state of the directory reading process.
  709. * See @ref readState() for details.
  710. **/
  711. void setReadState( KDirReadState newReadState );
  712. /**
  713. * Returns true if this is a @ref KDirInfo object.
  714. *
  715. * Don't confuse this with @ref isDir() which tells whether or not this
  716. * is a disk directory! Both should return the same, but you'll never
  717. * know - better be safe than sorry!
  718. *
  719. * Reimplemented - inherited from @ref KFileInfo.
  720. **/
  721. virtual bool isDirInfo() const { return true; }
  722. protected:
  723. /**
  724. * Recursively recalculate the summary fields when they are dirty.
  725. *
  726. * This is a _very_ expensive operation since the entire subtree may
  727. * recursively be traversed.
  728. **/
  729. void recalc();
  730. /**
  731. * Clean up unneeded / undesired dot entries:
  732. * Delete dot entries that don't have any children,
  733. * reparent dot entry children to the "real" (parent) directory if
  734. * there are not subdirectory siblings at the level of the dot entry.
  735. **/
  736. void cleanupDotEntries();
  737. bool _isDotEntry; // Flag: is this entry a "dot entry"?
  738. bool _isMountPoint; // Flag: is this a mount point?
  739. int _pendingReadJobs; // number of open directories in this subtree
  740. // Children management
  741. KFileInfo * _firstChild; // pointer to the first child
  742. KFileInfo * _dotEntry; // pseudo entry to hold non-dir children
  743. // Some cached values
  744. KFileSize _totalSize;
  745. KFileSize _totalBlocks;
  746. int _totalItems;
  747. int _totalSubDirs;
  748. int _totalFiles;
  749. time_t _latestMtime;
  750. bool _summaryDirty; // dirty flag for the cached values
  751. bool _beingDestroyed;
  752. KDirReadState _readState;
  753. private:
  754. void init();
  755. }; // class KDirInfo
  756. /**
  757. * A directory read job that can be queued. This is mainly to prevent
  758. * buffer thrashing because of too many directories opened at the same time
  759. * because of simultaneous reads or even system resource consumption
  760. * (directory handles in this case).
  761. *
  762. * Objects of this kind are transient by nature: They live only as long as
  763. * the job is queued or executed. When it's done, the data is contained in
  764. * the corresponding @ref KDirInfo subtree of the corresponding @ref
  765. * KDirTree.
  766. *
  767. * For each entry automatically a @ref KFileInfo or @ref KDirInfo will be
  768. * created and added to the parent @ref KDirInfo. For each directory a new
  769. * @ref KDirReadJob will be created and added to the @ref KDirTree 's job
  770. * queue.
  771. *
  772. * Notice: This class contains pure virtuals - you cannot use it
  773. * directly. Derive your own class from it or use one of
  774. * @ref KLocalDirReadJob or @ref KAnyDirReadJob.
  775. *
  776. * @short Abstract base class for directory reading.
  777. **/
  778. class KDirReadJob
  779. {
  780. public:
  781. /**
  782. * Constructor.
  783. **/
  784. KDirReadJob( KDirTree *tree, KDirInfo *dir );
  785. /**
  786. * Destructor.
  787. **/
  788. virtual ~KDirReadJob();
  789. /**
  790. * Start reading the directory. Prior to this nothing happens.
  791. *
  792. * Please notice there is no corresponding abortReading() call:
  793. * Simply delete the reader if the user requests to abort reading.
  794. *
  795. * Derived classes need to implement this method.
  796. **/
  797. virtual void startReading() = 0;
  798. /**
  799. * Returns the corresponding @ref KDirInfo item.
  800. **/
  801. virtual KDirInfo * dir() { return _dir; }
  802. protected:
  803. /**
  804. * Notification that a new child has been added.
  805. *
  806. * Derived classes are required to call this whenever a new child is
  807. * added so this notification can be passed up to the @ref KDirTree
  808. * which in turn emits a corresponding signal.
  809. **/
  810. void childAdded( KFileInfo *newChild );
  811. /**
  812. * Notification that a child is about to be deleted.
  813. *
  814. * Derived classes are required to call this just before a child is
  815. * deleted so this notification can be passed up to the @ref KDirTree
  816. * which in turn emits a corresponding signal.
  817. *
  818. * Derived classes are not required to handle child deletion at all,
  819. * but if they do, calling this method is required.
  820. **/
  821. void deletingChild( KFileInfo *deletedChild );
  822. KDirTree * _tree;
  823. KDirInfo * _dir;
  824. };
  825. /**
  826. * Impementation of the abstract @ref KDirReadJob class that reads a local
  827. * directory.
  828. *
  829. * This will use lstat() system calls rather than KDE's network transparent
  830. * directory services since lstat() unlike the KDE services can obtain
  831. * information about the device (i.e. file system) a file or directory
  832. * resides on. This is important if you wish to limit directory scans to
  833. * one file system - which is most desirable when that one file system runs
  834. * out of space.
  835. *
  836. * @short Directory reader that reads one local directory.
  837. **/
  838. class KLocalDirReadJob: public KDirReadJob
  839. {
  840. public:
  841. /**
  842. * Constructor.
  843. **/
  844. KLocalDirReadJob( KDirTree * tree, KDirInfo * dir );
  845. /**
  846. * Destructor.
  847. **/
  848. virtual ~KLocalDirReadJob();
  849. /**
  850. * Start reading the directory. Prior to this nothing happens.
  851. *
  852. * Inherited and reimplemented from @ref KDirReadJob.
  853. **/
  854. virtual void startReading();
  855. /**
  856. * Obtain information about the URL specified and create a new @ref
  857. * KFileInfo or a @ref KDirInfo (whatever is appropriate) from that
  858. * information. Use @ref KFileInfo::isDirInfo() to find out which.
  859. * Returns 0 if such information cannot be obtained (i.e. the
  860. * appropriate stat() call fails).
  861. **/
  862. static KFileInfo * stat( const KURL & url,
  863. KDirTree * tree,
  864. KDirInfo * parent = 0 );
  865. protected:
  866. DIR * _diskDir;
  867. };
  868. /**
  869. * Generic impementation of the abstract @ref KDirReadJob class, using
  870. * KDE's network transparent IO methods.
  871. *
  872. * This is much more generic than @ref KLocalDirReadJob since it supports
  873. * protocols like 'ftp', 'http', 'smb', 'tar' etc., too. Its only drawback
  874. * is that is cannot be prevented from crossing file system boundaries -
  875. * which makes it pretty useless for figuring out the cause of a 'file
  876. * system full' error.
  877. *
  878. * @short Generic directory reader that reads one directory, remote or local.
  879. **/
  880. class KAnyDirReadJob: public TQObject, public KDirReadJob
  881. {
  882. Q_OBJECT
  883. public:
  884. /**
  885. * Constructor.
  886. **/
  887. KAnyDirReadJob( KDirTree * tree, KDirInfo * dir );
  888. /**
  889. * Destructor.
  890. **/
  891. virtual ~KAnyDirReadJob();
  892. /**
  893. * Start reading the directory. Prior to this nothing happens.
  894. *
  895. * Inherited and reimplemented from @ref KDirReadJob.
  896. **/
  897. virtual void startReading();
  898. /**
  899. * Obtain information about the URL specified and create a new @ref
  900. * KFileInfo or a @ref KDirInfo (whatever is appropriate) from that
  901. * information. Use @ref KFileInfo::isDirInfo() to find out which.
  902. * Returns 0 if such information cannot be obtained (i.e. the
  903. * appropriate stat() call fails).
  904. **/
  905. static KFileInfo * stat( const KURL & url,
  906. KDirTree * tree,
  907. KDirInfo * parent = 0 );
  908. /**
  909. * Obtain the owner of the URL specified.
  910. *
  911. * This is a moderately expensive operation since it involves a network
  912. * transparent stat() call.
  913. **/
  914. static TQString owner( KURL url );
  915. protected slots:
  916. /**
  917. * Receive directory entries from a TDEIO job.
  918. **/
  919. void entries( TDEIO::Job * job,
  920. const TDEIO::UDSEntryList & entryList );
  921. /**
  922. * TDEIO job is finished.
  923. **/
  924. void finished( TDEIO::Job * job );
  925. protected:
  926. TDEIO::ListJob * _job;
  927. };
  928. /**
  929. * This class provides some infrastructure as well as global data for a
  930. * directory tree. It acts as the glue that holds things together: The root
  931. * item from which to descend into the subtree, the read queue and some
  932. * global policies (like whether or not to cross file systems while reading
  933. * directories).
  934. *
  935. * @short Directory tree global data and infrastructure
  936. **/
  937. class KDirTree: public TQObject
  938. {
  939. Q_OBJECT
  940. public:
  941. /**
  942. * Constructor.
  943. *
  944. * Remember to call @ref startReading() after the constructor and
  945. * setting up connections.
  946. **/
  947. KDirTree();
  948. /**
  949. * Destructor.
  950. **/
  951. virtual ~KDirTree();
  952. public slots:
  953. /**
  954. * Actually start reading.
  955. *
  956. * It's not very pretty this is required as an extra method, but this
  957. * cannot simply be done in the constructor: We need to give the caller
  958. * a chance to set up TQt signal connections, and for this the
  959. * constructor must return before any signals are sent, i.e. before
  960. * anything is read.
  961. **/
  962. void startReading( const KURL & url );
  963. /**
  964. * Forcefully stop a running read process.
  965. **/
  966. void abortReading();
  967. /**
  968. * Refresh a subtree, i.e. read its contents from disk again.
  969. *
  970. * The old subtree will be deleted and rebuilt from scratch, i.e. all
  971. * pointers to elements within this subtree will become invalid (a
  972. * @ref subtreeDeleted() signal will be emitted to notify about that
  973. * fact).
  974. *
  975. * When 0 is passed, the entire tree will be refreshed, i.e. from the
  976. * root element on.
  977. **/
  978. void refresh( KFileInfo *subtree = 0 );
  979. /**
  980. * Select some other item in this tree. Triggers the @ref
  981. * selectionChanged() signal - even to the sender of this signal,
  982. * i.e. take care not to cause endless signal ping-pong!
  983. *
  984. * Select nothing if '0' is passed.
  985. **/
  986. void selectItem( KFileInfo *newSelection );
  987. /**
  988. * Delete a subtree.
  989. **/
  990. void deleteSubtree( KFileInfo *subtree );
  991. public:
  992. /**
  993. * Returns the root item of this tree.
  994. *
  995. * Currently, there can only be one single root item for each tree.
  996. */
  997. KFileInfo * root() const { return _root; }
  998. /**
  999. * Locate a child somewhere in the tree whose URL (i.e. complete path)
  1000. * matches the URL passed. Returns 0 if there is no such child.
  1001. *
  1002. * Notice: This is a very expensive operation since the entire tree is
  1003. * searched recursively.
  1004. *
  1005. * 'findDotEntries' specifies if locating "dot entries" (".../<Files>")
  1006. * is desired.
  1007. *
  1008. * This is just a convenience method that maps to
  1009. * KDirTree::root()->locate( url, findDotEntries )
  1010. **/
  1011. KFileInfo * locate( TQString url, bool findDotEntries = false )
  1012. { return _root ? _root->locate( url, findDotEntries ) : 0; }
  1013. /**
  1014. * Notification of a finished directory read job.
  1015. * All read jobs are required to call this upon (successful or
  1016. * unsuccessful) completion.
  1017. **/
  1018. void jobFinishedNotify( KDirReadJob *job );
  1019. /**
  1020. * Add a new directory read job to the queue.
  1021. **/
  1022. void addJob( KDirReadJob * job );
  1023. /**
  1024. * Obtain the directory read method for this tree:
  1025. * KDirReadLocal use opendir() and lstat()
  1026. * KDirReadKDirLister use KDE 2.x's KDirLister
  1027. **/
  1028. KDirReadMethod readMethod() const { return _readMethod; }
  1029. /**
  1030. * Should directory scans cross file systems?
  1031. *
  1032. * Notice: This can only be avoided with local directories where the
  1033. * device number a file resides on can be obtained.
  1034. * Remember, that's what this KDirStat business is all about. ;-)
  1035. **/
  1036. bool crossFileSystems() const { return _crossFileSystems; }
  1037. /**
  1038. * Set or unset the "cross file systems" flag.
  1039. **/
  1040. void setCrossFileSystems( bool doCross ) { _crossFileSystems = doCross; }
  1041. /**
  1042. * Return the tree's current selection.
  1043. *
  1044. * Even though the KDirTree by itself doesn't have a visual
  1045. * representation, it supports the concept of one single selected
  1046. * item. Views can use this to transparently keep track of this single
  1047. * selected item, notifying the KDirTree and thus other views with @ref
  1048. * KDirTree::selectItem() . Attached views should connect to the @ref
  1049. * selectionChanged() signal to be notified when the selection changes.
  1050. *
  1051. * NOTE: This method returns 0 if nothing is selected.
  1052. **/
  1053. KFileInfo * selection() const { return _selection; }
  1054. /**
  1055. * Notification that a child has been added.
  1056. *
  1057. * Directory read jobs are required to call this for each child added
  1058. * so the tree can emit the corresponding @ref childAdded() signal.
  1059. **/
  1060. virtual void childAddedNotify( KFileInfo *newChild );
  1061. /**
  1062. * Notification that a child is about to be deleted.
  1063. *
  1064. * Directory read jobs are required to call this for each deleted child
  1065. * so the tree can emit the corresponding @ref deletingChild() signal.
  1066. **/
  1067. virtual void deletingChildNotify( KFileInfo *deletedChild );
  1068. /**
  1069. * Notification that one or more children have been deleted.
  1070. *
  1071. * Directory read jobs are required to call this when one or more
  1072. * children are deleted so the tree can emit the corresponding @ref
  1073. * deletingChild() signal. For multiple deletions (e.g. entire
  1074. * subtrees) this should only happen once at the end.
  1075. **/
  1076. virtual void childDeletedNotify();
  1077. /**
  1078. * Send a @ref progressInfo() signal to keep the user entertained while
  1079. * directories are being read.
  1080. **/
  1081. void sendProgressInfo( const TQString &infoLine );
  1082. /**
  1083. * Send a @ref finalizeLocal() signal to give views a chance to
  1084. * finalize the display of this directory level - e.g. clean up dot
  1085. * entries, set the final "expandable" state etc.
  1086. **/
  1087. void sendFinalizeLocal( KDirInfo *dir );
  1088. /**
  1089. * Returns 'true' if this tree uses the 'file:/' protocol (regardless
  1090. * of local or network transparent directory reader).
  1091. **/
  1092. bool isFileProtocol() { return _isFileProtocol; }
  1093. /**
  1094. * Returns 'true' if directory reading is in progress in this tree.
  1095. **/
  1096. bool isBusy() { return _isBusy; }
  1097. signals:
  1098. /**
  1099. * Emitted when a child has been added.
  1100. **/
  1101. void childAdded( KFileInfo *newChild );
  1102. /**
  1103. * Emitted when a child is about to be deleted.
  1104. **/
  1105. void deletingChild( KFileInfo *deletedChild );
  1106. /**
  1107. * Emitted after a child is deleted. If you are interested which child
  1108. * it was, better use the @ref deletingChild() signal.
  1109. * @ref childDeleted() is only useful to rebuild a view etc. completely.
  1110. * If possible, this signal is sent only once for multiple deletions -
  1111. * e.g., when entire subtrees are deleted.
  1112. **/
  1113. void childDeleted();
  1114. /**
  1115. * Emitted when reading is started.
  1116. **/
  1117. void startingReading();
  1118. /**
  1119. * Emitted when reading this directory tree is finished.
  1120. **/
  1121. void finished();
  1122. /**
  1123. * Emitted when reading this directory tree has been aborted.
  1124. **/
  1125. void aborted();
  1126. /**
  1127. * Emitted when reading a directory is finished.
  1128. * This does _not_ mean reading all subdirectories is finished, too -
  1129. * only this directory level is complete!
  1130. *
  1131. * WARNING: 'dir' may be 0 if the the tree's root could not be read.
  1132. *
  1133. * Use this signal to do similar cleanups like
  1134. * @ref KDirInfo::finalizeLocal(), e.g. cleaning up unused / undesired
  1135. * dot entries like in @ref KDirInfo::cleanupDotEntries().
  1136. **/
  1137. void finalizeLocal( KDirInfo *dir );
  1138. /**
  1139. * Emitted when the current selection has changed, i.e. whenever some
  1140. * attached view triggers the @ref selectItem() slot or when the
  1141. * current selection is deleted.
  1142. *
  1143. * NOTE: 'newSelection' may be 0 if nothing is selected.
  1144. **/
  1145. void selectionChanged( KFileInfo *newSelection );
  1146. /**
  1147. * Single line progress information, emitted when the read status
  1148. * changes - typically when a new directory is being read. Connect to a
  1149. * status bar etc. to keep the user entertained.
  1150. **/
  1151. void progressInfo( const TQString &infoLine );
  1152. protected slots:
  1153. /**
  1154. * Time-sliced work procedure to be performed while the application is
  1155. * in the main loop: Read some directory entries, but relinquish
  1156. * control back to the application so it can maintain some
  1157. * responsiveness. This method uses single-shot timers of minimal
  1158. * duration to activate itself as soon as there are no more user events
  1159. * to process. Call this only once directly after inserting a read job
  1160. * into the job queue.
  1161. **/
  1162. void timeSlicedRead();
  1163. /**
  1164. * Read some parameters from the global @ref TDEConfig object.
  1165. **/
  1166. void readConfig();
  1167. protected:
  1168. KFileInfo * _root;
  1169. KFileInfo * _selection;
  1170. TQPtrQueue<KDirReadJob> _jobQueue;
  1171. KDirReadMethod _readMethod;
  1172. bool _crossFileSystems;
  1173. bool _enableLocalDirReader;
  1174. bool _isFileProtocol;
  1175. bool _isBusy;
  1176. };
  1177. //----------------------------------------------------------------------
  1178. // Static Functions
  1179. //----------------------------------------------------------------------
  1180. /**
  1181. * Make a valid, fixed and cleaned URL from a (possibly dirty) URL or maybe
  1182. * a path.
  1183. **/
  1184. KURL fixedUrl( const TQString & dirtyUrl );
  1185. /**
  1186. * Format a file / subtree size human readable, i.e. in "GB" / "MB"
  1187. * etc. rather than huge numbers of digits.
  1188. *
  1189. * Note: For kdDebug() etc., operator<< is overwritten to do exactly that:
  1190. *
  1191. * kdDebug() << "Size: " << x->totalSize() << endl;
  1192. **/
  1193. TQString formatSize ( KFileSize lSize );
  1194. /**
  1195. * Print the debugUrl() of a @ref KFileInfo in a debug stream.
  1196. **/
  1197. inline kdbgstream & operator<< ( kdbgstream & stream, const KFileInfo * info )
  1198. {
  1199. if ( info )
  1200. stream << info->debugUrl();
  1201. else
  1202. stream << "<NULL>";
  1203. return stream;
  1204. }
  1205. /**
  1206. * Human-readable output of a file size in a debug stream.
  1207. **/
  1208. inline kdbgstream & operator<< ( kdbgstream & stream, KFileSize lSize )
  1209. {
  1210. stream << formatSize( lSize );
  1211. return stream;
  1212. }
  1213. } // namespace KDirStat
  1214. #endif // ifndef KDirTree_h
  1215. // EOF