Logo Search packages:      
Sourcecode: k4dirstat version File versions  Download package

kdirtreeview.h

/*
 *   File name:   kdirtreeview.h
 *   Summary:     High level classes for KDirStat
 *   License:     LGPL - See file COPYING.LIB for details.
 *   Author:      Stefan Hundhammer <sh@suse.de>
 *              Joshua Hodosh <kdirstat@grumpypenguin.org>
 *
 *   Updated:     2010-02-01
 */


#ifndef KDirTreeView_h
#define KDirTreeView_h


#ifdef HAVE_CONFIG_H
#   include <config.h>
#endif

#include <qdatetime.h>
#include <q3listview.h>
#include <qpixmap.h>
#include <KDE/K3ListView>
#include <q3painter.h>
#include "kdirtree.h"

#define DEBUG_COUNTERS        10


// Forward declarations
class QWidget;
class QTimer;
class Q3PopupMenu;
class KPacManAnimation;

#define USE_KLISTVIEW 0


// Open a new name space since KDE's name space is pretty much cluttered
// already - all names that would even remotely match are already used up,
// yet the resprective classes don't quite fit the purposes required here.

namespace KDirStat
{
#define KDirTreeViewMaxFillColor    16


#if USE_KLISTVIEW
#   define KDirTreeViewParentClass        KListView
#else
#   define KDirTreeViewParentClass        Q3ListView
#endif

    class KDirTreeViewItem;


00057     class KDirTreeView: public Q3ListView
    // Using
    //            class KDirTreeView: public KDirTreeViewParentClass
    // or some other 'ifdef' ... construct seems to confuse "moc".
    {
      Q_OBJECT

    public:
      /**
       * Default constructor.
       **/
      KDirTreeView( QWidget * parent = 0 );

      /**
       * Destructor.
       **/
      virtual ~KDirTreeView();

      /**
       * Locate the counterpart to an original tree item "wanted" somewhere
       * within this view tree. Returns 0 on failure.
       * If "lazy" is set, only the open part of the tree is searched.
       * "doClone" specifies whether or not to (deferred) clone nodes that
       * are not cloned yet. This is only used if "lazy" is false.
       **/
      KDirTreeViewItem *      locate( KFileInfo *     wanted,
                              bool        lazy  = true,
                              bool        doClone     = true );

      /**
       * Get the first child of this view or 0 if there is none.
       * Use the child's next() method to get the next child.
       * Reimplemented from @ref QListView.
       **/
00091       KDirTreeViewItem *      firstChild() const
          { return (KDirTreeViewItem *) KDirTreeViewParentClass::firstChild(); }

      /**
       * Return the currently selected item or 0, if none is selected.
       **/
00097       KDirTreeViewItem *      selection() const { return _selection; }

      /**
       * Returns the default level until which items are opened by default
       * (unless they are dot entries).
       **/
00103       int   openLevel()       const { return _openLevel;          }

      /**
       * Returns true if the view tree is to be cloned lazily, i.e. only
       * those view tree branches that are really visible are synced with the
       * original tree.
       **/
00110       bool  doLazyClone()           const { return _doLazyClone;        }

      /**
       * Enable / disable PacMan animation in this tree view during directory
       * reading. This is disabled by default since it eats quite some
       * performance.
       **/
00117       void  enablePacManAnimation( bool enable ) { _doPacManAnimation = enable; }
      /**
       * Returns true if the PacMan animation is to be used during directory
       * reading.
       **/
00122       bool  doPacManAnimation()     const { return _doPacManAnimation;  }

      /**
       * Returns the number of open items in the entire tree.
       **/
      int   openCount();

      /**
       * Return the percentage bar fill color for the specified directory
       * level (0..MaxInt). Wraps around every usedFillColors() colors.
       **/
      const QColor &    fillColor( int level ) const;

      /**
       * Very much like @ref fillColor(), but doesn't wrap around at @ref
       * usedFillColors(), but at KDirTreeViewMaxFillColor.
       **/
      const QColor &    rawFillColor( int level ) const;

      /**
       * Set the fill color of percentage bars of the specified directory
       * level (0..KDirTreeViewMaxFillColor-1).
       *
       * Calling repaint() after setting all desired colors is the
       * caller's responsibility.
       **/
      void setFillColor( int level, const QColor &color );

      /**
       * Set all tree colors to default values.
       **/
      void setDefaultFillColors();

      /**
       * Set the number of used percentage bar fill colors
       * (1..KDirTreeViewMaxFillColor).
       **/
      void setUsedFillColors( int usedFillColors );

      /**
       * Returns the number of used percentage bar fill colors.
       **/
00164       int usedFillColors()    const { return _usedFillColors;     }

      /**
       * Set the tree background color.
       *
       * Calling repaint() after setting all desired colors is the
       * caller's responsibility.
       **/
      void setTreeBackground( const QColor &color );

      /**
       * Returns the tree background color.
       **/
00177       const QColor &    treeBackground()        const { return _treeBackground;     }

      /**
       * Returns the background color for percentage bars.
       **/
00182       const QColor &    percentageBarBackground()     const { return _percentageBarBackground; }

      /**
       * (Try to) ensure good contrast between the tree background and the
       * percentage bars' 3D edges - prevent ugly 3D effects which will
       * inevitably be the case for a white background (which unfortunately
       * is very common): The percentage bars use white and black for 3D
       * borders - like any other widget. But other widgets normally can
       * assume their parent widget uses some more neutral color so white and
       * black will result in at least some minimal contrast.
       *
       * This function automagically sets a reasonable default background
       * color for the tree display: If the current color scheme's document
       * background color (as used for input fields, lists etc.) is white or
       * black, use the palette midlight color (the same color as "normal"
       * widgets like push buttons etc., but brighter). For all other colors
       * than white, the document background color (the palette base color)
       * is used.
       **/
      void ensureContrast();

      /**
       * Set the sort column.
       *
       * Reimplemented from QListView so we can keep track of the sort column.
       **/
      virtual void setSorting( int column, bool increasing = TRUE );

      /**
       * Returns the internal @ref KDirTree this view works on.
       * Handle with caution: This might be short-lived information.
       * The view might choose to create a new tree shortly after returning
       * this, so don't store this pointer internally.
       **/
00216       KDirTree *tree()              { return _tree; }

      int   nameCol()         const { return _nameCol;            }
      int   iconCol()         const { return _iconCol;            }
      int   percentBarCol()         const { return _percentBarCol;      }
      int   percentNumCol()         const { return _percentNumCol;      }
      int   totalSizeCol()          const { return _totalSizeCol;       }
      int   workingStatusCol()      const { return _workingStatusCol;   }
      int   ownSizeCol()            const { return _ownSizeCol;         }
      int   totalItemsCol()         const { return _totalItemsCol;      }
      int   totalFilesCol()         const { return _totalFilesCol;      }
      int   totalSubDirsCol() const { return _totalSubDirsCol;    }
      int   latestMtimeCol()  const { return _latestMtimeCol;     }
      int   readJobsCol()           const { return _readJobsCol;        }
      int   sortCol()         const   { return _sortCol;          }

      QPixmap     openDirIcon()           const { return _openDirIcon;        }
      QPixmap     closedDirIcon()         const { return _closedDirIcon;      }
      QPixmap     openDotEntryIcon()      const { return _openDotEntryIcon;   }
      QPixmap     closedDotEntryIcon()    const { return _closedDotEntryIcon; }
      QPixmap     unreadableDirIcon()     const { return _unreadableDirIcon;  }
      QPixmap mountPointIcon()      const { return _mountPointIcon;     }
      QPixmap     fileIcon()        const { return _fileIcon;           }
      QPixmap     symLinkIcon()           const { return _symLinkIcon;        }
      QPixmap blockDevIcon()        const       { return _blockDevIcon;       }
      QPixmap charDevIcon()         const       { return _charDevIcon;        }
      QPixmap fifoIcon()            const       { return _fifoIcon;           }
      QPixmap stopIcon()            const       { return _stopIcon;           }
      QPixmap     workingIcon()           const { return _workingIcon;        }
      QPixmap     readyIcon()       const { return _readyIcon;          }


      /**
       * Set function name of debug function #i
       **/
      void  setDebugFunc( int i, const QString & functionName );

      /**
       * Increase debug counter #i
       **/
      void  incDebugCount( int i );


    public slots:

      /**
       * Open a directory URL. Assume "file:" protocol unless otherwise specified.
       **/
      void openURL( KUrl url );

      /**
       * Refresh (i.e. re-read from disk) the entire tree.
       **/
      void refreshAll();

      /**
       * Refresh (i.e. re-read from disk) the selected subtree.
       **/
      void refreshSelected();

      /**
       * Forcefully stop a running read process.
       **/
      void abortReading();

      /**
       * Clear this view's contents.
       **/
      void clear();

        /**
       * Select a (QListViewItem) item. Triggers selectionChanged() signals.
       **/
        void selectItem( Q3ListViewItem *item );

        /**
       * Select an item. Triggers selectionChanged() signals.
       * Overloaded for convenience.
       **/
00295         void selectItem( KDirTreeViewItem *item ) { selectItem( (Q3ListViewItem *) item ); }

      /**
       * Select a KDirTree item. Used for connecting the @ref
       * KDirTree::selectionChanged() signal.
       **/
      void selectItem( KFileInfo *item );

      /**
       * Clear the current selection. Triggers selectionChanged() signals.
       **/
      void clearSelection();

      /**
       * Close all tree branches except the one specified.
       **/
      void closeAllExcept( KDirTreeViewItem *except );

      /**
       * Send a standardized mail to the owner of the selected branch.
       * The user will get a mailer window where he can edit that mail all he
       * likes before deciding to send or discard it.
       *
       * The mail includes all currently open branches from the selected
       * branch on.
       **/
      void sendMailToOwner();

      /**
       * Notification of a change in the KDE palette, i.e. the user selected
       * and applied different colors in the KDE control center.
       **/
      void paletteChanged();

      /**
       * Read configuration and initialize variables accordingly.
       * Will be called automatically in the constructor.
       **/
      void readConfig();

      /**
       * Save configuraton.
       **/
      void saveConfig() const;

      /**
       * Emit a @ref userActivity() signal worth 'points' activity points.
       **/
      void logActivity( int points );

      /**
       * Returns the minimum recommended size for this widget.
       * Reimplemented from QWidget.
       **/
00349       virtual QSize minimumSizeHint() const { return QSize( 0, 0 ); }

      /**
       * Write the current tree to a cache file.
       *
       * Returns true if OK, false upon error.
       **/
      bool writeCache( const QString & cacheFileName );

      /**
       * Read a cache file.
       **/
      void readCache( const QString & cacheFileName );


    protected slots:

      /**
       * Add a child as a clone of original tree item "newChild" to this view
       * tree.
       **/
      void  addChild    ( KFileInfo *newChild );

      /**
       * Delete a cloned child.
       **/
      void  deleteChild ( KFileInfo *newChild );

      /**
       * Recursively update the visual representation of the summary fields.
       * This update is as lazy as possible for optimum performance since it
       * is called very frequently as a cyclic update.
       **/
      void  updateSummary();

      /**
       * Signal end of all read jobs, finalize display and terminate pending
       * cyclic visual update.
       **/
      void  slotFinished();

      /**
       * Signal abortion of all read jobs, finalize display and terminate pending
       * cyclic visual update.
       **/
      void  slotAborted();

      /**
       * Signal end of one read job at this level and finalize display of
       * this level.
       **/
      void  finalizeLocal( KDirInfo *dir );

      /**
       * Display progress information in the status bar. Automatically adds
       * the elapsed time of a directory scan.
       **/
      void  sendProgressInfo( const QString & currentDir = "" );


#if QT_VERSION < 300
      /**
       * "moc" doesnt't seem to handle default arguments well, so this is an
       * overloaded slot that uses the internally stored current directory.
       **/
      void  sendProgressInfo();
#endif

        /**
       * Set up everything prior to reading: Cyclic update timer, display
       * busy state, default sorting, stopwatch.
       **/
        void      prepareReading();

      /**
       * Change the tree display to "busy" state, i.e. add a column to
       * display the number of pending read jobs for each level.
       **/
      void  busyDisplay();

      /**
       * Change the tree display back to "idle" state, i.e. remove columns
       * that are useful only while directories are being read, like the
       * pending read jobs column.
       **/
      void  idleDisplay();

      /**
       * Pop up context menu (i.e. emit the contextMenu() signal) or open a
       * small info popup with exact information, depending on 'column'.
       **/
      void  popupContextMenu  ( Q3ListViewItem *      listViewItem,
                                const QPoint &  pos,
                                int                   column );

      /**
       * Pop up info window with exact byte size.
       **/
      void  popupContextSizeInfo    ( const QPoint &  pos,
                                KFileSize       size );

      /**
       * Pop up info window with arbitrary one-line text.
       **/
      void  popupContextInfo  ( const QPoint &  pos,
                                const QString &       info );


      /**
       * Notification that a column has just been resized, thus may need
       * repaining.
       **/
        void columnResized( int column, int oldSize, int newSize );


    signals:

      /**
       * Single line progress information, emitted when the read status
       * changes - typically when a new directory is being read. Connect to a
       * status bar etc. to keep the user busy.
       **/
      void progressInfo( const QString &infoLine );

      /**
       * Emitted when reading is started.
       **/
      void startingReading();

      /**
       * Emitted when reading this tree is finished.
       **/
      void finished();

      /**
       * Emitted when reading this tree has been aborted.
       **/
      void aborted();

      /**
       * Emitted when the currently selected item changes.
       * Caution: 'item' may be 0 when the selection is cleared.
       **/
      void selectionChanged( KDirTreeViewItem *item );

      /**
       * Emitted when the currently selected item changes.
       * Caution: 'item' may be 0 when the selection is cleared.
       **/
      void selectionChanged( KFileInfo *item );

      /**
       * Emitted when a context menu for this item should be opened.
       * (usually on right click). 'pos' contains the click's mouse
       * coordinates.
       *
       * NOTE:
       *
       * This is _not_ the same as @ref QListView::rightButtonClicked():
       * The context menu may not open on a right click on every column,
       * usually only in the nameCol().
       **/
      void contextMenu( KDirTreeViewItem *item, const QPoint &pos );

      /**
       * Emitted at user activity. Some interactive actions are assigned an
       * amount of "activity points" that can be used to judge whether or not
       * the user is actually using this program or if it's just idly sitting
       * around on the desktop. This is intended for use together with a @ref
       * KActivityTracker.
       **/
      void userActivity( int points );


    protected:

      /**
       * Create a new tree (and delete the old one if there is one)
       **/
      void createTree();

      //
      // Data members
      //

      KDirTree *        _tree;
      QTimer *          _updateTimer;
      QTime             _stopWatch;
      QString                 _currentDir;
      KDirTreeViewItem *      _selection;
      Q3PopupMenu *           _contextInfo;
      int               _idContextInfo;

      int   _openLevel;
      bool  _doLazyClone;
      bool  _doPacManAnimation;
      int   _updateInterval;  // millisec
      int   _usedFillColors;
      QColor      _fillColor [ KDirTreeViewMaxFillColor ];
      QColor      _treeBackground;
      QColor      _percentageBarBackground;


      // The various columns in which to display information

      int   _nameCol;
      int   _iconCol;
      int   _percentNumCol;
      int   _percentBarCol;
      int   _totalSizeCol;
      int   _workingStatusCol;
      int   _ownSizeCol;
      int   _totalItemsCol;
      int   _totalFilesCol;
      int   _totalSubDirsCol;
      int   _latestMtimeCol;
      int   _readJobsCol;
      int   _sortCol;

      int   _debugCount[ DEBUG_COUNTERS ];
      QString     _debugFunc [ DEBUG_COUNTERS ];


      // The various icons

      QPixmap     _openDirIcon;
      QPixmap     _closedDirIcon;
      QPixmap     _openDotEntryIcon;
      QPixmap     _closedDotEntryIcon;
      QPixmap     _unreadableDirIcon;
      QPixmap _mountPointIcon;
      QPixmap     _fileIcon;
      QPixmap     _symLinkIcon;
      QPixmap _blockDevIcon;
      QPixmap _charDevIcon;
      QPixmap _fifoIcon;
      QPixmap _stopIcon;
      QPixmap     _workingIcon;
      QPixmap     _readyIcon;
    };



00592     class KDirTreeViewItem: public Q3ListViewItem
    {
    public:
      /**
       * Constructor for the root item.
       **/
      KDirTreeViewItem  ( KDirTreeView *  view,
                          KFileInfo *           orig );

      /**
       * Constructor for all other items.
       **/
      KDirTreeViewItem  ( KDirTreeView *  view,
                          KDirTreeViewItem *    parent,
                          KFileInfo *           orig );

      /**
       * Destructor.
       **/
      virtual ~KDirTreeViewItem();

      /**
       * Locate the counterpart to an original tree item "wanted" somewhere
       * within this view tree. Returns 0 on failure.
       *
       * When "lazy" is set, only the open part of the tree is searched.
       * "doClone" specifies whether or not to (deferred) clone nodes that
       * are not cloned yet. This is only used if "lazy" is false.
       * "Level" is just a hint for the current tree level for better
       * performance. It will be calculated automatically if omitted.
       **/
      KDirTreeViewItem *      locate( KFileInfo *     wanted,
                              bool        lazy  = true,
                              bool        doClone     = true,
                              int         level = -1 );

      /**
       * Recursively update the visual representation of the summary fields.
       * This update is as lazy as possible for optimum performance.
       **/
      void              updateSummary();

      /**
       * Bring (the top level of) this branch of the view tree in sync with
       * the original tree. Does _not_ recurse into subdirectories - only
       * this level of this branch is processed. Called when lazy tree
       * cloning is in effect and this branch is about to be opened.
       **/
      void              deferredClone();


      /**
       * Finalize this level - clean up unneeded / undesired dot entries.
       **/
      void              finalizeLocal();

      /**
       * Returns the corresponding view.
       **/
00651       KDirTreeView *          view()            { return _view;   }


      /**
       * Returns the parent view item or 0 if this is the root.
       **/
00657       KDirTreeViewItem *      parent()    { return _parent; }

      /**
       * Returns the corresponding original item of the "real" (vs. view)
       * tree where all the important information resides.
       **/
00663       KFileInfo *       orig()            { return _orig;   }

      /**
       * Returns the first child of this item or 0 if there is none.
       * Use the child's next() method to get the next child.
       * Reimplemented from @ref QListViewItem.
       **/
00670       KDirTreeViewItem *      firstChild() const
          { return (KDirTreeViewItem *) Q3ListViewItem::firstChild(); }

      /**
       * Returns the next sibling of this item or 0 if there is none.
       * (Kind of) reimplemented from @ref QListViewItem.
       **/
00677       KDirTreeViewItem *      next() const
          { return (KDirTreeViewItem *) Q3ListViewItem::nextSibling(); }

      /**
       * Comparison function used for sorting the list.
       *
       * Using this function is much more efficient than overwriting
       * QListViewItem::key() which operates on QStrings.
       *
       * Returns:
       * -1 if this <  other
       *  0 if this == other
       * +1 if this >  other
       *
       * Reimplemented from QListViewItem
       **/
      virtual int compare( Q3ListViewItem *     other,
                       int          col,
                       bool         ascending ) const;

      /**
       * Perform any necessary pending updates when a branch is opened.
       * Reimplemented from @ref QListViewItem.
       **/
      virtual void setOpen( bool open );

      /**
       * Notification that a branch in this subtree has been opened or close
       * somewhere. Don't call this if the state hasn't really changed!
       **/
      void openNotify( bool open );

      /**
       * Recursively open this subtree and all its ancestors up to the root.
       **/
      void openSubtree();

      /**
       * Recursively close all tree branches from here on downwards.
       **/
      void closeSubtree();

      /**
       * Close all tree branches except this one from the root on.
       **/
      void closeAllExceptThis();

      /**
       * Returns the number of open items in this subtree.
       **/
00727       int openCount()         const { return _openCount; }

      /**
       * Recursively return an ASCII representation of all open items from
       * here on.
       **/
      QString asciiDump();


    protected:

      /**
       * Set the appropriate icon depending on this item's type and open /
       * closed state.
       **/
      void  setIcon();

      /**
       * Remove dot entry if it doesn't have any children.
       * Reparent all of the dot entry's children if there are no
       * subdirectories on this level.
       **/
      void  cleanupDotEntries();

      /**
       * Find this entry's dot entry (clone).
       *
       * This doesn't create one if deferred cloning is in effect (which is
       * not a drawback since cloning directory nodes create a dot entry
       * clone along with the directory clone).
       *
       * Returns 0 if there is no dot entry clone.
       **/
      KDirTreeViewItem * findDotEntry() const;


      /**
       * Paint method. Reimplemented from @ref QListViewItem so different
       * colors can be used - and of course for painting percentage bars.
       *
       * Reimplemented from @ref QListViewItem.
       **/
      virtual void paintCell  ( Q3Painter *           painter,
                          const QColorGroup &   colorGroup,
                          int             column,
                          int             width,
                          int             alignment );

      /**
       * Paint a percentage bar into a @ref QListViewItem cell.
       * 'width' is the width of the entire cell.
       * 'indent' is the number of pixels to indent the bar.
       **/
      void paintPercentageBar ( float                 percent,
                          Q3Painter *           painter,
                          int             indent,
                          int             width,
                          const QColor &  fillColor,
                          const QColor &  barBackground     );

      /**
       * Generic comparison function.
       **/
      template<typename T> inline
00791       int compare( T a, T b ) const
      {
          if ( a < b ) return -1;
          if ( a > b ) return  1;
          return 0;
      }

    private:

      /**
       * Initializations common to all constructors.
       **/
      void init   ( KDirTreeView *  view,
                    KDirTreeViewItem *    parent,
                    KFileInfo *           orig );

    protected:

      // Data members

      KDirTreeView *          _view;
      KDirTreeViewItem *      _parent;
      KFileInfo *       _orig;
      KPacManAnimation *      _pacMan;
      float             _percent;
      int               _openCount;

    };


    inline kdbgstream & operator<< ( kdbgstream & stream, KDirTreeViewItem * item )
    {
      if ( item )
      {
          if ( item->orig() )
          {
            stream << item->orig()->debugUrl();
          }
          else
          {
            stream << "<NULL orig()> " << endl;
          }
      }
      else
          stream << "<NULL>";

      return stream;
    }



    //----------------------------------------------------------------------
    //                         Static Functions
    //----------------------------------------------------------------------

    /**
     * Format a file size with all digits, yet human readable using the current
     * locale's thousand separator, i.e. 12,345,678 rather than 12345678
     **/
    QString formatSizeLong( KFileSize size );

    /**
     * Format a file size for use within a QListView::key() function:
     * Right-justify and fill with leading zeroes.
     **/
    QString hexKey( KFileSize size );

    /**
     * Format a millisecond granularity time human readable.
     * Milliseconds will only be inluded if 'showMilliSeconds' is true.
     **/
    QString formatTime ( long millisec,
                   bool showMilliSeconds = false );

    /**
     * Format counters of any kind.
     *
     * Returns an empty string if 'suppressZero' is 'true' and the value of
     * 'count' is 0.
     **/
    QString formatCount( int count, bool suppressZero = false );

    /**
     * Format percentages.
     **/
    QString formatPercent( float percent );

    /**
     * Format time and date human-readable as "yyyy-mm-dd hh:mm:ss"
     * - unlike that ctime() crap that is really useless.
     * See the source for more about why this format.
     **/
    QString formatTimeDate( time_t rawTime );

    /**
     * Format time and date according to the current locale for those who
     * really must have that brain-dead ctime() format.
     **/
    QString localeTimeDate( time_t rawTime );

    /**
     * Return a color that contrasts to 'contrastColor'.
     **/
    QColor contrastingColor ( const QColor &desiredColor,
                        const QColor &contrastColor );

}     // namespace KDirStat


#endif // ifndef KDirTreeView_h


// EOF

Generated by  Doxygen 1.6.0   Back to index