From d1a30be5abcc2d5e5340866434b2691275a135a6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 5 Jul 2016 13:26:53 +0200 Subject: Polish the findfiles example to be actually useful MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Simplify the code, remove unused members - Fix the translations of plurals to use %n - Add tooltip displaying full paths in list - Add context menu allowing to copy the name and open - Display the correct slashes on Windows - Connect the returnPressed() signals of the line edits - Make the search recursive - Do not search binary files by checking the mime type Change-Id: I3663799c88931db1f58c03ea35211e7ab03737ec Reviewed-by: Topi Reiniƶ --- examples/widgets/dialogs/findfiles/window.cpp | 139 +++++++++++++++++++------- examples/widgets/dialogs/findfiles/window.h | 6 +- 2 files changed, 106 insertions(+), 39 deletions(-) (limited to 'examples/widgets/dialogs') diff --git a/examples/widgets/dialogs/findfiles/window.cpp b/examples/widgets/dialogs/findfiles/window.cpp index 780c398ad5..ce53dd8c83 100644 --- a/examples/widgets/dialogs/findfiles/window.cpp +++ b/examples/widgets/dialogs/findfiles/window.cpp @@ -42,51 +42,72 @@ #include "window.h" +//! [17] +enum { absoluteFileNameRole = Qt::UserRole + 1 }; +//! [17] + +//! [18] +static inline QString fileNameOfItem(const QTableWidgetItem *item) +{ + return item->data(absoluteFileNameRole).toString(); +} +//! [18] + +//! [14] +static inline void openFile(const QString &fileName) +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); +} +//! [14] + //! [0] Window::Window(QWidget *parent) : QWidget(parent) { - browseButton = new QPushButton(tr("&Browse..."), this); + QPushButton *browseButton = new QPushButton(tr("&Browse..."), this); connect(browseButton, &QAbstractButton::clicked, this, &Window::browse); findButton = new QPushButton(tr("&Find"), this); connect(findButton, &QAbstractButton::clicked, this, &Window::find); fileComboBox = createComboBox(tr("*")); + connect(fileComboBox->lineEdit(), &QLineEdit::returnPressed, + this, &Window::animateFindClick); textComboBox = createComboBox(); - directoryComboBox = createComboBox(QDir::currentPath()); + connect(textComboBox->lineEdit(), &QLineEdit::returnPressed, + this, &Window::animateFindClick); + directoryComboBox = createComboBox(QDir::toNativeSeparators(QDir::currentPath())); + connect(directoryComboBox->lineEdit(), &QLineEdit::returnPressed, + this, &Window::animateFindClick); - fileLabel = new QLabel(tr("Named:")); - textLabel = new QLabel(tr("Containing text:")); - directoryLabel = new QLabel(tr("In directory:")); filesFoundLabel = new QLabel; createFilesTable(); //! [0] //! [1] - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(fileLabel, 0, 0); + QGridLayout *mainLayout = new QGridLayout(this); + mainLayout->addWidget(new QLabel(tr("Named:")), 0, 0); mainLayout->addWidget(fileComboBox, 0, 1, 1, 2); - mainLayout->addWidget(textLabel, 1, 0); + mainLayout->addWidget(new QLabel(tr("Containing text:")), 1, 0); mainLayout->addWidget(textComboBox, 1, 1, 1, 2); - mainLayout->addWidget(directoryLabel, 2, 0); + mainLayout->addWidget(new QLabel(tr("In directory:")), 2, 0); mainLayout->addWidget(directoryComboBox, 2, 1); mainLayout->addWidget(browseButton, 2, 2); mainLayout->addWidget(filesTable, 3, 0, 1, 3); mainLayout->addWidget(filesFoundLabel, 4, 0, 1, 2); mainLayout->addWidget(findButton, 4, 2); - setLayout(mainLayout); setWindowTitle(tr("Find Files")); - resize(700, 300); + const QRect screenGeometry = QApplication::desktop()->screenGeometry(this); + resize(screenGeometry.width() / 2, screenGeometry.height() / 3); } //! [1] //! [2] void Window::browse() { - QString directory = QFileDialog::getExistingDirectory(this, - tr("Find Files"), QDir::currentPath()); + QString directory = + QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Find Files"), QDir::currentPath())); if (!directory.isEmpty()) { if (directoryComboBox->findText(directory) == -1) @@ -102,14 +123,28 @@ static void updateComboBox(QComboBox *comboBox) comboBox->addItem(comboBox->currentText()); } +//! [13] + +static void findRecursion(const QString &path, const QString &pattern, QStringList *result) +{ + QDir currentDir(path); + const QString prefix = path + QLatin1Char('/'); + foreach (const QString &match, currentDir.entryList(QStringList(pattern), QDir::Files | QDir::NoSymLinks)) + result->append(prefix + match); + foreach (const QString &dir, currentDir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot)) + findRecursion(prefix + dir, pattern, result); +} + +//! [13] //! [3] + void Window::find() { filesTable->setRowCount(0); QString fileName = fileComboBox->currentText(); QString text = textComboBox->currentText(); - QString path = directoryComboBox->currentText(); + QString path = QDir::cleanPath(directoryComboBox->currentText()); //! [3] updateComboBox(fileComboBox); @@ -117,19 +152,21 @@ void Window::find() updateComboBox(directoryComboBox); //! [4] + currentDir = QDir(path); QStringList files; - if (fileName.isEmpty()) - fileName = "*"; - files = currentDir.entryList(QStringList(fileName), - QDir::Files | QDir::NoSymLinks); - + findRecursion(path, fileName.isEmpty() ? QStringLiteral("*") : fileName, &files); if (!text.isEmpty()) files = findFiles(files, text); showFiles(files); } //! [4] +void Window::animateFindClick() +{ + findButton->animateClick(); +} + //! [5] QStringList Window::findFiles(const QStringList &files, const QString &text) { @@ -139,21 +176,26 @@ QStringList Window::findFiles(const QStringList &files, const QString &text) progressDialog.setWindowTitle(tr("Find Files")); //! [5] //! [6] + QMimeDatabase mimeDatabase; QStringList foundFiles; for (int i = 0; i < files.size(); ++i) { progressDialog.setValue(i); - progressDialog.setLabelText(tr("Searching file number %1 of %2...") - .arg(i).arg(files.size())); - qApp->processEvents(); + progressDialog.setLabelText(tr("Searching file number %1 of %n...", 0, files.size()).arg(i)); + QCoreApplication::processEvents(); //! [6] if (progressDialog.wasCanceled()) break; //! [7] - QFile file(currentDir.absoluteFilePath(files[i])); - + const QString fileName = files.at(i); + const QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileName); + if (mimeType.isValid() && !mimeType.inherits(QStringLiteral("text/plain"))) { + qWarning() << "Not searching binary file " << QDir::toNativeSeparators(fileName); + continue; + } + QFile file(fileName); if (file.open(QIODevice::ReadOnly)) { QString line; QTextStream in(&file); @@ -161,7 +203,7 @@ QStringList Window::findFiles(const QStringList &files, const QString &text) if (progressDialog.wasCanceled()) break; line = in.readLine(); - if (line.contains(text)) { + if (line.contains(text, Qt::CaseInsensitive)) { foundFiles << files[i]; break; } @@ -176,13 +218,18 @@ QStringList Window::findFiles(const QStringList &files, const QString &text) void Window::showFiles(const QStringList &files) { for (int i = 0; i < files.size(); ++i) { - QFile file(currentDir.absoluteFilePath(files[i])); - qint64 size = QFileInfo(file).size(); - - QTableWidgetItem *fileNameItem = new QTableWidgetItem(files[i]); + const QString &fileName = files.at(i); + const QString toolTip = QDir::toNativeSeparators(fileName); + const QString relativePath = QDir::toNativeSeparators(currentDir.relativeFilePath(fileName)); + const qint64 size = QFileInfo(fileName).size(); + QTableWidgetItem *fileNameItem = new QTableWidgetItem(relativePath); + fileNameItem->setData(absoluteFileNameRole, QVariant(fileName)); + fileNameItem->setToolTip(toolTip); fileNameItem->setFlags(fileNameItem->flags() ^ Qt::ItemIsEditable); QTableWidgetItem *sizeItem = new QTableWidgetItem(tr("%1 KB") .arg(int((size + 1023) / 1024))); + sizeItem->setData(absoluteFileNameRole, QVariant(fileName)); + sizeItem->setToolTip(toolTip); sizeItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); sizeItem->setFlags(sizeItem->flags() ^ Qt::ItemIsEditable); @@ -191,8 +238,7 @@ void Window::showFiles(const QStringList &files) filesTable->setItem(row, 0, fileNameItem); filesTable->setItem(row, 1, sizeItem); } - filesFoundLabel->setText(tr("%1 file(s) found").arg(files.size()) + - (" (Double click on a file to open it)")); + filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", 0, files.size())); filesFoundLabel->setWordWrap(true); } //! [8] @@ -220,20 +266,43 @@ void Window::createFilesTable() filesTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); filesTable->verticalHeader()->hide(); filesTable->setShowGrid(false); - +//! [15] + filesTable->setContextMenuPolicy(Qt::CustomContextMenu); + connect(filesTable, &QTableWidget::customContextMenuRequested, + this, &Window::contextMenu); connect(filesTable, &QTableWidget::cellActivated, this, &Window::openFileOfItem); +//! [15] } //! [11] + //! [12] void Window::openFileOfItem(int row, int /* column */) { - QTableWidgetItem *item = filesTable->item(row, 0); - - QDesktopServices::openUrl(QUrl::fromLocalFile(currentDir.absoluteFilePath(item->text()))); + const QTableWidgetItem *item = filesTable->item(row, 0); + openFile(fileNameOfItem(item)); } //! [12] +//! [16] +void Window::contextMenu(const QPoint &pos) +{ + const QTableWidgetItem *item = filesTable->itemAt(pos); + if (!item) + return; + QMenu menu; + QAction *copyAction = menu.addAction("Copy Name"); + QAction *openAction = menu.addAction("Open"); + QAction *action = menu.exec(filesTable->mapToGlobal(pos)); + if (!action) + return; + const QString fileName = fileNameOfItem(item); + if (action == copyAction) + QGuiApplication::clipboard()->setText(QDir::toNativeSeparators(fileName)); + else if (action == openAction) + openFile(fileName); +} +//! [16] diff --git a/examples/widgets/dialogs/findfiles/window.h b/examples/widgets/dialogs/findfiles/window.h index 89dd87b83b..119c0fa100 100644 --- a/examples/widgets/dialogs/findfiles/window.h +++ b/examples/widgets/dialogs/findfiles/window.h @@ -63,7 +63,9 @@ public: private slots: void browse(); void find(); + void animateFindClick(); void openFileOfItem(int row, int column); + void contextMenu(const QPoint &pos); private: QStringList findFiles(const QStringList &files, const QString &text); @@ -74,11 +76,7 @@ private: QComboBox *fileComboBox; QComboBox *textComboBox; QComboBox *directoryComboBox; - QLabel *fileLabel; - QLabel *textLabel; - QLabel *directoryLabel; QLabel *filesFoundLabel; - QPushButton *browseButton; QPushButton *findButton; QTableWidget *filesTable; -- cgit v1.2.3