分享
 
 
 

A Directory Browser

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

A Directory Browser

This example program demonstrates how to use a listview and listview items to build a multi-column hierarchical, memory- and CPU-efficient directory browser. It also demonstrates how to use Drag&Drop in a listview.

Header file:

/****************************************************************************

** $Id: qt/dirview.h 3.0.5 edited Oct 12 2001 $

**

** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.

**

** This file is part of an example program for Qt. This example

** program may be used, distributed and modified without limitation.

**

*****************************************************************************/

#ifndef DIRVIEW_H

#define DIRVIEW_H

#include <qlistview.h>

#include <qstring.h>

#include <qfile.h>

#include <qfileinfo.h>

#include <qtimer.h>

class QWidget;

class QDragEnterEvent;

class QDragMoveEvent;

class QDragLeaveEvent;

class QDropEvent;

class FileItem : public QListViewItem

{

public:

FileItem( QListViewItem *parent, const QString &s1, const QString &s2 )

: QListViewItem( parent, s1, s2 ), pix( 0 ) {}

const QPixmap *pixmap( int i ) const;

void setPixmap( QPixmap *p );

private:

QPixmap *pix;

};

class Directory : public QListViewItem

{

public:

Directory( QListView * parent, const QString& filename );

Directory( Directory * parent, const QString& filename, const QString &col2 )

: QListViewItem( parent, filename, col2 ), pix( 0 ) {}

Directory( Directory * parent, const QString& filename );

QString text( int column ) const;

QString fullName();

void setOpen( bool );

void setup();

const QPixmap *pixmap( int i ) const;

void setPixmap( QPixmap *p );

private:

QFile f;

Directory * p;

bool readable;

bool showDirsOnly;

QPixmap *pix;

};

class DirectoryView : public QListView

{

Q_OBJECT

public:

DirectoryView( QWidget *parent = 0, const char *name = 0, bool sdo = FALSE );

bool showDirsOnly() { return dirsOnly; }

public slots:

void setDir( const QString & );

signals:

void folderSelected( const QString & );

protected slots:

void slotFolderSelected( QListViewItem * );

void openFolder();

protected:

void contentsDragEnterEvent( QDragEnterEvent *e );

void contentsDragMoveEvent( QDragMoveEvent *e );

void contentsDragLeaveEvent( QDragLeaveEvent *e );

void contentsDropEvent( QDropEvent *e );

void contentsMouseMoveEvent( QMouseEvent *e );

void contentsMousePressEvent( QMouseEvent *e );

void contentsMouseReleaseEvent( QMouseEvent *e );

private:

QString fullPath(QListViewItem* item);

bool dirsOnly;

QListViewItem *oldCurrent;

QListViewItem *dropItem;

QTimer* autoopen_timer;

QPoint presspos;

bool mousePressed;

};

#endif

And here is the main implementation file. Note the way the program scans subdirectories only when it has to. This allows the program to handle very large file systems efficiently. The same technique can be used in any other trees.

/****************************************************************************

** $Id: qt/dirview.cpp 3.0.5 edited Oct 12 2001 $

**

** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.

**

** This file is part of an example program for Qt. This example

** program may be used, distributed and modified without limitation.

**

*****************************************************************************/

#include "dirview.h"

#include <qdir.h>

#include <qfile.h>

#include <qfileinfo.h>

#include <qpixmap.h>

#include <qevent.h>

#include <qpoint.h>

#include <qmessagebox.h>

#include <qdragobject.h>

#include <qmime.h>

#include <qstrlist.h>

#include <qstringlist.h>

#include <qapplication.h>

#include <qheader.h>

static const char* folder_closed_xpm[]={

"16 16 9 1",

"g c #808080",

"b c #c0c000",

"e c #c0c0c0",

"# c #000000",

"c c #ffff00",

". c None",

"a c #585858",

"f c #a0a0a4",

"d c #ffffff",

"..###...........",

".#abc##.........",

".#daabc#####....",

".#ddeaabbccc#...",

".#dedeeabbbba...",

".#edeeeeaaaab#..",

".#deeeeeeefe#ba.",

".#eeeeeeefef#ba.",

".#eeeeeefeff#ba.",

".#eeeeefefff#ba.",

".##geefeffff#ba.",

"...##gefffff#ba.",

".....##fffff#ba.",

".......##fff#b##",

".........##f#b##",

"...........####."};

static const char* folder_open_xpm[]={

"16 16 11 1",

"# c #000000",

"g c #c0c0c0",

"e c #303030",

"a c #ffa858",

"b c #808080",

"d c #a0a0a4",

"f c #585858",

"c c #ffdca8",

"h c #dcdcdc",

"i c #ffffff",

". c None",

"....###.........",

"....#ab##.......",

"....#acab####...",

"###.#acccccca#..",

"#ddefaaaccccca#.",

"#bdddbaaaacccab#",

".eddddbbaaaacab#",

".#bddggdbbaaaab#",

"..edgdggggbbaab#",

"..#bgggghghdaab#",

"...ebhggghicfab#",

"....#edhhiiidab#",

"......#egiiicfb#",

"........#egiibb#",

"..........#egib#",

"............#ee#"};

static const char * folder_locked[]={

"16 16 10 1",

"h c #808080",

"b c #ffa858",

"f c #c0c0c0",

"e c #c05800",

"# c #000000",

"c c #ffdca8",

". c None",

"a c #585858",

"g c #a0a0a4",

"d c #ffffff",

"..#a#...........",

".#abc####.......",

".#daa#eee#......",

".#ddf#e##b#.....",

".#dfd#e#bcb##...",

".#fdccc#daaab#..",

".#dfbbbccgfg#ba.",

".#ffb#ebbfgg#ba.",

".#ffbbe#bggg#ba.",

".#fffbbebggg#ba.",

".##hf#ebbggg#ba.",

"...###e#gggg#ba.",

".....#e#gggg#ba.",

"......###ggg#b##",

".........##g#b##",

"...........####."};

static const char * pix_file []={

"16 16 7 1",

"# c #000000",

"b c #ffffff",

"e c #000000",

"d c #404000",

"c c #c0c000",

"a c #ffffc0",

". c None",

"................",

".........#......",

"......#.#a##....",

".....#b#bbba##..",

"....#b#bbbabbb#.",

"...#b#bba##bb#..",

"..#b#abb#bb##...",

".#a#aab#bbbab##.",

"#a#aaa#bcbbbbbb#",

"#ccdc#bcbbcbbb#.",

".##c#bcbbcabb#..",

"...#acbacbbbe...",

"..#aaaacaba#....",

"...##aaaaa#.....",

".....##aa#......",

".......##......."};

QPixmap *folderLocked = 0;

QPixmap *folderClosed = 0;

QPixmap *folderOpen = 0;

QPixmap *fileNormal = 0;

/*****************************************************************************

*

* Class Directory

*

*****************************************************************************/

Directory::Directory( Directory * parent, const QString& filename )

: QListViewItem( parent ), f(filename),

showDirsOnly( parent->showDirsOnly ),

pix( 0 )

{

p = parent;

readable = QDir( fullName() ).isReadable();

if ( !readable )

setPixmap( folderLocked );

else

setPixmap( folderClosed );

}

Directory::Directory( QListView * parent, const QString& filename )

: QListViewItem( parent ), f(filename),

showDirsOnly( ( (DirectoryView*)parent )->showDirsOnly() ),

pix( 0 )

{

p = 0;

readable = QDir( fullName() ).isReadable();

}

void Directory::setPixmap( QPixmap *px )

{

pix = px;

setup();

widthChanged( 0 );

invalidateHeight();

repaint();

}

const QPixmap *Directory::pixmap( int i ) const

{

if ( i )

return 0;

return pix;

}

void Directory::setOpen( bool o )

{

if ( o )

setPixmap( folderOpen );

else

setPixmap( folderClosed );

if ( o && !childCount() ) {

QString s( fullName() );

QDir thisDir( s );

if ( !thisDir.isReadable() ) {

readable = FALSE;

setExpandable( FALSE );

return;

}

listView()->setUpdatesEnabled( FALSE );

const QFileInfoList * files = thisDir.entryInfoList();

if ( files ) {

QFileInfoListIterator it( *files );

QFileInfo * fi;

while( (fi=it.current()) != 0 ) {

++it;

if ( fi->fileName() == "." || fi->fileName() == ".." )

; // nothing

else if ( fi->isSymLink() && !showDirsOnly ) {

FileItem *item = new FileItem( this, fi->fileName(),

"Symbolic Link" );

item->setPixmap( fileNormal );

}

else if ( fi->isDir() )

(void)new Directory( this, fi->fileName() );

else if ( !showDirsOnly ) {

FileItem *item

= new FileItem( this, fi->fileName(),

fi->isFile()?"File":"Special" );

item->setPixmap( fileNormal );

}

}

}

listView()->setUpdatesEnabled( TRUE );

}

QListViewItem::setOpen( o );

}

void Directory::setup()

{

setExpandable( TRUE );

QListViewItem::setup();

}

QString Directory::fullName()

{

QString s;

if ( p ) {

s = p->fullName();

s.append( f.name() );

s.append( "/" );

} else {

s = f.name();

}

return s;

}

QString Directory::text( int column ) const

{

if ( column == 0 )

return f.name();

else if ( readable )

return "Directory";

else

return "Unreadable Directory";

}

/*****************************************************************************

*

* Class DirectoryView

*

*****************************************************************************/

DirectoryView::DirectoryView( QWidget *parent, const char *name, bool sdo )

: QListView( parent, name ), dirsOnly( sdo ), oldCurrent( 0 ),

dropItem( 0 ), mousePressed( FALSE )

{

autoopen_timer = new QTimer( this );

if ( !folderLocked ) {

folderLocked = new QPixmap( folder_locked );

folderClosed = new QPixmap( folder_closed_xpm );

folderOpen = new QPixmap( folder_open_xpm );

fileNormal = new QPixmap( pix_file );

}

connect( this, SIGNAL( doubleClicked( QListViewItem * ) ),

this, SLOT( slotFolderSelected( QListViewItem * ) ) );

connect( this, SIGNAL( returnPressed( QListViewItem * ) ),

this, SLOT( slotFolderSelected( QListViewItem * ) ) );

setAcceptDrops( TRUE );

viewport()->setAcceptDrops( TRUE );

connect( autoopen_timer, SIGNAL( timeout() ),

this, SLOT( openFolder() ) );

}

void DirectoryView::slotFolderSelected( QListViewItem *i )

{

if ( !i || !showDirsOnly() )

return;

Directory *dir = (Directory*)i;

emit folderSelected( dir->fullName() );

}

void DirectoryView::openFolder()

{

autoopen_timer->stop();

if ( dropItem && !dropItem->isOpen() ) {

dropItem->setOpen( TRUE );

dropItem->repaint();

}

}

static const int autoopenTime = 750;

void DirectoryView::contentsDragEnterEvent( QDragEnterEvent *e )

{

if ( !QUriDrag::canDecode(e) ) {

e->ignore();

return;

}

oldCurrent = currentItem();

QListViewItem *i = itemAt( contentsToViewport(e->pos()) );

if ( i ) {

dropItem = i;

autoopen_timer->start( autoopenTime );

}

}

void DirectoryView::contentsDragMoveEvent( QDragMoveEvent *e )

{

if ( !QUriDrag::canDecode(e) ) {

e->ignore();

return;

}

QPoint vp = contentsToViewport( ( (QDragMoveEvent*)e )->pos() );

QListViewItem *i = itemAt( vp );

if ( i ) {

setSelected( i, TRUE );

e->accept();

if ( i != dropItem ) {

autoopen_timer->stop();

dropItem = i;

autoopen_timer->start( autoopenTime );

}

switch ( e->action() ) {

case QDropEvent::Copy:

break;

case QDropEvent::Move:

e->acceptAction();

break;

case QDropEvent::Link:

e->acceptAction();

break;

default:

;

}

} else {

e->ignore();

autoopen_timer->stop();

dropItem = 0;

}

}

void DirectoryView::contentsDragLeaveEvent( QDragLeaveEvent * )

{

autoopen_timer->stop();

dropItem = 0;

setCurrentItem( oldCurrent );

setSelected( oldCurrent, TRUE );

}

void DirectoryView::contentsDropEvent( QDropEvent *e )

{

autoopen_timer->stop();

if ( !QUriDrag::canDecode(e) ) {

e->ignore();

return;

}

QListViewItem *item = itemAt( contentsToViewport(e->pos()) );

if ( item ) {

QStrList lst;

QUriDrag::decode( e, lst );

QString str;

switch ( e->action() ) {

case QDropEvent::Copy:

str = "Copy";

break;

case QDropEvent::Move:

str = "Move";

e->acceptAction();

break;

case QDropEvent::Link:

str = "Link";

e->acceptAction();

break;

default:

str = "Unknown";

}

str += "\n\n";

e->accept();

for ( uint i = 0; i < lst.count(); ++i ) {

QString filename = lst.at( i );

str += filename + "\n";

}

str += QString( "\nTo\n\n %1" )

.arg( fullPath(item) );

QMessageBox::information( this, "Drop target", str, "Not implemented" );

} else

e->ignore();

}

QString DirectoryView::fullPath(QListViewItem* item)

{

QString fullpath = item->text(0);

while ( (item=item->parent()) ) {

if ( item->parent() )

fullpath = item->text(0) + "/" + fullpath;

else

fullpath = item->text(0) + fullpath;

}

return fullpath;

}

void DirectoryView::contentsMousePressEvent( QMouseEvent* e )

{

QListView::contentsMousePressEvent(e);

QPoint p( contentsToViewport( e->pos() ) );

QListViewItem *i = itemAt( p );

if ( i ) {

// if the user clicked into the root decoration of the item, don't try to start a drag!

if ( p.x() > header()->cellPos( header()->mapToActual( 0 ) ) +

treeStepSize() * ( i->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ||

p.x() < header()->cellPos( header()->mapToActual( 0 ) ) ) {

presspos = e->pos();

mousePressed = TRUE;

}

}

}

void DirectoryView::contentsMouseMoveEvent( QMouseEvent* e )

{

if ( mousePressed && ( presspos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) {

mousePressed = FALSE;

QListViewItem *item = itemAt( contentsToViewport(presspos) );

if ( item ) {

QString source = fullPath(item);

if ( QFile::exists(source) ) {

QUriDrag* ud = new QUriDrag(viewport());

ud->setUnicodeUris( source );

if ( ud->drag() )

QMessageBox::information( this, "Drag source",

QString("Delete ")+source, "Not implemented" );

}

}

}

}

void DirectoryView::contentsMouseReleaseEvent( QMouseEvent * )

{

mousePressed = FALSE;

}

void DirectoryView::setDir( const QString &s )

{

QListViewItemIterator it( this );

++it;

for ( ; it.current(); ++it ) {

it.current()->setOpen( FALSE );

}

QStringList lst( QStringList::split( "/", s ) );

QListViewItem *item = firstChild();

QStringList::Iterator it2 = lst.begin();

for ( ; it2 != lst.end(); ++it2 ) {

while ( item ) {

if ( item->text( 0 ) == *it2 ) {

item->setOpen( TRUE );

break;

}

item = item->itemBelow();

}

}

if ( item )

setCurrentItem( item );

}

void FileItem::setPixmap( QPixmap *p )

{

pix = p;

setup();

widthChanged( 0 );

invalidateHeight();

repaint();

}

const QPixmap *FileItem::pixmap( int i ) const

{

if ( i )

return 0;

return pix;

}

Main:

/****************************************************************************

** $Id: qt/main.cpp 3.0.5 edited Oct 12 2001 $

**

** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.

**

** This file is part of an example program for Qt. This example

** program may be used, distributed and modified without limitation.

**

*****************************************************************************/

#include <qapplication.h>

#include <qfileinfo.h>

#include <qdir.h>

#include "dirview.h"

int main( int argc, char ** argv )

{

QApplication a( argc, argv );

DirectoryView mw;

mw.addColumn( "Name" );

mw.addColumn( "Type" );

mw.setTreeStepSize( 20 );

const QFileInfoList* roots = QDir::drives();

QPtrListIterator<QFileInfo> i(*roots);

QFileInfo* fi;

while ( (fi = *i) ) {

++i;

Directory * root = new Directory( &mw, fi->filePath() );

if ( roots->count() <= 1 )

root->setOpen( TRUE ); // be interesting

}

mw.resize( 400, 400 );

mw.setCaption( "Qt Example - Directory Browser" );

mw.setAllColumnsShowFocus( TRUE );

a.setMainWidget( &mw );

mw.show();

return a.exec();

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有