PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/examples/widgets/dialogs/findfiles/window.cpp

https://gitlab.com/f3822/qtbase
C++ | 311 lines | 195 code | 34 blank | 82 comment | 24 complexity | 7c6b119b072167ace497556d74593fb1 MD5 | raw file
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2016 The Qt Company Ltd.
  4. ** Contact: https://www.qt.io/licensing/
  5. **
  6. ** This file is part of the examples of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:BSD$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and The Qt Company. For licensing terms
  14. ** and conditions see https://www.qt.io/terms-conditions. For further
  15. ** information use the contact form at https://www.qt.io/contact-us.
  16. **
  17. ** BSD License Usage
  18. ** Alternatively, you may use this file under the terms of the BSD license
  19. ** as follows:
  20. **
  21. ** "Redistribution and use in source and binary forms, with or without
  22. ** modification, are permitted provided that the following conditions are
  23. ** met:
  24. ** * Redistributions of source code must retain the above copyright
  25. ** notice, this list of conditions and the following disclaimer.
  26. ** * Redistributions in binary form must reproduce the above copyright
  27. ** notice, this list of conditions and the following disclaimer in
  28. ** the documentation and/or other materials provided with the
  29. ** distribution.
  30. ** * Neither the name of The Qt Company Ltd nor the names of its
  31. ** contributors may be used to endorse or promote products derived
  32. ** from this software without specific prior written permission.
  33. **
  34. **
  35. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  36. ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  37. ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  38. ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  39. ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  42. ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  43. ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44. ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  45. ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  46. **
  47. ** $QT_END_LICENSE$
  48. **
  49. ****************************************************************************/
  50. #include <QtWidgets>
  51. #include "window.h"
  52. //! [17]
  53. enum { absoluteFileNameRole = Qt::UserRole + 1 };
  54. //! [17]
  55. //! [18]
  56. static inline QString fileNameOfItem(const QTableWidgetItem *item)
  57. {
  58. return item->data(absoluteFileNameRole).toString();
  59. }
  60. //! [18]
  61. //! [14]
  62. static inline void openFile(const QString &fileName)
  63. {
  64. QDesktopServices::openUrl(QUrl::fromLocalFile(fileName));
  65. }
  66. //! [14]
  67. //! [0]
  68. Window::Window(QWidget *parent)
  69. : QWidget(parent)
  70. {
  71. setWindowTitle(tr("Find Files"));
  72. QPushButton *browseButton = new QPushButton(tr("&Browse..."), this);
  73. connect(browseButton, &QAbstractButton::clicked, this, &Window::browse);
  74. findButton = new QPushButton(tr("&Find"), this);
  75. connect(findButton, &QAbstractButton::clicked, this, &Window::find);
  76. fileComboBox = createComboBox(tr("*"));
  77. connect(fileComboBox->lineEdit(), &QLineEdit::returnPressed,
  78. this, &Window::animateFindClick);
  79. textComboBox = createComboBox();
  80. connect(textComboBox->lineEdit(), &QLineEdit::returnPressed,
  81. this, &Window::animateFindClick);
  82. directoryComboBox = createComboBox(QDir::toNativeSeparators(QDir::currentPath()));
  83. connect(directoryComboBox->lineEdit(), &QLineEdit::returnPressed,
  84. this, &Window::animateFindClick);
  85. filesFoundLabel = new QLabel;
  86. createFilesTable();
  87. QGridLayout *mainLayout = new QGridLayout(this);
  88. mainLayout->addWidget(new QLabel(tr("Named:")), 0, 0);
  89. mainLayout->addWidget(fileComboBox, 0, 1, 1, 2);
  90. mainLayout->addWidget(new QLabel(tr("Containing text:")), 1, 0);
  91. mainLayout->addWidget(textComboBox, 1, 1, 1, 2);
  92. mainLayout->addWidget(new QLabel(tr("In directory:")), 2, 0);
  93. mainLayout->addWidget(directoryComboBox, 2, 1);
  94. mainLayout->addWidget(browseButton, 2, 2);
  95. mainLayout->addWidget(filesTable, 3, 0, 1, 3);
  96. mainLayout->addWidget(filesFoundLabel, 4, 0, 1, 2);
  97. mainLayout->addWidget(findButton, 4, 2);
  98. //! [0]
  99. //! [1]
  100. connect(new QShortcut(QKeySequence::Quit, this), &QShortcut::activated,
  101. qApp, &QApplication::quit);
  102. //! [1]
  103. }
  104. //! [2]
  105. void Window::browse()
  106. {
  107. QString directory =
  108. QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Find Files"), QDir::currentPath()));
  109. if (!directory.isEmpty()) {
  110. if (directoryComboBox->findText(directory) == -1)
  111. directoryComboBox->addItem(directory);
  112. directoryComboBox->setCurrentIndex(directoryComboBox->findText(directory));
  113. }
  114. }
  115. //! [2]
  116. static void updateComboBox(QComboBox *comboBox)
  117. {
  118. if (comboBox->findText(comboBox->currentText()) == -1)
  119. comboBox->addItem(comboBox->currentText());
  120. }
  121. //! [3]
  122. void Window::find()
  123. {
  124. filesTable->setRowCount(0);
  125. QString fileName = fileComboBox->currentText();
  126. QString text = textComboBox->currentText();
  127. QString path = QDir::cleanPath(directoryComboBox->currentText());
  128. currentDir = QDir(path);
  129. //! [3]
  130. updateComboBox(fileComboBox);
  131. updateComboBox(textComboBox);
  132. updateComboBox(directoryComboBox);
  133. //! [4]
  134. QStringList filter;
  135. if (!fileName.isEmpty())
  136. filter << fileName;
  137. QDirIterator it(path, filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
  138. QStringList files;
  139. while (it.hasNext())
  140. files << it.next();
  141. if (!text.isEmpty())
  142. files = findFiles(files, text);
  143. files.sort();
  144. showFiles(files);
  145. }
  146. //! [4]
  147. void Window::animateFindClick()
  148. {
  149. findButton->animateClick();
  150. }
  151. //! [5]
  152. QStringList Window::findFiles(const QStringList &files, const QString &text)
  153. {
  154. QProgressDialog progressDialog(this);
  155. progressDialog.setCancelButtonText(tr("&Cancel"));
  156. progressDialog.setRange(0, files.size());
  157. progressDialog.setWindowTitle(tr("Find Files"));
  158. //! [5] //! [6]
  159. QMimeDatabase mimeDatabase;
  160. QStringList foundFiles;
  161. for (int i = 0; i < files.size(); ++i) {
  162. progressDialog.setValue(i);
  163. progressDialog.setLabelText(tr("Searching file number %1 of %n...", nullptr, files.size()).arg(i));
  164. QCoreApplication::processEvents();
  165. //! [6]
  166. if (progressDialog.wasCanceled())
  167. break;
  168. //! [7]
  169. const QString fileName = files.at(i);
  170. const QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileName);
  171. if (mimeType.isValid() && !mimeType.inherits(QStringLiteral("text/plain"))) {
  172. qWarning() << "Not searching binary file " << QDir::toNativeSeparators(fileName);
  173. continue;
  174. }
  175. QFile file(fileName);
  176. if (file.open(QIODevice::ReadOnly)) {
  177. QString line;
  178. QTextStream in(&file);
  179. while (!in.atEnd()) {
  180. if (progressDialog.wasCanceled())
  181. break;
  182. line = in.readLine();
  183. if (line.contains(text, Qt::CaseInsensitive)) {
  184. foundFiles << files[i];
  185. break;
  186. }
  187. }
  188. }
  189. }
  190. return foundFiles;
  191. }
  192. //! [7]
  193. //! [8]
  194. void Window::showFiles(const QStringList &paths)
  195. {
  196. for (const QString &filePath : paths) {
  197. const QString toolTip = QDir::toNativeSeparators(filePath);
  198. const QString relativePath = QDir::toNativeSeparators(currentDir.relativeFilePath(filePath));
  199. const qint64 size = QFileInfo(filePath).size();
  200. QTableWidgetItem *fileNameItem = new QTableWidgetItem(relativePath);
  201. fileNameItem->setData(absoluteFileNameRole, QVariant(filePath));
  202. fileNameItem->setToolTip(toolTip);
  203. fileNameItem->setFlags(fileNameItem->flags() ^ Qt::ItemIsEditable);
  204. QTableWidgetItem *sizeItem = new QTableWidgetItem(QLocale().formattedDataSize(size));
  205. sizeItem->setData(absoluteFileNameRole, QVariant(filePath));
  206. sizeItem->setToolTip(toolTip);
  207. sizeItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
  208. sizeItem->setFlags(sizeItem->flags() ^ Qt::ItemIsEditable);
  209. int row = filesTable->rowCount();
  210. filesTable->insertRow(row);
  211. filesTable->setItem(row, 0, fileNameItem);
  212. filesTable->setItem(row, 1, sizeItem);
  213. }
  214. filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", nullptr, paths.size()));
  215. filesFoundLabel->setWordWrap(true);
  216. }
  217. //! [8]
  218. //! [10]
  219. QComboBox *Window::createComboBox(const QString &text)
  220. {
  221. QComboBox *comboBox = new QComboBox;
  222. comboBox->setEditable(true);
  223. comboBox->addItem(text);
  224. comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  225. return comboBox;
  226. }
  227. //! [10]
  228. //! [11]
  229. void Window::createFilesTable()
  230. {
  231. filesTable = new QTableWidget(0, 2);
  232. filesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
  233. QStringList labels;
  234. labels << tr("Filename") << tr("Size");
  235. filesTable->setHorizontalHeaderLabels(labels);
  236. filesTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
  237. filesTable->verticalHeader()->hide();
  238. filesTable->setShowGrid(false);
  239. //! [15]
  240. filesTable->setContextMenuPolicy(Qt::CustomContextMenu);
  241. connect(filesTable, &QTableWidget::customContextMenuRequested,
  242. this, &Window::contextMenu);
  243. connect(filesTable, &QTableWidget::cellActivated,
  244. this, &Window::openFileOfItem);
  245. //! [15]
  246. }
  247. //! [11]
  248. //! [12]
  249. void Window::openFileOfItem(int row, int /* column */)
  250. {
  251. const QTableWidgetItem *item = filesTable->item(row, 0);
  252. openFile(fileNameOfItem(item));
  253. }
  254. //! [12]
  255. //! [16]
  256. void Window::contextMenu(const QPoint &pos)
  257. {
  258. const QTableWidgetItem *item = filesTable->itemAt(pos);
  259. if (!item)
  260. return;
  261. QMenu menu;
  262. #ifndef QT_NO_CLIPBOARD
  263. QAction *copyAction = menu.addAction("Copy Name");
  264. #endif
  265. QAction *openAction = menu.addAction("Open");
  266. QAction *action = menu.exec(filesTable->mapToGlobal(pos));
  267. if (!action)
  268. return;
  269. const QString fileName = fileNameOfItem(item);
  270. if (action == openAction)
  271. openFile(fileName);
  272. #ifndef QT_NO_CLIPBOARD
  273. else if (action == copyAction)
  274. QGuiApplication::clipboard()->setText(QDir::toNativeSeparators(fileName));
  275. #endif
  276. }
  277. //! [16]