文件系统可视化与文件管理
经过一段时间的学习,终于完成了文件系统的一个可视化与文件管理,简单记录一下整个程序的想法。
主要分为以下几个模块:
1.界面搭建
2.目录树可视化
此处通过QDir读取文件夹,然后通过QStandardItem创建目录树条目,在QTreeView中呈现。源码如下:
void Widget::loadLogFiles(const QString path, QStandardItemModel *model){model->removeRows(0, model->rowCount());QDir d(path);d.setFilter(QDir::Files | QDir::Hidden |QDir::NoSymLinks | QDir::AllDirs|QDir::NoDotAndDotDot);const QFileInfoList list = d.entryInfoList();int i=0;while(i<list.count()){QStyle *style = QApplication::style();QString fileType;QFileInfo file = list[i];LogStandardItem *dir = new LogStandardItem(file.fileName());dir->setCheckable(true);dir->setToolTip(file.path()+"/"+file.fileName());if(file.isDir()){dir->setIcon(style->standardIcon(QStyle::SP_DirIcon));fileType = "日志文件夹";}else{dir->setIcon(style->standardIcon(QStyle::SP_FileIcon));fileType = file.suffix();}QString sizeItem = QString::number(file.size());int rowItem = model->indexFromItem(dir).row();QString timeItem = QDateTime(file.lastModified()).toString("yyyy-MM-dd hh:mm:ss");model->appendRow(dir);model->setItem(rowItem, 1, new LogStandardItem(sizeItem));model->setItem(rowItem, 3, new LogStandardItem(timeItem));model->setItem(rowItem, 2, new LogStandardItem(fileType));if(file.isDir()) loadLogFiles(file.path()+"/"+file.fileName(), dir);i++;}
}void Widget::loadLogFiles(const QString path, QStandardItem *model){QDir d(path);d.setFilter(QDir::Files | QDir::Hidden |QDir::NoSymLinks | QDir::AllDirs|QDir::NoDotAndDotDot);const QFileInfoList list = d.entryInfoList();int i=0;while(i<list.count()){QStyle *style = QApplication::style();QString fileType;QFileInfo file = list[i];LogStandardItem *dir = new LogStandardItem(file.fileName());dir->setCheckable(true);dir->setToolTip(file.path()+"/"+file.fileName());if(file.isDir()){dir->setIcon(style->standardIcon(QStyle::SP_DirIcon));fileType = "日志文件夹";}else{dir->setIcon(style->standardIcon(QStyle::SP_FileIcon));fileType = file.suffix();}QString sizeItem = QString::number(file.size());QString timeItem = QDateTime(file.lastModified()).toString("yyyy-MM-dd hh:mm:ss");model->appendRow(dir);int rowItem = dir->index().row();model->setChild(rowItem, 1, new LogStandardItem(sizeItem));model->setChild(rowItem, 3, new LogStandardItem(timeItem));model->setChild(rowItem, 2, new LogStandardItem(fileType));if(file.isDir()) loadLogFiles(dir->toolTip(), dir);i++;}
}
3.复选框三态的实现
由于设置复选框是针对每一个条目QStandardItem的,其本身是没有半选状态的,所以我们要重新实现QStandardItem的三态,从而让其具有父子之间的联系。我们创建一个继承QStandardItem类的子类,重写其setData函数,代码如下:
void LogStandardItem::setData(const QVariant &value, int role){if(role == Qt::CheckStateRole){Qt::CheckState CheckState = (Qt::CheckState) value.toInt();switch(CheckState){case Qt::Unchecked:{for(int i=0; i<rowCount(); i++){child(i)->setData(Qt::Unchecked, Qt::CheckStateRole);}QStandardItem::setData(value, role);if(parent()) parent()->setData(Qt::PartiallyChecked, role);}return;case Qt::PartiallyChecked:{Qt::CheckState current_state = checkState();int CheckedNum = 0;int UnCheckedNum = 0;bool isPartially = false;Qt::CheckState ChildState;int m_rowCount = rowCount();for(int i=0; i<m_rowCount; i++){ChildState = child(i)->checkState();switch(ChildState){case Qt::PartiallyChecked: isPartially = true;break;case Qt::Unchecked: UnCheckedNum++;break;case Qt::Checked: CheckedNum++; break;default: CheckedNum++;break;}}Qt::CheckState NowState;if(isPartially) NowState = Qt::PartiallyChecked;else if(UnCheckedNum == m_rowCount) NowState = Qt::Unchecked;else if(CheckedNum == m_rowCount) NowState = Qt::Checked;else NowState = Qt::PartiallyChecked;if(current_state != NowState){QStandardItem::setData(NowState, role);if(parent()) parent()->setData(Qt::PartiallyChecked, role);}}return;case Qt::Checked:{for(int i=0, num = rowCount(); i<num; i++){child(i)->setData(Qt::Checked, Qt::CheckStateRole);}QStandardItem::setData(value, role);if(parent()) parent()->setData(Qt::PartiallyChecked, role);}return;default:break;}}QStandardItem::setData(value, role);
}
实现了复选框的三态,其实就可以实现删除选中的文件或者文件夹的功能了。
4.双击显示日志内容
对于此功能,我们采用子线程去读取日志内容,然后将读取的内容显示于控件当中。首先我们创建关于此功能的信号与槽:
connect(m_pLogTree, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(loadLogContent(QModelIndex)));
然后将所点击的目录对应的路径传输于子线程,设置信号与槽,在子线程读取完成以后主线程将内容显示。槽函数如下:
void Widget::loadLogContent(const QModelIndex &index){QStandardItem *item = m_pLogTreeModel->itemFromIndex(index);QFileInfo f(item->toolTip());if(f.isFile()){connect(&m_tShowLogContentThread, SIGNAL(readOverSignal()),this, SLOT(displayContent()));m_pContentDisplayWid->setToolTip(item->toolTip());m_tShowLogContentThread.m_sPath = item->toolTip();m_tShowLogContentThread.start();m_tShowLogContentThread.wait();m_pStatusBar->setText("正在浏览日志:"+f.fileName());}
}
在子线程中读取:
void ReadLogThread::run(){mutex.lock();QFile file(m_sPath);QTextStream contentRead(&file);QString content;m_lLogContent.clear();while(!contentRead.atEnd()){content = contentRead.readLine();m_lLogContent.append(content);}emit readOverSignal();mutex.unlock();
}
通过信号readOverSignal激活主线程槽函数displayContent,通过其来将内容显示于QListWidget中:
void Widget::displayContent(){QStringList disContent = m_tShowLogContentThread.m_lLogContent;// 如果日志数大于0,展示第一页,如果日志数=0, 依然显示0if(disContent.length() == 0) FlushContentPage(0);else FlushContentPage(1);
}void Widget::FlushContentPage(int page){m_nContentPage = page;while(m_pContentDisplayWid->count()>0){QListWidgetItem *item = m_pContentDisplayWid->takeItem(0);delete item;}if(m_nContentPage>0){QStringList disContent = m_tShowLogContentThread.m_lLogContent;for(int i=(m_nContentPage-1)*19; i<m_nContentPage*19 &&i<m_tShowLogContentThread.m_lLogContent.length(); i++){QListWidgetItem *Item = new QListWidgetItem(m_pContentDisplayWid);Item->setSizeHint(QSize(0, 20));Item->setText(qPrintable(m_tShowLogContentThread.m_lLogContent[i]));m_pContentDisplayWid->addItem(Item);}}QString pageInformation = QString::number(m_nContentPage) + "/" +QString::number(qCeil(m_tShowLogContentThread.m_lLogContent.length()*1.0/19*1.0));m_pShowPg->setText(pageInformation);
}
5.为QListWidget增加翻页功能
先创建控件,通过QSignalMapper 将多个按钮统一到一块,点击不同的按钮,QSignalMapper则会得到不同的索引值,从而根据索引值,来判断索要进行的操作。
QSignalMapper *btMapper = new QSignalMapper;
connect(m_pDelPgsBtn, SIGNAL(clicked(bool)), btMapper, SLOT(map()));
connect(m_pDelPgBtn, SIGNAL(clicked(bool)), btMapper, SLOT(map()));
connect(m_pAddPgBtn, SIGNAL(clicked(bool)), btMapper, SLOT(map()));
connect(m_pAddPgsBtn, SIGNAL(clicked(bool)), btMapper, SLOT(map()));
btMapper->setMapping(m_pDelPgsBtn, 0);
btMapper->setMapping(m_pDelPgBtn, 1);
btMapper->setMapping(m_pAddPgBtn, 2);
btMapper->setMapping(m_pAddPgsBtn, 3);
connect(btMapper, SIGNAL(mapped(int)), this, SLOT(TurnPage(int)));
然后创建对应的槽函数,以实现翻页功能:
void Widget::TurnPage(const int index){int page = m_nContentPage;switch (index) {case 0: //向前翻十页if(page >10) FlushContentPage(page-10);else if(page > 0) FlushContentPage(1);else FlushContentPage(0);break;case 1: // 向前翻一页if(page >1) FlushContentPage(page-1);else if(page == 0) FlushContentPage(0);break;case 2: // 向后翻一页if(page < qCeil(m_tShowLogContentThread.m_lLogContent.length() * 1.0/19 * 1.0) && page != 0)FlushContentPage(page+1);else if(page == 0) FlushContentPage(0);break;case 3: // 向后翻十页if(page <= qCeil(m_tShowLogContentThread.m_lLogContent.length() * 1.0 / 19 * 1.0) - 10 && page != 0) FlushContentPage(page+10);else if(page != 0){page = qCeil(m_tShowLogContentThread.m_lLogContent.length()*1.0/19*1.0);FlushContentPage(page);}else FlushContentPage(0);break;}
}
6.检测文件夹
如果文件夹中有新的文件,则展示于程序中,如果程序中某些对应的文件夹删除,则将其一并删除:同样此功能采用子线程来实现,子线程我们设置为2秒钟扫描一次文件夹:
void Widget::checkFileAndTree(){QTimer *tim = new QTimer();tim->start(2000);connect(tim, SIGNAL(timeout()), this, SLOT(checkFileAndTreeOnce()));
}void Widget::checkFileAndTreeOnce(){m_tUpdateTreeThread.start();m_tUpdateTreeThread.wait();
}
检测函数放于子线程中,此处呈现部分代码,其他的无非QStandardItemModel换成QStandardItem及之前的添加函数:
void UpdateTreeThread::run(){mutex.lock();checkFileInTree(m_sPath, m_tModel);checkTreeInFile(m_tModel);mutex.unlock();
}void UpdateTreeThread::checkFileInTree(QString path, QStandardItemModel *model){QDir d(path);d.setFilter(QDir::Files | QDir::Hidden |QDir::NoSymLinks | QDir::AllDirs|QDir::NoDotAndDotDot);const QFileInfoList list = d.entryInfoList();if(!list.length()) model->removeRows(0, model->rowCount());else if(!model->rowCount()) addLists(path, model);else{int i=0;while(i<list.length()){QFileInfo file = list[i];QString filePath = file.path()+"/"+file.fileName();bool fileExist = false;int j=0;while(j<model->rowCount()){if(filePath == model->item(j)->toolTip()){if(!fileExist){fileExist = true;if(file.isDir()) checkFileInTree(filePath, model->item(j));j++;}else model->removeRow(model->item(j)->row());}else j++;}if(!fileExist){QStyle *style = QApplication::style();QString fileType;LogStandardItem *item = new LogStandardItem(file.fileName());item->setCheckable(true);item->setToolTip(file.path()+"/"+file.fileName());if(file.isDir()){item->setIcon(style->standardIcon(QStyle::SP_DirIcon));fileType = "日志文件夹";}else{item->setIcon(style->standardIcon(QStyle::SP_FileIcon));fileType = file.suffix();}QString sizeItem = QString::number(file.size());QString timeItem = QDateTime(file.lastModified()).toString("yyyy-MM-dd hh:mm:ss");model->appendRow(item);int rowItem = item->index().row();model->setItem(rowItem, 1, new LogStandardItem(sizeItem));model->setItem(rowItem, 3, new LogStandardItem(timeItem));model->setItem(rowItem, 2, new LogStandardItem(fileType));if(file.isDir()) addLists(item->toolTip(), item);}i++;}}
}void UpdateTreeThread::checkTreeInFile(QStandardItemModel *model){if(model->rowCount() == 0)return;int i=0;while(i<model->rowCount()){QString path = model->item(i)->toolTip();QFileInfo file(path);if(!file.exists()) model->removeRow(model->item(i)->row());else{if(file.isDir()) checkTreeInFile(model->item(i));i++;}}
}
最终就可以实现上述文件呈现及对应的操作的功能。
这段程序也有不足的地方,记录一下,以供以后努力:
1.代码模块化能力较弱
2.对于线程的使用水平太低
3.对于程序运行的成本考虑太少,严重浪费计算资源
文件系统可视化与文件管理相关推荐
- linux根-文件系统-目录管理-文件管理-用户及权限详解-用户组-用户管理-权限管理...
一 .Linux文件结构 文件结构是文件存放在磁盘等存贮设备上的组织方法.主要体现在对文件和目录的组织上. 目录提供了管理文件的一个方便而有效的途径. Linux使用标准的目录结构,在安装的时候,安装 ...
- 操作系统 - 文件管理实验(文件系统)
用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程,从而对各种文件操作命令的实质内容和执行过程有比较深入的了解. 要求设计一个 n 个用户的文件系统,每次用户可保存 m 个文件,用户在一次 ...
- 基于android的资源文件管理器
软 件 学 院 毕业实训报告 课题名称: android资源管理器 专 业: 软件设计(游戏开发方向) 班 级: 学 号: 学生姓名: 指导教师: 年 月 日 摘 要 相信大家对Android的发展历 ...
- 根文件系统(rootfs)理解
说明 最近学习了使用qemu搭建ARM vexpress环境,对rootfs有了一些大致理解并且对rootfs的构建做了些测试验证,特记录下. 简介 文件系统有两种意思: 文件管理系统,例如:ext2 ...
- linux管理控制面板--可视化管理linux
市面上主要的网站主机分为三大类,具体差异简单说明: [虚拟主机]:也是大家口中说的"主机空间",可定制化低,适合纯小白和新手,完全不懂技术.说明白点,就是一台云服务器分割空间和内存 ...
- 操作系统文件管理实验
1. 实验目的 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程,从而对各种文件操作命令的实质内容和执行过程有比较深入的了解. 2. 实验内容与要求 要求设计一个 n个用户的文件系统,每 ...
- Linux系统结构和文件管理
Linux系统的哲学之一就是一切皆文件.文件系统FHS和文件管理在Linux系统中占用很重要的地位. 1.linux系统结构 linux是一个倒树结构,linux中所有的东西都是文件. 这些文件都在系 ...
- 操作系统原理模拟实验(基于C/C++模拟处理机调度、存储管理和文件系统)
目录 引言 一.处理机调度模拟 1.下载链接 2.目的与要求 3.截图示例 二.存储管理模拟 动态分区分配 1.下载链接 2.目的与要求 3.截图示例 分页存储地址转换 1.下载链接 2.目的与要求 ...
- kde 桌面显示管理器_KDE文件管理器Dolphin的综合指南
kde 桌面显示管理器 自Fedora 10以来, Dolphin一直是KDE桌面的默认文件管理器.使用KDE作为桌面选项的其他发行版也将其用作默认文件管理器. 它非常强大,并提供了一些非常高级的功能 ...
最新文章
- 卫星发现一个重要信号:路上货车跑起来
- Java 虚拟机总结给面试的你(下)
- stm32非操作系统开发和带uCos的开发的区别,及一些解析
- 记录 grafana登录 从 go 迁移到 php
- java servlet 3_java – Servlet 2.5和3之间有什么区别?
- python rarfile不支持unicode_python – zipfile提取时的unicode错误
- hiho一下 第六十四周	Right-click Context Menu
- .so动态链接库文件
- 印染面料产品出现纬斜疵病,应该怎么防止?
- unity如何重新生成解决方案_揭秘Sherman:使用Unity制作影视级光照效果
- 第十一届蓝桥杯物联网设计与开发实验(合集)STM32学习
- android iCloud 短信,云助手 基于安卓的iCloud
- 计算机服务器组装,一台家用虚拟化测试服务器组装
- 第三章 代码的坏味道
- C++编程-牛客网-雀魂启动
- 统计学习方法chapter1
- win10计算机 需要新应用,手把手为你win10系统商店出现“需要新应用打开此ms-windows-store”的还原步骤...
- 苹果电脑虚拟键盘怎么打开
- iOS音乐播放器小技巧
- Java调用ffmepg+mencoder视频格式转换
热门文章
- BeanPostProcessor妙用(转载)
- 计算机操做系统(十二):进程同步和互斥
- oracle修改数据库用户名密码,怎样修改oracle数据库的用户名密码
- 连接到另外计算机要用户名,连接局域网电脑需要用户名密码
- 关于华为,一次不做评价的陈述
- 135编辑器html点击图片播放音乐,135微信编辑器怎样添加音乐 135编辑器添加音乐图文教程...
- 新技术加速隐私暴露,如何应对?
- 计算机专业买哪一款华硕电脑好,华硕电脑哪款好
- 天大计算机辅助设计与制造考题,2017年CAD工程师认证考题答案及解析
- mysql安装所需最低配置数据_MySQL的安装与基本配置