文章目录
效果图 现实的功能 总体框架 功能介绍 视图 双击进入处理 复制与剪切 粘贴 重命名,新建 显示文件详细信息 文件路径导航栏
总结
效果图
现实的功能
支持文件/文件夹复制,粘贴,剪切,删除,重命名的基本操作 支持打开图片,文档等资源 支持文件显示详细信息 支持文件路径导航
总体框架
本案例主要使用了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需要处理,有些功能可加入,待完善。 知识理应共享,源码在此(持续优化 )。