使用QDirModel替换目录名称中的中文数字

使用QDirModel替换目录名称中的中文数字

一、 需求

经常会有一些教程,其目录名是用中文显示的,比如:“第一讲”、“第二讲”、"第三讲"之类的,这时目录排序的时候以汉字的编码进行排序,如下所示:

E:.
├─第一讲
├─第三讲
└─第二讲

这种顺序是难以理解的,于是想到把这种中文数字替换成阿拉伯数字:“一二三四五六七八九十” --> “1234567890”。

   E:.
   ├─第01讲
   ├─第02讲
   └─第03讲

上面这种顺序就很直观,看着赏心悦目一点。

二、核心算法–替换中文数字

算法倒是简单,简单的查找替换,并依次生成一个整数即可。

QString chineseNumber = "一二三四五六七八九十";
  • 获取一个字符串 txt = “第一十二讲”
    • 迭代每一个字符 charTmp = txt.at(i)
    • 在chineseNumber中查找charTmp,获取 index = QString::indexOf(charTmp )
    • 记录起始索引 start = index
  • “一十二” ,这是常规的替换
    • 查找到 “一” : num += index(‘一’) + 1, len += 1;
    • 查找到 “十” : num *= 10, len += 1;
    • 查找到 “二” : num += index(‘二’) + 1, len += 1;
  • “十二” ,但是在中文里面 ‘十’ 可以单独放在前面的,所以需要在上面的算法中加判断
    • 查找到 “十” :如果len==0,那么num += index(‘十’) +1,否则的话 num *= 10, len += 1;
    • 查找到 “二” : num += index(‘二’) + 1, len += 1;
  • 替换字符串操作: QString &QString::replace(int start, int len, const QString &after)方法

具体实现

    int len = 0;
    int num = 0;
    int start = 0;
    for (int i = 0; i < txt.length (); ++i) {
        auto index = chineseNumber.indexOf (txt.at (i),i);
        // 找到第一个中文数字
        if(index != -1){
            if(len==0)
                start = i;
            if(index>=9 && len != 0){
                num *=10;
            } else{
                num += index+1;
            }
            len += 1;
        }
    }
    if(len>0) {
        txt.replace (start,len,QString("%1").arg (num,2,10,QChar('0')));
    }

三、添加个界面

如果不用界面,开发就算到此为止,很简单,目录名的替换直接用 QDir::rename(const QString &oldName, const QString &newName)

实现方法太多也是挺让人愁的,最终敲定的结果是 用 QTreeView + QDirModel 来实现。

又发现 QDirModel 的 setData 方法可以直接修改目录名称,这不是又能偷懒了么

bool QDirModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    Q_D(QDirModel);
    if (!d->indexValid(index) || index.column() != 0
        || (flags(index) & Qt::ItemIsEditable) == 0 || role != Qt::EditRole)
        return false;
		......
    if (dir.rename(node->info.fileName(), name)) {
		......
}

QDirModel :: setData 需要 index对应的item具有可编辑设置才行,使用 model->setReadOnly (false);

1. 简单布局

在这里插入图片描述 在这里插入图片描述

如果只需要显示目录,model 添加过滤器 model->setFilter (QDir::Dirs | QDir::NoDotAndDotDot) ;

2. Open按钮的clicked槽函数

  • 点击按钮弹出目录选择对话框

    QFileDialog::getExistingDirectory (this,"选择目录",curPath,QFileDialog::DontUseNativeDialog);,当然使用本地对话框也行

在这里插入图片描述

  • 更新treeView的rootIndex

        ui->lineEditPath->setText (selPath);
        auto rootIndex = model->index (selPath);
        ui->treeView->setRootIndex (rootIndex);
    

在这里插入图片描述

3. Apply 按钮的clicked槽函数

  • 遍历目录节点, 并修改目录名

    获取根索引,获取第1个索引,treeView获取下一个索引

        // 获取树的根索引
        auto rootIndex = ui->treeView->rootIndex ();
        // 根索引的第一个子索引
        auto subIndex = model->index (0,0,rootIndex);
    
        while (subIndex.isValid ()) {
            // 获取 目录名
            auto dirname = subIndex.data ().toString ();
            // 获取 替换中文数字以后的字符串
            auto txt = replaceChineseNumber (dirname);
            // model 设置数据后,会自动对应的目录名
            qout << model->setData (subIndex,txt);
    
            // 迭代到下一个索引
            subIndex = ui->treeView->indexBelow (subIndex);
        }
    

在这里插入图片描述

四、cpp代码

#include "DirExplorer.h"
#include "ui_DirExplorer.h"

#include <QDebug>
#include <QFileDialog>
#include <QAbstractItemModel>
#include <QStandardPaths>

static QString chineseNumber = "一二三四五六七八九十";
static QString selPath;

DirExplorer::DirExplorer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DirExplorer)
{
    ui->setupUi(this);
    //    model = new QFileSystemModel(this);
    model = new QDirModel(this);
    model->setReadOnly (false);
	//    model->setFilter (QDir::Dirs | QDir::NoDotAndDotDot) ;

    ui->treeView->setModel (model);

    auto index = model->index (QStandardPaths::standardLocations(QStandardPaths::DesktopLocation).at(0));
    ui->treeView->setRootIndex (index);


    qout << model->columnCount ();
    for (int i = 1; i < model->columnCount (); ++i) {
        ui->treeView->hideColumn (i);
    }
}

DirExplorer::~DirExplorer()
{
    delete ui;
}

QString DirExplorer::replaceChineseNumber(QString txt)
{
    int len = 0;
    int num = 0;
    int start = 0;
    for (int i = 0; i < txt.length (); ++i) {
        auto index = chineseNumber.indexOf (txt.at (i));
        // 找到第一个中文数字
        if(index != -1){
            if(len==0)
                start = i;
            if(index>=9 && len != 0){
                num *=10;
            } else{
                num += index+1;
            }
            len += 1;
        }
    }
    if(len>0) {
        txt.replace (start,len,QString("%1").arg (num,2,10,QChar('0')));
    }
    return txt;
}


void DirExplorer::on_toolButtonOpen_clicked()
{
    auto curPath = ui->lineEditPath->text ();
    if (curPath.isEmpty ())
        curPath = QStandardPaths::standardLocations(QStandardPaths::DesktopLocation).at(0);
    selPath = QFileDialog::getExistingDirectory (this,"选择目录",curPath,QFileDialog::DontUseNativeDialog);
    if(selPath.isEmpty ())
        return;

    ui->lineEditPath->setText (selPath);
    auto rootIndex = model->index (selPath);
    ui->treeView->setRootIndex (rootIndex);
}


void DirExplorer::on_toolButtonApply_clicked()
{
    // 获取树的根索引
    auto rootIndex = ui->treeView->rootIndex ();
    // 根索引的第一个子索引
    auto subIndex = model->index (0,0,rootIndex);

    while (subIndex.isValid ()) {
        // 获取 目录名
        auto dirname = subIndex.data ().toString ();
        // 获取 替换中文数字以后的字符串
        auto txt = replaceChineseNumber (dirname);
        // model 设置数据后,会自动对应的目录名
        qout << model->setData (subIndex,txt);

        // 迭代到下一个索引
        subIndex = ui->treeView->indexBelow (subIndex);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值