文章目录 效果图 现实的功能 总体框架 功能介绍 视图 双击进入处理 复制与剪切 粘贴 重命名,新建 显示文件详细信息 文件路径导航栏 总结
效果图
现实的功能
支持文件/文件夹复制,粘贴,剪切,删除,重命名的基本操作 支持打开图片,文档等资源 支持文件显示详细信息 支持文件路径导航
总体框架
本案例主要使用了QFileSystemModel
与QListView
。上方的路径导航栏使用了QListWidget
,每一个路径名为一个item
。关键在于你对QFileSystemModel
的使用。
功能介绍
视图
创建QFileSystemModel
模型与QListView
视图,并设置相关参数,就可以显示本地的文件目录。关键在于要设置setViewMode
函数。
model = new QFileSystemModel ( this ) ;
model-> setRootPath ( QDir :: homePath ( ) ) ;
listView = new FileListView ( this ) ;
listView-> setModel ( model) ;
listView-> setRootIndex ( model-> index ( QDir :: homePath ( ) ) ) ;
listView-> setDragEnabled ( false ) ;
listView-> setMovement ( QListView:: Static) ;
listView-> setViewMode ( QListView:: IconMode) ;
listView-> setResizeMode ( QListView:: Adjust) ;
listView-> setSpacing ( 20 ) ;
listView-> setIconSize ( QSize ( 48 , 48 ) ) ;
listView-> setGridSize ( QSize ( 80 , 80 ) ) ;
listView-> installEventFilter ( this ) ;
双击进入处理
在进入下一级的时候,要判断是文件还是文件夹,文件夹则进入,文件则调用系统默认的软件打开。
void FileExplorer :: onDoubleClicked ( const QModelIndex & index)
{ if ( model-> isDir ( index) ) { listView-> setRootIndex ( index) ; updatePath ( index) ; } else { QString filePath = model-> filePath ( index) ; QDesktopServices :: openUrl ( QUrl :: fromLocalFile ( filePath) ) ; }
}
复制与剪切
复制与剪切的逻辑相似,需要维护一个保存要操作文件的路径,和判断是否为剪切的标志位。剪切就是使用复制,粘贴成功后删除原有的文件。
void FileExplorer :: copyFileOrFolder ( )
{ cutOperation = false ; QModelIndexList indexes = listView-> selectionModel ( ) -> selectedIndexes ( ) ; listOfFilesToCopy. clear ( ) ; for ( QModelIndex index : indexes) { QString filePath = model-> filePath ( index) ; listOfFilesToCopy. append ( filePath) ; } listView-> clearSelection ( ) ;
}
粘贴
我们从复制/剪切下得到了需操作文件的路径,就可以使用copy
函数实现粘贴,需要注意的是,要复制目录内容,需要递归地复制所有文件和子目录,若路径不存在则创建不存在的文件,不然无法复制粘贴成功,若是剪切,粘贴完后要删除原文件,并清空链表。
重命名,新建
显示文件详细信息
这个需要利用到事件过滤器,当判断到事件为 QEvent::ToolTip
时,使用QToolTip
显示得到的文件信息。
bool FileExplorer :: eventFilter ( QObject * watched, QEvent * event)
{ if ( watched == listView && event-> type ( ) == QEvent:: ToolTip) { QHelpEvent * helpEvent = static_cast < QHelpEvent * > ( event) ; if ( helpEvent) { QModelIndex index = listView-> indexAt ( helpEvent-> pos ( ) ) ; if ( index. isValid ( ) ) { QString toolTipText; QLocale locale; QString filePath = model-> filePath ( index) ; QFileInfo fileInfo ( filePath) ; QString longDate = locale. toString ( fileInfo. lastModified ( ) , QLocale:: LongFormat) ; toolTipText = QString ( "Name: %1\nSize: %2KB\nType: %3\nLast Modified: %4" ) . arg ( fileInfo. fileName ( ) ) . arg ( ! fileInfo. isFile ( ) ? calculateFolderSize ( filePath) : fileInfo. size ( ) / 1024 ) . arg ( ! fileInfo. isFile ( ) ? "file" : fileInfo. suffix ( ) ) . arg ( longDate) ; QToolTip :: showText ( helpEvent-> globalPos ( ) , toolTipText) ; } else { QToolTip :: hideText ( ) ; event-> ignore ( ) ; } return true ; } } return QWidget :: eventFilter ( watched, event) ;
}
文件路径导航栏
主要思想就是使用QListWidget
,每当路径变化时,就使用文件名重新生成item
,点击其中一个文件名时,就会拼接成正确的路径名从而实现跳转。
void FileListWidget :: refresh ( const QString & dir)
{ this -> clear ( ) ; auto initlist = dir. split ( "/" ) ; for ( auto & str : initlist) { QListWidgetItem * item = new QListWidgetItem ( str, this ) ; item-> setFlags ( item-> flags ( ) | Qt:: ItemIsUserCheckable) ; addItem ( ">" ) ; addItem ( item) ; }
} void FileExplorer :: onitemClicked ( QListWidgetItem * item)
{ if ( ! item) return ; auto row = fileList-> row ( item) + 1 ; QString strdir; for ( int i = 0 ; i < row; ++ i) { QListWidgetItem * itemc = fileList-> item ( i) ; if ( itemc-> text ( ) != ">" ) { strdir. push_back ( QString ( itemc-> text ( ) + "/" ) ) ; } } strdir. chop ( 1 ) ; if ( ! strdir. isEmpty ( ) ) { fileList-> refresh ( strdir) ; model-> setRootPath ( strdir) ; listView-> setRootIndex ( model-> index ( strdir) ) ; }
}
总结
文件操作的功能基本实现,但还是存在一些BUG需要处理,有些功能可加入,待完善。 知识理应共享,源码在此(持续优化 )。