window.cpp 范例文件
dialogs/findfiles/window.cpp
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
#include "window.h"
enum { absoluteFileNameRole = Qt :: UserRole + 1 };
static inline QString fileNameOfItem(const QTableWidgetItem * item)
{
return item- > data(absoluteFileNameRole). toString();
}
static inline void openFile(const QString & fileName)
{
QDesktopServices :: openUrl(QUrl :: fromLocalFile(fileName));
}
Window:: Window(QWidget * parent)
: QWidget (parent)
{
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();
connect(textComboBox- > lineEdit(), & QLineEdit :: returnPressed,
this , & Window:: animateFindClick);
directoryComboBox = createComboBox(QDir :: toNativeSeparators(QDir :: currentPath()));
connect(directoryComboBox- > lineEdit(), & QLineEdit :: returnPressed,
this , & Window:: animateFindClick);
filesFoundLabel = new QLabel ;
createFilesTable();
QGridLayout * mainLayout = new QGridLayout (this );
mainLayout- > addWidget(new QLabel (tr("Named:" )), 0 , 0 );
mainLayout- > addWidget(fileComboBox, 0 , 1 , 1 , 2 );
mainLayout- > addWidget(new QLabel (tr("Containing text:" )), 1 , 0 );
mainLayout- > addWidget(textComboBox, 1 , 1 , 1 , 2 );
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 );
setWindowTitle(tr("Find Files" ));
const QRect screenGeometry = QApplication :: desktop()- > screenGeometry(this );
resize(screenGeometry. width() / 2 , screenGeometry. height() / 3 );
}
void Window:: browse()
{
QString directory =
QDir :: toNativeSeparators(QFileDialog :: getExistingDirectory(this , tr("Find Files" ), QDir :: currentPath()));
if (! directory. isEmpty()) {
if (directoryComboBox- > findText(directory) = = - 1 )
directoryComboBox- > addItem(directory);
directoryComboBox- > setCurrentIndex(directoryComboBox- > findText(directory));
}
}
static void updateComboBox(QComboBox * comboBox)
{
if (comboBox- > findText(comboBox- > currentText()) = = - 1 )
comboBox- > addItem(comboBox- > currentText());
}
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);
}
void Window:: find()
{
filesTable- > setRowCount(0 );
QString fileName = fileComboBox- > currentText();
QString text = textComboBox- > currentText();
QString path = QDir :: cleanPath(directoryComboBox- > currentText());
updateComboBox(fileComboBox);
updateComboBox(textComboBox);
updateComboBox(directoryComboBox);
currentDir = QDir (path);
QStringList files;
findRecursion(path, fileName. isEmpty() ? QStringLiteral ("*" ) : fileName, & files);
if (! text. isEmpty())
files = findFiles(files, text);
showFiles(files);
}
void Window:: animateFindClick()
{
findButton- > animateClick();
}
QStringList Window:: findFiles(const QStringList & files, const QString & text)
{
QProgressDialog progressDialog(this );
progressDialog. setCancelButtonText(tr("&Cancel" ));
progressDialog. setRange(0 , files. size());
progressDialog. setWindowTitle(tr("Find Files" ));
QMimeDatabase mimeDatabase;
QStringList foundFiles;
for (int i = 0 ; i < files. size(); + + i) {
progressDialog. setValue(i);
progressDialog. setLabelText(tr("Searching file number %1 of %n..." , 0 , files. size()). arg(i));
QCoreApplication :: processEvents();
if (progressDialog. wasCanceled())
break ;
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);
while (! in. atEnd()) {
if (progressDialog. wasCanceled())
break ;
line = in. readLine();
if (line. contains(text, Qt :: CaseInsensitive)) {
foundFiles < < files[ i] ;
break ;
}
}
}
}
return foundFiles;
}
void Window:: showFiles(const QStringList & files)
{
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();
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);
int row = filesTable- > rowCount();
filesTable- > insertRow(row);
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- > setWordWrap(true );
}
QComboBox * Window:: createComboBox(const QString & text)
{
QComboBox * comboBox = new QComboBox ;
comboBox- > setEditable(true );
comboBox- > addItem(text);
comboBox- > setSizePolicy(QSizePolicy :: Expanding, QSizePolicy :: Preferred);
return comboBox;
}
void Window:: createFilesTable()
{
filesTable = new QTableWidget (0 , 2 );
filesTable- > setSelectionBehavior(QAbstractItemView :: SelectRows);
QStringList labels;
labels < < tr("Filename" ) < < tr("Size" );
filesTable- > setHorizontalHeaderLabels(labels);
filesTable- > horizontalHeader()- > setSectionResizeMode(0 , QHeaderView :: Stretch);
filesTable- > verticalHeader()- > hide();
filesTable- > setShowGrid(false );
filesTable- > setContextMenuPolicy(Qt :: CustomContextMenu);
connect(filesTable, & QTableWidget :: customContextMenuRequested,
this , & Window:: contextMenu);
connect(filesTable, & QTableWidget :: cellActivated,
this , & Window:: openFileOfItem);
}
void Window:: openFileOfItem(int row, int /* column */ )
{
const QTableWidgetItem * item = filesTable- > item(row, 0 );
openFile(fileNameOfItem(item));
}
void Window:: contextMenu(const QPoint & pos)
{
const QTableWidgetItem * item = filesTable- > itemAt(pos);
if (! item)
return ;
QMenu menu;
#ifndef QT_NO_CLIPBOARD
QAction * copyAction = menu. addAction("Copy Name" );
#endif
QAction * openAction = menu. addAction("Open" );
QAction * action = menu. exec(filesTable- > mapToGlobal(pos));
if (! action)
return ;
const QString fileName = fileNameOfItem(item);
if (action = = openAction)
openFile(fileName);
#ifndef QT_NO_CLIPBOARD
else if (action = = copyAction)
QGuiApplication :: clipboard()- > setText(QDir :: toNativeSeparators(fileName));
#endif
}