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.
620 lines
14 KiB
620 lines
14 KiB
/*
|
|
|
|
ark -- archiver for the KDE project
|
|
|
|
Copyright (C)
|
|
|
|
2005: Henrique Pinto <henrique.pinto@kdemail.net>
|
|
2003: Georg Robbers <Georg.Robbers@urz.uni-hd.de>
|
|
2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com)
|
|
1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com)
|
|
1999: Francois-Xavier Duranceau duranceau@kde.org
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
// TQt includes
|
|
#include <tqpainter.h>
|
|
#include <tqwhatsthis.h>
|
|
#include <tqheader.h>
|
|
|
|
// KDE includes
|
|
#include <tdelocale.h>
|
|
#include <tdeglobal.h>
|
|
#include <kdebug.h>
|
|
#include <tdeglobalsettings.h>
|
|
#include <kmimetype.h>
|
|
|
|
#include "filelistview.h"
|
|
#include "arch.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// FileLVI implementation
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
FileLVI::FileLVI( TDEListView* lv )
|
|
: TDEListViewItem( lv ), m_fileSize( 0 ), m_packedFileSize( 0 ),
|
|
m_ratio( 0 ), m_timeStamp( TQDateTime() ), m_entryName( TQString() )
|
|
{
|
|
|
|
}
|
|
|
|
FileLVI::FileLVI( TDEListViewItem* lvi )
|
|
: TDEListViewItem( lvi ), m_fileSize( 0 ), m_packedFileSize( 0 ),
|
|
m_ratio( 0 ), m_timeStamp( TQDateTime() ), m_entryName( TQString() )
|
|
{
|
|
}
|
|
|
|
TQString FileLVI::key( int column, bool ascending ) const
|
|
{
|
|
if ( column == 0 )
|
|
return fileName();
|
|
else
|
|
return TQListViewItem::key( column, ascending );
|
|
}
|
|
|
|
int FileLVI::compare( TQListViewItem * i, int column, bool ascending ) const
|
|
{
|
|
FileLVI * item = static_cast< FileLVI * >( i );
|
|
|
|
if ( ( this->childCount() > 0 ) && ( item->childCount() == 0 ) )
|
|
return -1;
|
|
|
|
if ( ( this->childCount() == 0 ) && ( item->childCount() > 0 ) )
|
|
return 1;
|
|
|
|
if ( column == 0 )
|
|
return TDEListViewItem::compare( i, column, ascending );
|
|
|
|
columnName colName = ( static_cast< FileListView * > ( listView() ) )->nameOfColumn( column );
|
|
switch ( colName )
|
|
{
|
|
case sizeCol:
|
|
{
|
|
return ( m_fileSize < item->fileSize() ? -1 :
|
|
( m_fileSize > item->fileSize() ? 1 : 0 )
|
|
);
|
|
break;
|
|
}
|
|
|
|
case ratioStrCol:
|
|
{
|
|
return ( m_ratio < item->ratio() ? -1 :
|
|
( m_ratio > item->ratio() ? 1 : 0 )
|
|
);
|
|
break;
|
|
}
|
|
|
|
case packedStrCol:
|
|
{
|
|
return ( m_packedFileSize < item->packedFileSize() ? -1 :
|
|
( m_packedFileSize > item->packedFileSize() ? 1 : 0 )
|
|
);
|
|
break;
|
|
}
|
|
|
|
case timeStampStrCol:
|
|
{
|
|
return ( m_timeStamp < item->timeStamp() ? -1 :
|
|
( m_timeStamp > item->timeStamp() ? 1 : 0 )
|
|
);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return TDEListViewItem::compare( i, column, ascending );
|
|
}
|
|
}
|
|
|
|
void FileLVI::setText( int column, const TQString &text )
|
|
{
|
|
columnName colName = ( static_cast< FileListView * > ( listView() ) )->nameOfColumn( column );
|
|
if ( column == 0 )
|
|
{
|
|
TQString name = text;
|
|
if ( name.endsWith( "/" ) )
|
|
name = name.left( name.length() - 1 );
|
|
if ( name.startsWith( "/" ) )
|
|
name = name.mid( 1 );
|
|
int pos = name.findRev( '/' );
|
|
if ( pos != -1 )
|
|
name = name.right( name.length() - pos - 1 );
|
|
TQListViewItem::setText( column, name );
|
|
m_entryName = text;
|
|
}
|
|
else if ( colName == sizeCol )
|
|
{
|
|
m_fileSize = text.toULongLong();
|
|
TQListViewItem::setText( column, TDEIO::convertSize( m_fileSize ) );
|
|
}
|
|
else if ( colName == packedStrCol )
|
|
{
|
|
m_packedFileSize = text.toULongLong();
|
|
TQListViewItem::setText( column, TDEIO::convertSize( m_packedFileSize ) );
|
|
}
|
|
else if ( colName == ratioStrCol )
|
|
{
|
|
int l = text.length() - 1;
|
|
if ( l>0 && text[l] == '%' )
|
|
m_ratio = text.left(l).toDouble();
|
|
else
|
|
m_ratio = text.toDouble();
|
|
TQListViewItem::setText( column, i18n( "Packed Ratio", "%1 %" )
|
|
.arg(TDEGlobal::locale()->formatNumber( m_ratio, 1 ) )
|
|
);
|
|
}
|
|
else if ( colName == timeStampStrCol )
|
|
{
|
|
if ( text.isEmpty() )
|
|
TQListViewItem::setText(column, text);
|
|
else
|
|
{
|
|
m_timeStamp = TQDateTime::fromString( text, TQt::ISODate );
|
|
TQListViewItem::setText( column, TDEGlobal::locale()->formatDateTime( m_timeStamp ) );
|
|
}
|
|
}
|
|
else
|
|
TQListViewItem::setText(column, text);
|
|
}
|
|
|
|
void FileLVI::setItemData( const TQStringList &entryData )
|
|
{
|
|
int i = 0;
|
|
|
|
for (TQStringList::ConstIterator it = entryData.begin(); it != entryData.end(); ++it)
|
|
{
|
|
this->setText(i, *it);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
static FileLVI* folderLVI( TDEListViewItem *parent, const TQString& name )
|
|
{
|
|
FileLVI *folder = new FileLVI( parent );
|
|
|
|
folder->setText( 0, name );
|
|
|
|
folder->setPixmap( 0, KMimeType::mimeType( "inode/directory" )->pixmap( TDEIcon::Small ) );
|
|
|
|
return folder;
|
|
}
|
|
|
|
static FileLVI* folderLVI( TDEListView *parent, const TQString& name )
|
|
{
|
|
FileLVI *folder = new FileLVI( parent );
|
|
folder->setText( 0, name );
|
|
folder->setPixmap( 0, KMimeType::mimeType( "inode/directory" )->pixmap( TDEIcon::Small ) );
|
|
return folder;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// FileListView implementation
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
FileListView::FileListView(TQWidget *parent, const char* name)
|
|
: TDEListView(parent, name)
|
|
{
|
|
TQWhatsThis::add( this,
|
|
i18n( "This area is for displaying information about the files contained within an archive." )
|
|
);
|
|
|
|
setMultiSelection( true );
|
|
setSelectionModeExt( FileManager );
|
|
setItemsMovable( false );
|
|
setRootIsDecorated( true );
|
|
setShowSortIndicator( true );
|
|
setItemMargin( 3 );
|
|
header()->hide(); // Don't show the header until there is something to be shown in it
|
|
|
|
m_pressed = false;
|
|
}
|
|
|
|
int FileListView::addColumn ( const TQString & label, int width )
|
|
{
|
|
int index = TDEListView::addColumn( label, width );
|
|
if ( label == SIZE_COLUMN.first )
|
|
{
|
|
m_columnMap[ index ] = sizeCol;
|
|
}
|
|
else if ( label == PACKED_COLUMN.first )
|
|
{
|
|
m_columnMap[ index ] = packedStrCol;
|
|
}
|
|
else if ( label == RATIO_COLUMN.first )
|
|
{
|
|
m_columnMap[ index ] = ratioStrCol;
|
|
}
|
|
else if ( label == TIMESTAMP_COLUMN.first )
|
|
{
|
|
m_columnMap[ index ] = timeStampStrCol;
|
|
}
|
|
else
|
|
{
|
|
m_columnMap[ index ] = otherCol;
|
|
}
|
|
return index;
|
|
}
|
|
|
|
void FileListView::removeColumn( int index )
|
|
{
|
|
for ( unsigned int i = index; i < m_columnMap.count() - 2; i++ )
|
|
{
|
|
m_columnMap.replace( i, m_columnMap[ i + 1 ] );
|
|
}
|
|
|
|
m_columnMap.remove( m_columnMap[ m_columnMap.count() - 1 ] );
|
|
TDEListView::removeColumn( index );
|
|
}
|
|
|
|
columnName FileListView::nameOfColumn( int index )
|
|
{
|
|
return m_columnMap[ index ];
|
|
}
|
|
|
|
TQStringList FileListView::selectedFilenames()
|
|
{
|
|
TQStringList files;
|
|
|
|
FileLVI *item = static_cast<FileLVI*>( firstChild() );
|
|
|
|
while ( item )
|
|
{
|
|
if ( item->isSelected() )
|
|
{
|
|
// If the item has children, add each child and the item
|
|
if ( item->childCount() > 0 )
|
|
{
|
|
files += item->fileName();
|
|
files += childrenOf( item );
|
|
|
|
/* If we got here, then the logic for "going to the next item"
|
|
* is a bit different: as we already dealt with all the children,
|
|
* the "next item" is the next sibling of the current item, not
|
|
* its first child. If the current item has no siblings, then
|
|
* the next item is the next sibling of its parent, and so on.
|
|
*/
|
|
FileLVI *nitem = static_cast<FileLVI*>( item->nextSibling() );
|
|
while ( !nitem && item->parent() )
|
|
{
|
|
item = static_cast<FileLVI*>( item->parent() );
|
|
if ( item->parent() )
|
|
nitem = static_cast<FileLVI*>( item->parent()->nextSibling() );
|
|
}
|
|
item = nitem;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// If the item has no children, just add it to the list
|
|
files += item->fileName();
|
|
}
|
|
}
|
|
// Go to the next item
|
|
item = static_cast<FileLVI*>( item->itemBelow() );
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
TQStringList FileListView::fileNames()
|
|
{
|
|
TQStringList files;
|
|
|
|
TQListViewItemIterator it( this );
|
|
while ( it.current() )
|
|
{
|
|
FileLVI *item = static_cast<FileLVI*>( it.current() );
|
|
files += item->fileName();
|
|
++it;
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
bool FileListView::isSelectionEmpty()
|
|
{
|
|
FileLVI * flvi = (FileLVI*)firstChild();
|
|
|
|
while (flvi)
|
|
{
|
|
if( flvi->isSelected() )
|
|
return false;
|
|
else
|
|
flvi = (FileLVI*)flvi->itemBelow();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void
|
|
FileListView::contentsMousePressEvent(TQMouseEvent *e)
|
|
{
|
|
if( e->button()==TQt::LeftButton )
|
|
{
|
|
m_pressed = true;
|
|
m_presspos = e->pos();
|
|
}
|
|
|
|
TDEListView::contentsMousePressEvent(e);
|
|
}
|
|
|
|
void
|
|
FileListView::contentsMouseReleaseEvent(TQMouseEvent *e)
|
|
{
|
|
m_pressed = false;
|
|
TDEListView::contentsMouseReleaseEvent(e);
|
|
}
|
|
|
|
void
|
|
FileListView::contentsMouseMoveEvent(TQMouseEvent *e)
|
|
{
|
|
if(!m_pressed)
|
|
{
|
|
TDEListView::contentsMouseMoveEvent(e);
|
|
}
|
|
else if( ( m_presspos - e->pos() ).manhattanLength() > TDEGlobalSettings::dndEventDelay() )
|
|
{
|
|
m_pressed = false; // Prevent triggering again
|
|
if(isSelectionEmpty())
|
|
{
|
|
return;
|
|
}
|
|
TQStringList dragFiles = selectedFilenames();
|
|
emit startDragRequest( dragFiles );
|
|
TDEListView::contentsMouseMoveEvent(e);
|
|
}
|
|
}
|
|
|
|
FileLVI*
|
|
FileListView::item(const TQString& filename) const
|
|
{
|
|
if (filename.isEmpty()) {
|
|
return 0;
|
|
}
|
|
|
|
TQStringList pathList = TQStringList::split( '/', filename );
|
|
|
|
FileLVI * flvi = (FileLVI*) firstChild();
|
|
|
|
// File path iterator
|
|
TQStringList::ConstIterator pathIt = pathList.begin(), pathEnd = pathList.end();
|
|
// Iterate over the current tree level siblings
|
|
while (flvi)
|
|
{
|
|
if (flvi->fileName() == *pathIt) {
|
|
++pathIt;
|
|
if (pathIt != pathEnd) {
|
|
flvi = (FileLVI*) flvi->firstChild();
|
|
} else {
|
|
return flvi;
|
|
}
|
|
}
|
|
else {
|
|
flvi = (FileLVI*) flvi->nextSibling();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
FileLVI *FileListView::addItem( const TQStringList & entries )
|
|
{
|
|
FileLVI *flvi, *parent = findParent( entries[0] );
|
|
if ( parent )
|
|
flvi = new FileLVI( parent );
|
|
else
|
|
flvi = new FileLVI( this );
|
|
|
|
flvi->setItemData (entries);
|
|
|
|
KMimeType::Ptr mimeType = KMimeType::findByPath( entries.first(), 0, true );
|
|
flvi->setPixmap( 0, mimeType->pixmap( TDEIcon::Small ) );
|
|
|
|
return flvi;
|
|
}
|
|
|
|
FileLVI *FileListView::addOrUpdateItem( const TQStringList &entries )
|
|
{
|
|
FileLVI *flvi = item ( entries[0] );
|
|
if (flvi) {
|
|
flvi->setItemData (entries);
|
|
return flvi;
|
|
} else {
|
|
return addItem (entries);
|
|
}
|
|
}
|
|
|
|
void FileListView::selectAll()
|
|
{
|
|
TQListView::selectAll( true );
|
|
}
|
|
|
|
void FileListView::unselectAll()
|
|
{
|
|
TQListView::selectAll( false );
|
|
}
|
|
|
|
void FileListView::setHeaders( const ColumnList& columns )
|
|
{
|
|
clearHeaders();
|
|
|
|
for ( ColumnList::const_iterator it = columns.constBegin();
|
|
it != columns.constEnd();
|
|
++it )
|
|
{
|
|
TQPair< TQString, TQt::AlignmentFlags > pair = *it;
|
|
int colnum = addColumn( pair.first );
|
|
setColumnAlignment( colnum, pair.second );
|
|
}
|
|
|
|
setResizeMode( TQListView::LastColumn );
|
|
|
|
header()->show();
|
|
}
|
|
|
|
void FileListView::clearHeaders()
|
|
{
|
|
header()->hide();
|
|
while ( columns() > 0 )
|
|
{
|
|
removeColumn( 0 );
|
|
}
|
|
}
|
|
|
|
int FileListView::totalFiles()
|
|
{
|
|
int numFiles = 0;
|
|
|
|
TQListViewItemIterator it( this );
|
|
while ( it.current() )
|
|
{
|
|
if ( it.current()->childCount() == 0 )
|
|
++numFiles;
|
|
++it;
|
|
}
|
|
|
|
return numFiles;
|
|
}
|
|
|
|
int FileListView::selectedFilesCount()
|
|
{
|
|
int numFiles = 0;
|
|
|
|
TQListViewItemIterator it( this, TQListViewItemIterator::Selected );
|
|
while ( it.current() )
|
|
{
|
|
++numFiles;
|
|
++it;
|
|
}
|
|
|
|
return numFiles;
|
|
}
|
|
|
|
TDEIO::filesize_t FileListView::totalSize()
|
|
{
|
|
TDEIO::filesize_t size = 0;
|
|
|
|
TQListViewItemIterator it(this);
|
|
while ( it.current() )
|
|
{
|
|
FileLVI *item = static_cast<FileLVI*>( it.current() );
|
|
size += item->fileSize();
|
|
++it;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
TDEIO::filesize_t FileListView::selectedSize()
|
|
{
|
|
TDEIO::filesize_t size = 0;
|
|
|
|
TQListViewItemIterator it( this, TQListViewItemIterator::Selected );
|
|
while ( it.current() )
|
|
{
|
|
FileLVI *item = static_cast<FileLVI*>( it.current() );
|
|
size += item->fileSize();
|
|
++it;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
FileLVI* FileListView::findParent( const TQString& fullname )
|
|
{
|
|
TQString name = fullname;
|
|
|
|
if ( name.endsWith( "/" ) )
|
|
name = name.left( name.length() -1 );
|
|
if ( name.startsWith( "/" ) )
|
|
name = name.mid( 1 );
|
|
// Checks if this entry needs a parent
|
|
if ( !name.contains( '/' ) )
|
|
return static_cast< FileLVI* >( 0 );
|
|
|
|
// Get a list of ancestors
|
|
TQString parentFullname = name.left( name.findRev( '/' ) );
|
|
TQStringList ancestorList = TQStringList::split( '/', parentFullname );
|
|
|
|
// Checks if the listview contains the first item in the list of ancestors
|
|
TQListViewItem *item = firstChild();
|
|
while ( item )
|
|
{
|
|
if ( item->text( 0 ) == ancestorList[0] )
|
|
break;
|
|
item = item->nextSibling();
|
|
}
|
|
|
|
// If the list view does not contain the item, create it
|
|
if ( !item )
|
|
{
|
|
item = folderLVI( this, ancestorList[0] );
|
|
}
|
|
|
|
// We've already dealt with the first item, remove it
|
|
ancestorList.pop_front();
|
|
|
|
while ( ancestorList.count() > 0 )
|
|
{
|
|
TQString name = ancestorList[0];
|
|
|
|
FileLVI *parent = static_cast< FileLVI*>( item );
|
|
item = parent->firstChild();
|
|
while ( item )
|
|
{
|
|
if ( item->text(0) == name )
|
|
break;
|
|
item = item->nextSibling();
|
|
}
|
|
|
|
if ( !item )
|
|
{
|
|
item = folderLVI( parent, name );
|
|
}
|
|
|
|
ancestorList.pop_front();
|
|
}
|
|
|
|
item->setOpen( true );
|
|
return static_cast< FileLVI* >( item );
|
|
}
|
|
|
|
TQStringList FileListView::childrenOf( FileLVI* parent )
|
|
{
|
|
Q_ASSERT( parent );
|
|
TQStringList children;
|
|
|
|
FileLVI *item = static_cast<FileLVI*>( parent->firstChild() );
|
|
|
|
while ( item )
|
|
{
|
|
if ( item->childCount() == 0 )
|
|
{
|
|
children += item->fileName();
|
|
}
|
|
else
|
|
{
|
|
children += item->fileName();
|
|
children += childrenOf( item );
|
|
}
|
|
item = static_cast<FileLVI*>( item->nextSibling() );
|
|
}
|
|
|
|
return children;
|
|
}
|
|
|
|
#include "filelistview.moc"
|