QFileDialog that accepts a single file or a single directory

前端 未结 4 1366
有刺的猬
有刺的猬 2021-02-13 23:46

Is it possible to show a QFileDialog where the user can select a file or a directory, either one?

QFileDialog::getOpenFileName() accepts only files, while

4条回答
  •  忘了有多久
    2021-02-14 00:31

    What worked for me was to use:

    file_dialog.setProxyModel(nullptr);
    

    as suggested here, or

    class FileFilterProxyModel : public QSortFilterProxyModel
    {
    protected:
        virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
        {
            QFileSystemModel* fileModel = qobject_cast(sourceModel());
            return (fileModel!=NULL && fileModel->isDir(sourceModel()->index(sourceRow, 0, sourceParent))) || QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
        }
    };
    ...
    FileFilterProxyModel* proxyModel = new FileFilterProxyModel;
    file_dialog.setProxyModel(proxyModel);
    

    as suggested here, or

    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();
    
            this->setOption(QFileDialog::DontUseNativeDialog, true);
            this->setFileMode(QFileDialog::Directory);
            QList btns = this->findChildren();
            for (int i = 0; i < btns.size(); ++i) {
                QString text = btns[i]->text();
                if (text.toLower().contains("open") || text.toLower().contains("choose"))
                {
                    m_btnOpen = btns[i];
                    break;
                }
            }
    
            if (!m_btnOpen) return;
    
            m_btnOpen->installEventFilter(this);
            //connect(m_btnOpen, SIGNAL(changed()), this, SLOT(btnChanged()))
            m_btnOpen->disconnect(SIGNAL(clicked()));
            connect(m_btnOpen, SIGNAL(clicked()), this, SLOT(chooseClicked()));
    
    
            m_listView = findChild("listView");
            if (m_listView)
                m_listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    
            m_treeView = findChild();
            if (m_treeView)
                m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        }
    
        QStringList selectedFiles()
        {
            return m_selectedFiles;
        }
    
        bool eventFilter( QObject* watched, QEvent* event )
        {
            QPushButton *btn = qobject_cast(watched);
            if (btn)
            {
                if(event->type()==QEvent::EnabledChange) {
                    if (!btn->isEnabled())
                        btn->setEnabled(true);
                }
            }
    
            return QWidget::eventFilter(watched, event);
        }
    
    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;
    };
    

    as suggested here. Credits for the original authors and me.

提交回复
热议问题