当前位置:   article > 正文

在QML中使用QtWidgets的QFileDialog_qml qfiledialog

qml qfiledialog

QML 中虽然也提供了 FileDialog 组件,但是使用体验远不如 QtWidgets 中的 QFileDialog,故做了简单的封装,使得可以在 QML 中使用 QFileDialog 来选择文件或者文件夹。

因为[Qt文档]提示不应直接在 QML 逻辑中启用自己的事件循环,所以我是通过信号槽来弹出和传递返回结果,操作流程和 QML 的 FileDialog 类似。

Demo 链接:

https://github.com/gongjianbo/MyTestCode/tree/master/Qml/FileDialogWrap

主要代码:

  1. #pragma once
  2. #include <QObject>
  3. #include <QUrl>
  4. #include <QSettings>
  5. #include <QFileDialog>
  6. /**
  7. * @brief 包装QFileDialog在QML中使用
  8. * @author 龚建波
  9. * @date 2022-12-31
  10. * @details
  11. * 参考:https://doc.qt.io/qt-5/qtquick-performance.html
  12. * 文档指出我们不应该在qml逻辑中执行自己的事件循环,所以通过信号槽异步调用对话框exec
  13. * 而操作结果也只能通过信号传递,不能像cpp代码那样exec后面直接获取结果
  14. */
  15. class FileDialogWrap : public QObject
  16. {
  17. Q_OBJECT
  18. Q_PROPERTY(int mode READ getMode WRITE setMode NOTIFY modeChanged)
  19. Q_PROPERTY(QString title READ getTitle WRITE setTitle NOTIFY titleChanged)
  20. Q_PROPERTY(QStringList nameFilters READ getNameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
  21. Q_PROPERTY(QUrl currentUrl READ getCurrentUrl NOTIFY currentUrlChanged)
  22. Q_PROPERTY(QList<QUrl> currentUrls READ getCurrentUrls NOTIFY currentUrlsChanged)
  23. public:
  24. enum WorkMode {
  25. SelectFile, //单选文件
  26. SelectFiles, //多选文件
  27. SelectDir, //选择目录
  28. SaveFile //保存文件
  29. };
  30. Q_ENUM(WorkMode)
  31. public:
  32. explicit FileDialogWrap(QObject *parent = nullptr);
  33. ~FileDialogWrap();
  34. //工作模式,枚举WorkMode
  35. int getMode() const;
  36. void setMode(int mode);
  37. //标题设置
  38. QString getTitle() const;
  39. void setTitle(const QString &title);
  40. //后缀过滤
  41. QStringList getNameFilters() const;
  42. void setNameFilters(const QStringList &filters);
  43. //单选结果
  44. QUrl getCurrentUrl() const;
  45. void setCurrentUrl(const QUrl &url);
  46. //多选结果
  47. QList<QUrl> getCurrentUrls() const;
  48. void setCurrentUrls(const QList<QUrl> &urls);
  49. Q_INVOKABLE void open();
  50. Q_INVOKABLE void close();
  51. //打开前选中某个路径,带文件名则作为选中的文件名
  52. Q_INVOKABLE void selectUrl(const QUrl &url);
  53. //桌面路径
  54. Q_INVOKABLE static QString desktopPath();
  55. Q_INVOKABLE static QUrl desktopUrl();
  56. //设置ini配置路径,qml初始化之前cpp中设置
  57. static void initSetting(const QString &filepath, const QSettings::Format &format = QSettings::IniFormat);
  58. private:
  59. QString getDefaultPath();
  60. void setDefaultPath(const QString &dirpath);
  61. private slots:
  62. void openDialog();
  63. signals:
  64. void __openRequest();
  65. void __closeRequest();
  66. void accepted();
  67. void rejected();
  68. void modeChanged();
  69. void titleChanged();
  70. void nameFiltersChanged();
  71. void currentUrlChanged();
  72. void currentUrlsChanged();
  73. private:
  74. //ini配置文件路径
  75. inline static QString iniPath;
  76. inline static QSettings::Format iniFormat{QSettings::IniFormat};
  77. //对话框
  78. QFileDialog *dialog;
  79. //模式,选择文件还是目录等
  80. int workMode{FileDialogWrap::SelectFile};
  81. //文件名过滤
  82. QStringList nameFilters{"All (*.*)"};
  83. //单选结果,当前选中路径
  84. QUrl currentUrl;
  85. //多选结果
  86. QList<QUrl> currentUrls;
  87. //selectUrl可设置,下次弹出时生效
  88. QUrl nextUrl;
  89. };
  1. #include "FileDialogWrap.h"
  2. #include <QCoreApplication>
  3. #include <QStandardPaths>
  4. #include <QFileInfo>
  5. #include <QDebug>
  6. FileDialogWrap::FileDialogWrap(QObject *parent)
  7. : QObject{parent}
  8. , dialog{new QFileDialog}
  9. {
  10. setTitle(QCoreApplication::applicationName());
  11. connect(this, &FileDialogWrap::__openRequest, this, &FileDialogWrap::openDialog, Qt::QueuedConnection);
  12. connect(this, &FileDialogWrap::__closeRequest, this, [=](){
  13. dialog->reject();
  14. }, Qt::QueuedConnection);
  15. }
  16. FileDialogWrap::~FileDialogWrap()
  17. {
  18. dialog->deleteLater();
  19. }
  20. int FileDialogWrap::getMode() const
  21. {
  22. return workMode;
  23. }
  24. void FileDialogWrap::setMode(int mode)
  25. {
  26. if (mode != workMode) {
  27. workMode = mode;
  28. emit modeChanged();
  29. }
  30. }
  31. QString FileDialogWrap::getTitle() const
  32. {
  33. return dialog->windowTitle();
  34. }
  35. void FileDialogWrap::setTitle(const QString &title)
  36. {
  37. if (title != getTitle()) {
  38. dialog->setWindowTitle(title);
  39. emit titleChanged();
  40. }
  41. }
  42. QStringList FileDialogWrap::getNameFilters() const
  43. {
  44. return nameFilters;
  45. }
  46. void FileDialogWrap::setNameFilters(const QStringList &filters)
  47. {
  48. if (filters != nameFilters) {
  49. nameFilters = filters;
  50. emit nameFiltersChanged();
  51. }
  52. }
  53. QUrl FileDialogWrap::getCurrentUrl() const
  54. {
  55. return currentUrl;
  56. }
  57. void FileDialogWrap::setCurrentUrl(const QUrl &url)
  58. {
  59. if (url != currentUrl) {
  60. currentUrl = url;
  61. emit currentUrlChanged();
  62. }
  63. }
  64. QList<QUrl> FileDialogWrap::getCurrentUrls() const
  65. {
  66. return currentUrls;
  67. }
  68. void FileDialogWrap::setCurrentUrls(const QList<QUrl> &urls)
  69. {
  70. if (urls != currentUrls) {
  71. currentUrls = urls;
  72. emit currentUrlsChanged();
  73. }
  74. }
  75. void FileDialogWrap::open()
  76. {
  77. if (dialog->isVisible())
  78. return;
  79. emit __openRequest();
  80. }
  81. void FileDialogWrap::close()
  82. {
  83. if (!dialog->isVisible())
  84. return;
  85. emit __closeRequest();
  86. }
  87. void FileDialogWrap::selectUrl(const QUrl &url)
  88. {
  89. nextUrl = url;
  90. }
  91. QString FileDialogWrap::desktopPath()
  92. {
  93. return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
  94. }
  95. QUrl FileDialogWrap::desktopUrl()
  96. {
  97. return QUrl::fromLocalFile(desktopPath());
  98. }
  99. void FileDialogWrap::initSetting(const QString &filepath, const QSettings::Format &format)
  100. {
  101. iniPath = filepath;
  102. iniFormat = format;
  103. }
  104. QString FileDialogWrap::getDefaultPath()
  105. {
  106. //QFileDialog默认实现在构造时恢复,析构时保存
  107. //QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
  108. //settings.beginGroup(QLatin1String("FileDialog"));
  109. //记录上一次选择的路径
  110. QSettings setting(iniPath, QSettings::IniFormat);
  111. QString dirpath = setting.value("LastPath").toString();
  112. if (dirpath.isEmpty()) {
  113. //默认桌面路径
  114. dirpath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
  115. }
  116. qDebug()<<"get default"<<dirpath;
  117. return dirpath;
  118. }
  119. void FileDialogWrap::setDefaultPath(const QString &dirpath)
  120. {
  121. QSettings setting(iniPath, QSettings::IniFormat);
  122. setting.setValue("LastPath", dirpath);
  123. qDebug()<<"set default"<<dirpath;
  124. }
  125. void FileDialogWrap::openDialog()
  126. {
  127. switch (workMode) {
  128. case SelectFile:
  129. {
  130. dialog->setFileMode(QFileDialog::ExistingFile);
  131. }
  132. break;
  133. case SelectFiles:
  134. {
  135. dialog->setFileMode(QFileDialog::ExistingFiles);
  136. }
  137. break;
  138. case SelectDir:
  139. {
  140. dialog->setOption(QFileDialog::ShowDirsOnly);
  141. //参考源码中的写法
  142. QT_WARNING_PUSH
  143. QT_WARNING_DISABLE_DEPRECATED
  144. dialog->setFileMode(QFileDialog::DirectoryOnly);
  145. QT_WARNING_POP
  146. }
  147. break;
  148. case SaveFile:
  149. {
  150. dialog->setFileMode(QFileDialog::AnyFile);
  151. dialog->setAcceptMode(QFileDialog::AcceptSave);
  152. }
  153. break;
  154. default: break;
  155. }
  156. dialog->setNameFilters(nameFilters);
  157. //设置了url就用设置的,否则用上次保存的目录
  158. //selectUrl设置nextUrl
  159. if (nextUrl.isValid()) {
  160. QFileInfo info(nextUrl.toLocalFile());
  161. if (info.isDir()) {
  162. dialog->setDirectory(info.absoluteFilePath());
  163. } else {
  164. dialog->setDirectory(info.absolutePath());
  165. dialog->selectFile(info.fileName());
  166. }
  167. nextUrl.clear();
  168. } else {
  169. dialog->setDirectory(getDefaultPath());
  170. }
  171. const int ret = dialog->exec();
  172. if (ret == QDialog::Rejected) {
  173. emit rejected();
  174. return;
  175. }
  176. auto &&urls = dialog->selectedUrls();
  177. if (urls.isEmpty()) {
  178. setCurrentUrl(QUrl());
  179. setDefaultPath(desktopPath());
  180. } else {
  181. QUrl first_url = urls.first();
  182. setCurrentUrl(first_url);
  183. //保存目录到配置文件
  184. QFileInfo info(first_url.toLocalFile());
  185. if (info.isDir()) {
  186. setDefaultPath(info.absoluteFilePath());
  187. } else {
  188. setDefaultPath(info.absolutePath());
  189. }
  190. }
  191. setCurrentUrls(urls);
  192. emit accepted();
  193. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/831284
推荐阅读
相关标签
  

闽ICP备14008679号