Qt内支持多选文件及文件夹的Dialog

Qt自带的选则本地文件及文件夹的对话框QFileDialog其实挺好用的,它支持单选文件、多选文件、单选文件夹,可惜我收到的需求是要支持多选文件+多选文件夹,且文件和文件夹可以混着选,现有(Qt版本:5.12.9)的QFileDialog是不支持这种需求的,本来以为是要自己写个Dialog的,没想到经过网上搜索之后,发现QFileDialog还有一种模式可以支持这种需求,最主要的一个措施是设置它的Option为QFileDialog::DontUseNativeDialog,由此这个对话框变成了Qt自己设计(可以在源码内找到相应的ui文件)的一个对话框,不根据运行的系统平台来调用当前系统的对话框,完整代码如下:

class FileDialog : public QFileDialog
{
    Q_OBJECT
public:
    explicit FileDialog(QWidget *parent = Q_NULLPTR)
        : QFileDialog(parent) {
        m_btnOpen = NULL;
        m_listView = NULL;
        m_treeView = NULL;
        m_selectedFiles.clear();

        setLabelTextAccept, "存入";
        setLabelTextReject, "取消";

        this->setOptionsDontResolveSymlinks | QFileDialog::DontUseNativeDialog;
        this->setFileModeDirectory;

        QList<QPushButton*> btns = this->findChildren<QPushButton*>();
        for (int i = 0; i < btns.size(); ++i) {
            QString text = btns[i]->text();
            if (text == "存入") {
                m_btnOpen = btns[i];
                break;
            }
        }

        if (!m_btnOpen) return;

        m_btnOpen->disconnect(SIGNAL(clicked()));
        connect(m_btnOpen, SIGNAL(clicked()), this, SLOT(chooseClicked()));


        m_listView = findChild<QListView*>("listView");
        if (m_listView) {
            m_listView->setSelectionModeExtendedSelection;
        }


        m_treeView = findChild<QTreeView*>();
        if (m_treeView) {
            m_treeView->setSelectionModeExtendedSelection;
        }

        QItemSelectionModel *tModel = m_listView->selectionModel();
        connect(tModel,&QItemSelectionModel::selectionChanged,[=]{
            QModelIndexList indexList = tModel->selectedIndexes();
            if(indexList.count()>=1)
                m_btnOpen->setEnabled(true);
            else
                m_btnOpen->setEnabled(false);
        });
        m_btnOpen->setEnabled(false);
    }

    QStringList selectedFiles() {
        return m_selectedFiles;
    }

public slots:
    void chooseClicked() {
        QModelIndexList indexList = m_listView->selectionModel()->selectedIndexes();
        foreach (QModelIndex index, indexList) {
            if (index.column()== 0)
                m_selectedFiles.append(this->directory().absolutePath() + "/" + index.data().toString());
        }
        QDialog::accept();
    }

private:
    QListView *m_listView;
    QTreeView *m_treeView;
    QPushButton *m_btnOpen;
    QStringList m_selectedFiles;
};

这样我们只要在需要多选文件和文件夹时使用以下代码获取结果就行了

FileDialog fileDiglog(this);
fileDiglog.setWindowTitle("上传");
fileDiglog.exec();
QStringList fileList = fileDiglog.selectedFiles();

但是我如此实现之后,依然发现了一些问题,由于该对话框是Qt自带的对话框,且使用winqtdeploy打包时不会打包系统语言的语言包,因此界面上控件内的内容和提示都是英文的,就算使用setLabelText方法,其实也就能控制里面部分控件的内容,不能把所有控件的内容变成中文。

经过多次尝试之后,我发现把简体中文语言包直接作为资源文件放进程序,启用Qt自带的翻译器就能解决这个问题:

//qt_zh_CN为自带的翻译文件,可翻译QFileDialog内各组件的文本
QTranslator* pTranslator = new QTranslator();
pTranslator->load("://resources/qt_zh_CN.qm");
a.installTranslator(pTranslator);

至此,一个支持本地多选文件+多选文件夹的对话框功能完成!