Improve the findfiles example: use QDirIterator, etc
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 <robin.burchell@crimson.no> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
c4f397ee11
commit
0c4d31d8c9
@ -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);
|
||||
@ -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);
|
||||
@ -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()
|
||||
@ -133,21 +133,7 @@ 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);
|
||||
@ -155,6 +141,7 @@ void Window::find()
|
||||
QString fileName = fileComboBox->currentText();
|
||||
QString text = textComboBox->currentText();
|
||||
QString path = QDir::cleanPath(directoryComboBox->currentText());
|
||||
currentDir = QDir(path);
|
||||
//! [3]
|
||||
|
||||
updateComboBox(fileComboBox);
|
||||
@ -162,12 +149,16 @@ void Window::find()
|
||||
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]
|
||||
@ -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);
|
||||
@ -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]
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user