Skip to content

Commit

Permalink
Improve the findfiles example: use QDirIterator, etc
Browse files Browse the repository at this point in the history
It hasn't been necessary for a long time now to write the recursive
file-find function manually.  It has just been an obscurely documented
feature of QDirIterator for far too long.

Demonstrate the new QLocale::formattedDataSize() function.

Also sync up the qdoc description of this example with the recent changes.

Change-Id: I9c2bb15bb5ec353d38181b160f0be198774cbea2
Reviewed-by: Robin Burchell <[email protected]>
Reviewed-by: Shawn Rutledge <[email protected]>
  • Loading branch information
ec1oud committed Dec 27, 2017
1 parent c4f397e commit 0c4d31d
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 54 deletions.
57 changes: 23 additions & 34 deletions examples/widgets/dialogs/findfiles/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ static inline void openFile(const QString &fileName)
Window::Window(QWidget *parent)
: QWidget(parent)
{
setWindowTitle(tr("Find Files"));
QPushButton *browseButton = new QPushButton(tr("&Browse..."), this);
connect(browseButton, &QAbstractButton::clicked, this, &Window::browse);
findButton = new QPushButton(tr("&Find"), this);
Expand All @@ -92,9 +93,7 @@ Window::Window(QWidget *parent)
filesFoundLabel = new QLabel;

createFilesTable();
//! [0]

//! [1]
QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(new QLabel(tr("Named:")), 0, 0);
mainLayout->addWidget(fileComboBox, 0, 1, 1, 2);
Expand All @@ -106,12 +105,13 @@ Window::Window(QWidget *parent)
mainLayout->addWidget(filesTable, 3, 0, 1, 3);
mainLayout->addWidget(filesFoundLabel, 4, 0, 1, 2);
mainLayout->addWidget(findButton, 4, 2);
//! [0]

setWindowTitle(tr("Find Files"));
const QRect screenGeometry = QApplication::desktop()->screenGeometry(this);
resize(screenGeometry.width() / 2, screenGeometry.height() / 3);
}
//! [1]
connect(new QShortcut(QKeySequence::Quit, this), &QShortcut::activated,
qApp, &QApplication::quit);
//! [1]
}

//! [2]
void Window::browse()
Expand All @@ -133,41 +133,32 @@ 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 = QDir::cleanPath(directoryComboBox->currentText());
currentDir = QDir(path);
//! [3]

updateComboBox(fileComboBox);
updateComboBox(textComboBox);
updateComboBox(directoryComboBox);

//! [4]

currentDir = QDir(path);
QStringList filter;
if (!fileName.isEmpty())
filter << fileName;
QDirIterator it(path, filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
QStringList files;
findRecursion(path, fileName.isEmpty() ? QStringLiteral("*") : fileName, &files);
while (it.hasNext())
files << it.next();
if (!text.isEmpty())
files = findFiles(files, text);
files.sort();
showFiles(files);
}
//! [4]
Expand Down Expand Up @@ -225,20 +216,18 @@ QStringList Window::findFiles(const QStringList &files, const QString &text)
//! [7]

//! [8]
void Window::showFiles(const QStringList &files)
void Window::showFiles(const QStringList &paths)
{
for (int i = 0; i < files.size(); ++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();
for (const QString &filePath : paths) {
const QString toolTip = QDir::toNativeSeparators(filePath);
const QString relativePath = QDir::toNativeSeparators(currentDir.relativeFilePath(filePath));
const qint64 size = QFileInfo(filePath).size();
QTableWidgetItem *fileNameItem = new QTableWidgetItem(relativePath);
fileNameItem->setData(absoluteFileNameRole, QVariant(fileName));
fileNameItem->setData(absoluteFileNameRole, QVariant(filePath));
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));
QTableWidgetItem *sizeItem = new QTableWidgetItem(QLocale().formattedDataSize(size));
sizeItem->setData(absoluteFileNameRole, QVariant(filePath));
sizeItem->setToolTip(toolTip);
sizeItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
sizeItem->setFlags(sizeItem->flags() ^ Qt::ItemIsEditable);
Expand All @@ -248,7 +237,7 @@ void Window::showFiles(const QStringList &files)
filesTable->setItem(row, 0, fileNameItem);
filesTable->setItem(row, 1, sizeItem);
}
filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", 0, files.size()));
filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", 0, paths.size()));
filesFoundLabel->setWordWrap(true);
}
//! [8]
Expand Down
2 changes: 1 addition & 1 deletion examples/widgets/dialogs/findfiles/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private slots:

private:
QStringList findFiles(const QStringList &files, const QString &text);
void showFiles(const QStringList &files);
void showFiles(const QStringList &paths);
QComboBox *createComboBox(const QString &text = QString());
void createFilesTable();

Expand Down
41 changes: 22 additions & 19 deletions examples/widgets/doc/src/findfiles.qdoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,23 @@

\snippet dialogs/findfiles/window.cpp 0

We create the application's buttons using the private \c
createButton() function. Then we create the comboboxes associated
with the search specifications, using the private \c
createComboBox() function. We also create the application's labels
before we use the private \c createFilesTable() function to create
the table displaying the search results.
We create the widgets to build up the UI, and we add them to a main layout
using QGridLayout. We have, however, put the \c Find and \c Quit buttons
and a stretchable space in a separate \l QHBoxLayout first, to make the
buttons appear in the \c Window widget's bottom right corner.

Alternatively, we could have used Qt Designer to construct a UI file,
and \l {uic} to generate this code.

\snippet dialogs/findfiles/window.cpp 1

Then we add all the widgets to a main layout using QGridLayout. We
have, however, put the \c Find and \c Quit buttons and a
stretchable space in a separate QHBoxLayout first, to make the
buttons appear in the \c Window widget's bottom right corner.
We did not create a \l QMenuBar with a \uicontrol Quit menu item; but we
would still like to have a keyboard shortcut for quitting. Since we
construct a \l QShortcut with \l QKeySequence::Quit, and connect it to
\l QApplication::quit(), on most platforms it will be possible to press
Control-Q to quit (or whichever standard Quit key is configured on that platform).
(On \macos, this is redundant, because every application gets a
\uicontrol Quit menu item automatically; but it helps to make the application portable.)

\snippet dialogs/findfiles/window.cpp 2

Expand Down Expand Up @@ -122,18 +126,16 @@
We use the directory's path to create a QDir; the QDir class
provides access to directory structures and their contents.

\snippet dialogs/findfiles/window.cpp 13

We recursively create a list of the files (contained in the newl
created QDir) that match the specified file name.
We use QDirIterator to iterate over the files that match the
specified file name and build a QStringList of paths.

Then we search through all the files in the list, using the private
\c findFiles() function, eliminating the ones that don't contain
the specified text. And finally, we display the results using the
private \c showFiles() function.
\c findFiles() function, eliminating the ones that don't contain the
specified text. We sort them (because QDirIterator did not). And finally,
we display the results using the private \c showFiles() function.

If the user didn't specify any text, there is no reason to search
through the files, and we display the results immediately.
through the files, so we sort and display the results immediately.

\image findfiles_progress_dialog.png Screenshot of the Progress Dialog

Expand Down Expand Up @@ -196,7 +198,8 @@
the \c find() slot. In the \c showFiles() function we run through
the provided list of file names, adding each relative file name to the
first column in the table widget and retrieving the file's size using
QFileInfo for the second column. For later use, we set
QFileInfo for the second column. We use \l QLocale::formattedDataSize()
to format the file size in a human-readable form. For later use, we set
the absolute path as a data on the QTableWidget using the
the role absoluteFileNameRole defined to be Qt::UserRole + 1.

Expand Down

0 comments on commit 0c4d31d

Please sign in to comment.