QCMakeWidgets.cxx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION_CHECK(5, 14, 0)
  4. #include "QCMakeWidgets.h"
  5. #include <utility>
  6. #include <QFileDialog>
  7. #include <QFileInfo>
  8. #include <QResizeEvent>
  9. #include <QSortFilterProxyModel>
  10. #include <QToolButton>
  11. #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
  12. # include <QRegularExpression>
  13. #endif
  14. #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
  15. # include <QFileSystemModel>
  16. #else
  17. # include <QDirModel>
  18. #endif
  19. QCMakeFileEditor::QCMakeFileEditor(QWidget* p, QString var)
  20. : QLineEdit(p)
  21. , Variable(std::move(var))
  22. {
  23. this->ToolButton = new QToolButton(this);
  24. this->ToolButton->setText("...");
  25. this->ToolButton->setCursor(QCursor(Qt::ArrowCursor));
  26. QObject::connect(this->ToolButton, &QAbstractButton::clicked, this,
  27. &QCMakeFileEditor::chooseFile);
  28. }
  29. QCMakeFilePathEditor::QCMakeFilePathEditor(QWidget* p, const QString& var)
  30. : QCMakeFileEditor(p, var)
  31. {
  32. this->setCompleter(new QCMakeFileCompleter(this, false));
  33. }
  34. QCMakePathEditor::QCMakePathEditor(QWidget* p, const QString& var)
  35. : QCMakeFileEditor(p, var)
  36. {
  37. this->setCompleter(new QCMakeFileCompleter(this, true));
  38. }
  39. void QCMakeFileEditor::resizeEvent(QResizeEvent* e)
  40. {
  41. // make the tool button fit on the right side
  42. int h = e->size().height();
  43. // move the line edit to make room for the tool button
  44. this->setContentsMargins(0, 0, h, 0);
  45. // put the tool button in its place
  46. this->ToolButton->resize(h, h);
  47. this->ToolButton->move(this->width() - h, 0);
  48. }
  49. void QCMakeFilePathEditor::chooseFile()
  50. {
  51. // choose a file and set it
  52. QString path;
  53. QFileInfo info(this->text());
  54. QString title;
  55. if (this->Variable.isEmpty()) {
  56. title = tr("Select File");
  57. } else {
  58. title = tr("Select File for %1");
  59. title = title.arg(this->Variable);
  60. }
  61. emit this->fileDialogExists(true);
  62. path =
  63. QFileDialog::getOpenFileName(this, title, info.absolutePath(), QString(),
  64. nullptr, QFileDialog::DontResolveSymlinks);
  65. emit this->fileDialogExists(false);
  66. if (!path.isEmpty()) {
  67. this->setText(QDir::fromNativeSeparators(path));
  68. }
  69. }
  70. void QCMakePathEditor::chooseFile()
  71. {
  72. // choose a file and set it
  73. QString path;
  74. QString title;
  75. if (this->Variable.isEmpty()) {
  76. title = tr("Select Path");
  77. } else {
  78. title = tr("Select Path for %1");
  79. title = title.arg(this->Variable);
  80. }
  81. emit this->fileDialogExists(true);
  82. path = QFileDialog::getExistingDirectory(this, title, this->text(),
  83. QFileDialog::ShowDirsOnly |
  84. QFileDialog::DontResolveSymlinks);
  85. emit this->fileDialogExists(false);
  86. if (!path.isEmpty()) {
  87. this->setText(QDir::fromNativeSeparators(path));
  88. }
  89. }
  90. #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
  91. // use same QFileSystemModel for all completers
  92. static QFileSystemModel* fileDirModel()
  93. {
  94. static QFileSystemModel* m = nullptr;
  95. if (!m) {
  96. m = new QFileSystemModel();
  97. }
  98. return m;
  99. }
  100. static QFileSystemModel* pathDirModel()
  101. {
  102. static QFileSystemModel* m = nullptr;
  103. if (!m) {
  104. m = new QFileSystemModel();
  105. m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
  106. }
  107. return m;
  108. }
  109. #else
  110. // use same QDirModel for all completers
  111. static QDirModel* fileDirModel()
  112. {
  113. static QDirModel* m = nullptr;
  114. if (!m) {
  115. m = new QDirModel();
  116. }
  117. return m;
  118. }
  119. static QDirModel* pathDirModel()
  120. {
  121. static QDirModel* m = nullptr;
  122. if (!m) {
  123. m = new QDirModel();
  124. m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
  125. }
  126. return m;
  127. }
  128. #endif
  129. QCMakeFileCompleter::QCMakeFileCompleter(QObject* o, bool dirs)
  130. : QCompleter(o)
  131. {
  132. #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
  133. QFileSystemModel* m = dirs ? pathDirModel() : fileDirModel();
  134. this->setModel(m);
  135. m->setRootPath(QString());
  136. #else
  137. QDirModel* m = dirs ? pathDirModel() : fileDirModel();
  138. this->setModel(m);
  139. #endif
  140. }
  141. QString QCMakeFileCompleter::pathFromIndex(const QModelIndex& idx) const
  142. {
  143. return QDir::fromNativeSeparators(QCompleter::pathFromIndex(idx));
  144. }
  145. namespace QtCMake {
  146. bool setSearchFilter(QSortFilterProxyModel* model, const QString& searchString)
  147. {
  148. #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
  149. QRegularExpression const regex(searchString,
  150. QRegularExpression::CaseInsensitiveOption |
  151. QRegularExpression::DontCaptureOption);
  152. if (regex.isValid()) {
  153. model->setFilterRegularExpression(regex);
  154. return true;
  155. }
  156. model->setFilterFixedString(QString{});
  157. return false;
  158. #else
  159. model->setFilterFixedString(searchString);
  160. return true;
  161. #endif
  162. }
  163. void setSearchFilterColor(QLineEdit* edit, bool valid)
  164. {
  165. QPalette palette;
  166. if (!valid) {
  167. palette.setColor(QPalette::Base, Qt::red);
  168. }
  169. edit->setPalette(palette);
  170. }
  171. }