From 3c7b870f367df150ea60eb9d6bb2fd41646545d7 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 3 Feb 2010 01:26:04 +0000 Subject: Added abandoned Filelight application git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/filelight@1084392 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- src/part/fileTree.h | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 src/part/fileTree.h (limited to 'src/part/fileTree.h') diff --git a/src/part/fileTree.h b/src/part/fileTree.h new file mode 100644 index 0000000..25ac6fb --- /dev/null +++ b/src/part/fileTree.h @@ -0,0 +1,238 @@ +//Author: Max Howell , (C) 2004 +//Copyright: See COPYING file that comes with this distribution + +#ifndef FILETREE_H +#define FILETREE_H + +#include //qstrdup +#include //decodeName() +#include + + +//TODO these are pointlessly general purpose now, make them incredibly specific + + + +typedef unsigned long int FileSize; +typedef unsigned long int Dirsize; //**** currently unused + +template class Iterator; +template class ConstIterator; +template class Chain; + +template +class Link +{ +public: + Link( T* const t ) : prev( this ), next( this ), data( t ) {} + Link() : prev( this ), next( this ), data( 0 ) {} + +//TODO unlinking is slow and you don't use it very much in this context. +// ** Perhaps you can make a faster deletion system that doesn't bother tidying up first +// ** and then you MUST call some kind of detach() function when you remove elements otherwise + ~Link() { delete data; unlink(); } + + friend class Iterator; + friend class ConstIterator; + friend class Chain; + +private: + void unlink() { prev->next = next; next->prev = prev; prev = next = this; } + + Link* prev; + Link* next; + + T* data; //ensure only iterators have access to this +}; + + +template +class Iterator +{ +public: + Iterator() : link( 0 ) { } //**** remove this, remove this REMOVE THIS!!! dangerous as your implementation doesn't test for null links, always assumes they can be derefenced + Iterator( Link *p ) : link( p ) { } + + bool operator==( const Iterator& it ) const { return link == it.link; } + bool operator!=( const Iterator& it ) const { return link != it.link; } + bool operator!=( const Link *p ) const { return p != link; } + + //here we have a choice, really I should make two classes one const the other not + const T* operator*() const { return link->data; } + T* operator*() { return link->data; } + + Iterator& operator++() { link = link->next; return *this; } //**** does it waste time returning in places where we don't use the retval? + + bool isNull() const { return (link == 0); } //REMOVE WITH ABOVE REMOVAL you don't want null iterators to be possible + + void transferTo( Chain &chain ) + { + chain.append( remove() ); + } + + T* const remove() //remove from list, delete Link, data is returned NOT deleted + { + T* const d = link->data; + Link* const p = link->prev; + + link->data = 0; + delete link; + link = p; //make iterator point to previous element, YOU must check this points to an element + + return d; + } + +private: + Link *link; +}; + + +template +class ConstIterator +{ +public: + ConstIterator( Link *p ) : link( p ) { } + + bool operator==( const Iterator& it ) const { return link == it.link; } + bool operator!=( const Iterator& it ) const { return link != it.link; } + bool operator!=( const Link *p ) const { return p != link; } + + const T* operator*() const { return link->data; } + + ConstIterator& operator++() { link = link->next; return *this; } + +private: + const Link *link; +}; + + +template +class Chain +{ +public: + virtual ~Chain() { empty(); } + + void append( T* const data ) + { + Link* const link = new Link( data ); + + link->prev = head.prev; + link->next = &head; + + head.prev->next = link; + head.prev = link; + } + + void transferTo( Chain &c ) + { + if( isEmpty() ) return; + + Link* const first = head.next; + Link* const last = head.prev; + + head.unlink(); + + first->prev = c.head.prev; + c.head.prev->next = first; + + last->next = &c.head; + c.head.prev = last; + } + + void empty() { while( head.next != &head ) { delete head.next; } } + + Iterator iterator() const { return Iterator( head.next ); } + ConstIterator constIterator() const { return ConstIterator( head.next ); } + const Link *end() const { return &head; } + bool isEmpty() const { return head.next == &head; } + +private: + Link head; + void operator=( const Chain& ); +}; + + +class Directory; +class QString; + +class File +{ +public: + friend class Directory; + + enum UnitPrefix { kilo, mega, giga, tera }; + + static const uint DENOMINATOR[4]; + +public: + File( const char *name, FileSize size ) : m_parent( 0 ), m_name( qstrdup( name ) ), m_size( size ) {} + virtual ~File() { delete [] m_name; } + + const Directory *parent() const { return m_parent; } + const char *name8Bit() const { return m_name; } + const FileSize size() const { return m_size; } + QString name() const { return QFile::decodeName( m_name ); } + + virtual bool isDirectory() const { return false; } + + QString fullPath( const Directory* = 0 ) const; + QString humanReadableSize( UnitPrefix key = mega ) const; + +public: + static QString humanReadableSize( uint size, UnitPrefix Key = mega ); + +protected: + File( const char *name, FileSize size, Directory *parent ) : m_parent( parent ), m_name( qstrdup( name ) ), m_size( size ) {} + + Directory *m_parent; //0 if this is treeRoot + char *m_name; + FileSize m_size; //in units of KiB + +private: + File( const File& ); + void operator=( const File& ); +}; + + +class Directory : public Chain, public File +{ +public: + Directory( const char *name ) : File( name, 0 ), m_children( 0 ) {} //DON'T pass the full path! + + uint children() const { return m_children; } + virtual bool isDirectory() const { return true; } + + ///appends a Directory + void append( Directory *d, const char *name=0 ) + { + if( name ) { + delete [] d->m_name; + d->m_name = qstrdup( name ); } //directories that had a fullpath copy just their names this way + + m_children += d->children(); //doesn't include the dir itself + d->m_parent = this; + append( (File*)d ); //will add 1 to filecount for the dir itself + } + + ///appends a File + void append( const char *name, FileSize size ) + { + append( new File( name, size, this ) ); + } + +private: + void append( File *p ) + { + m_children++; + m_size += p->size(); + Chain::append( p ); + } + + uint m_children; + +private: + Directory( const Directory& ); //undefined + void operator=( const Directory& ); //undefined +}; + +#endif -- cgit v1.2.1