Commit cc7fe5ea authored by Daniel Teske's avatar Daniel Teske
Browse files

Project: Simplfy file adding/removing interface



The filetype is only relevant for Qt4 projects. But even for Qt4 projects
the file type is insufficient to decide where the file should be added.
So remove the file type from the interface and let the projectmanagers
themselves figure out what they want to do.

Also fix
Task-number: QTCREATORBUG-9688

Change-Id: I02f7b1cd2e05efaf76e36fb9af34b109d4482f88
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent a98fe15f
......@@ -515,7 +515,7 @@ bool AndroidManager::createAndroidTemplatesIfNecessary(ProjectExplorer::Target *
}
}
if (!androidFiles.isEmpty())
qt4Project->rootProjectNode()->addFiles(ProjectExplorer::UnknownFileType, androidFiles);
qt4Project->rootProjectNode()->addFiles(androidFiles);
int minApiLevel = 4;
if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit()))
......
......@@ -74,39 +74,31 @@ bool AutotoolsProjectNode::removeSubProjects(const QStringList &proFilePaths)
return false;
}
bool AutotoolsProjectNode::addFiles(const FileType fileType,
const QStringList &filePaths,
bool AutotoolsProjectNode::addFiles( const QStringList &filePaths,
QStringList *notAdded)
{
Q_UNUSED(fileType);
Q_UNUSED(filePaths);
Q_UNUSED(notAdded);
return false;
}
bool AutotoolsProjectNode::removeFiles(const FileType fileType,
const QStringList &filePaths,
bool AutotoolsProjectNode::removeFiles(const QStringList &filePaths,
QStringList *notRemoved)
{
Q_UNUSED(fileType);
Q_UNUSED(filePaths);
Q_UNUSED(notRemoved);
return false;
}
bool AutotoolsProjectNode::deleteFiles(const FileType fileType,
const QStringList &filePaths)
bool AutotoolsProjectNode::deleteFiles(const QStringList &filePaths)
{
Q_UNUSED(fileType);
Q_UNUSED(filePaths);
return false;
}
bool AutotoolsProjectNode::renameFile(const FileType fileType,
const QString &filePath,
bool AutotoolsProjectNode::renameFile(const QString &filePath,
const QString &newFilePath)
{
Q_UNUSED(fileType);
Q_UNUSED(filePath);
Q_UNUSED(newFilePath);
return false;
......
......@@ -64,16 +64,10 @@ public:
bool canAddSubProject(const QString &proFilePath) const;
bool addSubProjects(const QStringList &proFilePaths);
bool removeSubProjects(const QStringList &proFilePaths);
bool addFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notAdded = 0);
bool removeFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notRemoved = 0);
bool deleteFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths);
bool renameFile(const ProjectExplorer::FileType fileType,
const QString &filePath,
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
bool deleteFiles(const QStringList &filePaths);
bool renameFile(const QString &filePath,
const QString &newFilePath);
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
......
......@@ -67,32 +67,28 @@ bool CMakeProjectNode::removeSubProjects(const QStringList &proFilePaths)
return false;
}
bool CMakeProjectNode::addFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notAdded)
bool CMakeProjectNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
{
Q_UNUSED(fileType)
Q_UNUSED(filePaths)
Q_UNUSED(notAdded)
return false;
}
bool CMakeProjectNode::removeFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notRemoved)
bool CMakeProjectNode::removeFiles(const QStringList &filePaths, QStringList *notRemoved)
{
Q_UNUSED(fileType)
Q_UNUSED(filePaths)
Q_UNUSED(notRemoved)
return false;
}
bool CMakeProjectNode::deleteFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths)
bool CMakeProjectNode::deleteFiles(const QStringList &filePaths)
{
Q_UNUSED(fileType)
Q_UNUSED(filePaths)
return false;
}
bool CMakeProjectNode::renameFile(const ProjectExplorer::FileType fileType, const QString &filePath, const QString &newFilePath)
bool CMakeProjectNode::renameFile(const QString &filePath, const QString &newFilePath)
{
Q_UNUSED(fileType)
Q_UNUSED(filePath)
Q_UNUSED(newFilePath)
return false;
......
......@@ -48,16 +48,12 @@ public:
virtual bool addSubProjects(const QStringList &proFilePaths);
virtual bool removeSubProjects(const QStringList &proFilePaths);
virtual bool addFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
virtual bool addFiles( const QStringList &filePaths,
QStringList *notAdded = 0);
virtual bool removeFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
virtual bool removeFiles(const QStringList &filePaths,
QStringList *notRemoved = 0);
virtual bool deleteFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths);
virtual bool renameFile(const ProjectExplorer::FileType fileType,
const QString &filePath,
virtual bool deleteFiles(const QStringList &filePaths);
virtual bool renameFile(const QString &filePath,
const QString &newFilePath);
virtual QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
};
......
......@@ -259,37 +259,28 @@ bool GenericProjectNode::removeSubProjects(const QStringList &proFilePaths)
return false;
}
bool GenericProjectNode::addFiles(const FileType fileType,
const QStringList &filePaths, QStringList *notAdded)
bool GenericProjectNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
{
Q_UNUSED(fileType)
Q_UNUSED(notAdded)
return m_project->addFiles(filePaths);
}
bool GenericProjectNode::removeFiles(const FileType fileType,
const QStringList &filePaths, QStringList *notRemoved)
bool GenericProjectNode::removeFiles(const QStringList &filePaths, QStringList *notRemoved)
{
Q_UNUSED(fileType)
Q_UNUSED(notRemoved)
return m_project->removeFiles(filePaths);
}
bool GenericProjectNode::deleteFiles(const FileType fileType,
const QStringList &filePaths)
bool GenericProjectNode::deleteFiles(const QStringList &filePaths)
{
Q_UNUSED(fileType)
Q_UNUSED(filePaths)
return false;
}
bool GenericProjectNode::renameFile(const FileType fileType,
const QString &filePath, const QString &newFilePath)
bool GenericProjectNode::renameFile(const QString &filePath, const QString &newFilePath)
{
Q_UNUSED(fileType)
return m_project->renameFile(filePath, newFilePath);
}
......
......@@ -62,19 +62,10 @@ public:
bool addSubProjects(const QStringList &proFilePaths);
bool removeSubProjects(const QStringList &proFilePaths);
bool addFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notAdded = 0);
bool removeFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notRemoved = 0);
bool deleteFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths);
bool renameFile(const ProjectExplorer::FileType fileType,
const QString &filePath,
const QString &newFilePath);
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
bool deleteFiles(const QStringList &filePaths);
bool renameFile(const QString &filePath, const QString &newFilePath);
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
......
......@@ -2844,16 +2844,9 @@ void ProjectExplorerPlugin::addExistingFiles(ProjectNode *projectNode, const QSt
const QString dir = directoryFor(projectNode);
QStringList fileNames = filePaths;
QHash<FileType, QString> fileTypeToFiles;
foreach (const QString &fileName, fileNames) {
FileType fileType = typeForFileName(Core::ICore::mimeDatabase(), QFileInfo(fileName));
fileTypeToFiles.insertMulti(fileType, fileName);
}
QStringList notAdded;
foreach (const FileType type, fileTypeToFiles.uniqueKeys()) {
projectNode->addFiles(type, fileTypeToFiles.values(type), &notAdded);
}
projectNode->addFiles(fileNames, &notAdded);
if (!notAdded.isEmpty()) {
QString message = tr("Could not add following files to project %1:\n").arg(projectNode->displayName());
QString files = notAdded.join(QString(QLatin1Char('\n')));
......@@ -2919,7 +2912,7 @@ void ProjectExplorerPlugin::removeFile()
ProjectNode *projectNode = fileNode->projectNode();
Q_ASSERT(projectNode);
if (!projectNode->removeFiles(fileNode->fileType(), QStringList(filePath))) {
if (!projectNode->removeFiles(QStringList(filePath))) {
QMessageBox::warning(Core::ICore::mainWindow(), tr("Removing File Failed"),
tr("Could not remove file %1 from project %2.").arg(filePath).arg(projectNode->displayName()));
return;
......@@ -2947,7 +2940,7 @@ void ProjectExplorerPlugin::deleteFile()
ProjectNode *projectNode = fileNode->projectNode();
QTC_ASSERT(projectNode, return);
projectNode->deleteFiles(fileNode->fileType(), QStringList(filePath));
projectNode->deleteFiles(QStringList(filePath));
Core::DocumentManager::expectFileChange(filePath);
if (Core::IVersionControl *vc =
......@@ -2988,7 +2981,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
if (Core::FileUtils::renameFile(orgFilePath, newFilePath)) {
// Tell the project plugin about rename
ProjectNode *projectNode = fileNode->projectNode();
if (!projectNode->renameFile(fileNode->fileType(), orgFilePath, newFilePath)) {
if (!projectNode->renameFile(orgFilePath, newFilePath)) {
QMessageBox::warning(Core::ICore::mainWindow(), tr("Project Editing Failed"),
tr("The file %1 was renamed to %2, but the project file %3 could not be automatically changed.")
.arg(orgFilePath)
......
......@@ -472,8 +472,6 @@ bool ProjectFileWizardExtension::processProject(
const QList<Core::GeneratedFile> &files,
bool *removeOpenProjectAttribute, QString *errorMessage)
{
typedef QMultiMap<FileType, QString> TypeFileMap;
*removeOpenProjectAttribute = false;
QString generatedProject = generatedProjectFilePath(files);
......@@ -491,22 +489,15 @@ bool ProjectFileWizardExtension::processProject(
}
*removeOpenProjectAttribute = true;
} else {
// Split into lists by file type and bulk-add them.
TypeFileMap typeFileMap;
const Core::MimeDatabase *mdb = Core::ICore::mimeDatabase();
foreach (const Core::GeneratedFile &generatedFile, files) {
const QString path = generatedFile.path();
typeFileMap.insert(typeForFileName(mdb, path), path);
}
foreach (FileType type, typeFileMap.uniqueKeys()) {
const QStringList typeFiles = typeFileMap.values(type);
if (!project->addFiles(type, typeFiles)) {
QStringList filePaths;
foreach (const Core::GeneratedFile &generatedFile, files)
filePaths << generatedFile.path();
if (!project->addFiles(filePaths)) {
*errorMessage = tr("Failed to add one or more files to project\n'%1' (%2).").
arg(project->path(), typeFiles.join(QString(QLatin1Char(','))));
arg(project->path(), filePaths.join(QString(QLatin1Char(','))));
return false;
}
}
}
return true;
}
......
......@@ -837,27 +837,3 @@ NodesWatcher::NodesWatcher(QObject *parent)
: QObject(parent)
{
}
// TODO Maybe put this in core, so that all can benefit
FileType typeForFileName(const Core::MimeDatabase *db, const QFileInfo &file)
{
const Core::MimeType mt = db->findByFile(file);
if (!mt)
return UnknownFileType;
const QString typeName = mt.type();
if (typeName == QLatin1String(Constants::CPP_SOURCE_MIMETYPE)
|| typeName == QLatin1String(Constants::C_SOURCE_MIMETYPE))
return SourceType;
if (typeName == QLatin1String(Constants::CPP_HEADER_MIMETYPE)
|| typeName == QLatin1String(Constants::C_HEADER_MIMETYPE))
return HeaderType;
if (typeName == QLatin1String(Constants::RESOURCE_MIMETYPE))
return ResourceType;
if (typeName == QLatin1String(Constants::FORM_MIMETYPE))
return FormType;
if (mt.subClassesOf().contains(QLatin1String(Constants::QML_MIMETYPE))
|| typeName == QLatin1String(Constants::QML_MIMETYPE))
return QMLType;
return UnknownFileType;
}
......@@ -214,18 +214,10 @@ public:
virtual bool removeSubProjects(const QStringList &proFilePaths) = 0;
virtual bool addFiles(const FileType fileType,
const QStringList &filePaths,
QStringList *notAdded = 0) = 0;
// TODO: Maybe remove fileType, can be detected by project
virtual bool removeFiles(const FileType fileType,
const QStringList &filePaths,
QStringList *notRemoved = 0) = 0;
virtual bool deleteFiles(const FileType fileType,
const QStringList &filePaths) = 0;
virtual bool renameFile(const FileType fileType,
const QString &filePath,
const QString &newFilePath) = 0;
virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0) = 0;
virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0) = 0;
virtual bool deleteFiles(const QStringList &filePaths) = 0;
virtual bool renameFile(const QString &filePath, const QString &newFilePath) = 0;
// by default returns false
virtual bool deploysFolder(const QString &folder) const;
......@@ -343,7 +335,4 @@ private:
} // namespace ProjectExplorer
// HACK: THERE SHOULD BE ONE PLACE TO MAKE THE FILE ENDING->FILE TYPE ASSOCIATION
ProjectExplorer::FileType typeForFileName(const Core::MimeDatabase *db, const QFileInfo &file);
#endif // PROJECTNODES_H
......@@ -286,32 +286,28 @@ bool QbsBaseProjectNode::removeSubProjects(const QStringList &proFilePaths)
return false;
}
bool QbsBaseProjectNode::addFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notAdded)
bool QbsBaseProjectNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
{
Q_UNUSED(fileType);
Q_UNUSED(filePaths);
Q_UNUSED(notAdded);
return false;
}
bool QbsBaseProjectNode::removeFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notRemoved)
bool QbsBaseProjectNode::removeFiles(const QStringList &filePaths, QStringList *notRemoved)
{
Q_UNUSED(fileType);
Q_UNUSED(filePaths);
Q_UNUSED(notRemoved);
return false;
}
bool QbsBaseProjectNode::deleteFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths)
bool QbsBaseProjectNode::deleteFiles(const QStringList &filePaths)
{
Q_UNUSED(fileType);
Q_UNUSED(filePaths);
return false;
}
bool QbsBaseProjectNode::renameFile(const ProjectExplorer::FileType fileType, const QString &filePath, const QString &newFilePath)
bool QbsBaseProjectNode::renameFile(const QString &filePath, const QString &newFilePath)
{
Q_UNUSED(fileType);
Q_UNUSED(filePath);
Q_UNUSED(newFilePath);
return false;
......
......@@ -90,17 +90,10 @@ public:
bool removeSubProjects(const QStringList &proFilePaths);
bool addFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notAdded = 0);
bool removeFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notRemoved = 0);
bool deleteFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths);
bool renameFile(const ProjectExplorer::FileType fileType,
const QString &filePath,
const QString &newFilePath);
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
bool deleteFiles(const QStringList &filePaths);
bool renameFile(const QString &filePath, const QString &newFilePath);
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
......
......@@ -198,26 +198,22 @@ bool QmlProjectNode::removeSubProjects(const QStringList &proFilePaths)
return false;
}
bool QmlProjectNode::addFiles(const ProjectExplorer::FileType /*fileType*/,
const QStringList &filePaths, QStringList * /*notAdded*/)
bool QmlProjectNode::addFiles(const QStringList &filePaths, QStringList * /*notAdded*/)
{
return m_project->addFiles(filePaths);
}
bool QmlProjectNode::removeFiles(const ProjectExplorer::FileType /*fileType*/,
const QStringList & /*filePaths*/, QStringList * /*notRemoved*/)
bool QmlProjectNode::removeFiles(const QStringList & /*filePaths*/, QStringList * /*notRemoved*/)
{
return false;
}
bool QmlProjectNode::deleteFiles(const ProjectExplorer::FileType /*fileType*/,
const QStringList & /*filePaths*/)
bool QmlProjectNode::deleteFiles(const QStringList & /*filePaths*/)
{
return true;
}
bool QmlProjectNode::renameFile(const ProjectExplorer::FileType /*fileType*/,
const QString & /*filePath*/, const QString & /*newFilePath*/)
bool QmlProjectNode::renameFile(const QString & /*filePath*/, const QString & /*newFilePath*/)
{
return true;
}
......
......@@ -63,20 +63,10 @@ public:
virtual bool addSubProjects(const QStringList &proFilePaths);
virtual bool removeSubProjects(const QStringList &proFilePaths);
virtual bool addFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notAdded = 0);
virtual bool removeFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths,
QStringList *notRemoved = 0);
virtual bool deleteFiles(const ProjectExplorer::FileType fileType,
const QStringList &filePaths);
virtual bool renameFile(const ProjectExplorer::FileType fileType,
const QString &filePath,
const QString &newFilePath);
virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
virtual bool deleteFiles(const QStringList &filePaths);
virtual bool renameFile(const QString &filePath, const QString &newFilePath);
virtual QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
......
......@@ -52,6 +52,7 @@
#include <qtsupport/qtkitinformation.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <cpptools/cpptoolsconstants.h>
#include <utils/hostosinfo.h>
#include <utils/stringutils.h>
......@@ -921,7 +922,7 @@ bool Qt4PriFileNode::addSubProjects(const QStringList &proFilePaths)
uniqueProFilePaths.append(simplifyProFilePath(proFile));
QStringList failedFiles;
changeFiles(ProjectExplorer::ProjectFileType, uniqueProFilePaths, &failedFiles, AddToProFile);
changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), uniqueProFilePaths, &failedFiles, AddToProFile);
return failedFiles.isEmpty();
}
......@@ -929,20 +930,19 @@ bool Qt4PriFileNode::addSubProjects(const QStringList &proFilePaths)
bool Qt4PriFileNode::removeSubProjects(const QStringList &proFilePaths)
{
QStringList failedOriginalFiles;
changeFiles(ProjectExplorer::ProjectFileType, proFilePaths, &failedOriginalFiles, RemoveFromProFile);
changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), proFilePaths, &failedOriginalFiles, RemoveFromProFile);
QStringList simplifiedProFiles;
foreach (const QString &proFile, failedOriginalFiles)
simplifiedProFiles.append(simplifyProFilePath(proFile));
QStringList failedSimplifiedFiles;
changeFiles(ProjectExplorer::ProjectFileType, simplifiedProFiles, &failedSimplifiedFiles, RemoveFromProFile);
changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), simplifiedProFiles, &failedSimplifiedFiles, RemoveFromProFile);
return failedSimplifiedFiles.isEmpty();
}
bool Qt4PriFileNode::addFiles(const FileType fileType, const QStringList &filePaths,
QStringList *notAdded)
bool Qt4PriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
{
// If a file is already referenced in the .pro file then we don't add them.
// That ignores scopes and which variable was used to reference the file
......@@ -953,9 +953,21 @@ bool Qt4PriFileNode::addFiles(const FileType fileType, const QStringList &filePa
accept(&visitor);
const QStringList &allFiles = visitor.filePaths();
typedef QMap<QString, QStringList> TypeFileMap;
// Split into lists by file type and bulk-add them.
TypeFileMap typeFileMap;
const Core::MimeDatabase *mdb = Core::ICore::mimeDatabase();
foreach (const QString file, filePaths) {
const Core::MimeType mt = mdb->findByFile(file);
typeFileMap[mt.type()] << file;
}
QStringList failedFiles;
foreach (const QString &type, typeFileMap.keys()) {
const QStringList typeFiles = typeFileMap.value(type);
QStringList qrcFiles; // the list of qrc files referenced from ui files
if (fileType == ProjectExplorer::FormType) {
foreach (const QString &formFile, filePaths) {
if (type == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE)) {
foreach (const QString &formFile, typeFiles) {
QStringList resourceFiles = formResources(formFile);
foreach (const QString &resourceFile, resourceFiles)
if (!qrcFiles.contains(resourceFile))
......@@ -970,51 +982,74 @@ bool Qt4PriFileNode::addFiles(const FileType fileType, const QStringList &filePa
}
QStringList uniqueFilePaths;
foreach (const QString &file, filePaths) {
foreach (const QString &file, typeFiles) {
if (!allFiles.contains(file))
uniqueFilePaths.append(file);
}
QStringList failedFiles;
changeFiles(fileType, uniqueFilePaths, &failedFiles, AddToProFile);
changeFiles(type, uniqueFilePaths, &failedFiles, AddToProFile);
if (notAdded)
*notAdded = failedFiles;
changeFiles(ProjectExplorer::ResourceType, uniqueQrcFiles, &failedFiles, AddToProFile);
*notAdded += failedFiles;
changeFiles(QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE), uniqueQrcFiles, &failedFiles, AddToProFile);
if (notAdded)
*notAdded += failedFiles;
}
return failedFiles.isEmpty();
}
bool Qt4PriFileNode::removeFiles(const FileType fileType, const QStringList &filePaths,
bool Qt4PriFileNode::removeFiles(const QStringList &filePaths,
QStringList *notRemoved)
{
QStringList failedFiles;
changeFiles(fileType, filePaths, &failedFiles, RemoveFromProFile);
typedef QMap<QString, QStringList> TypeFileMap;
// Split into lists by file type and bulk-add them.
TypeFileMap typeFileMap;
const Core::MimeDatabase *mdb = Core::ICore::mimeDatabase();
foreach (const QString file, filePaths) {
const Core::MimeType mt = mdb->findByFile(file);
typeFileMap[mt.type()] << file;
}
foreach (const QString &type, typeFileMap.keys()) {
const QStringList typeFiles = typeFileMap.value(type);
changeFiles(type, typeFiles, &failedFiles, RemoveFromProFile);
if (notRemoved)
*notRemoved = failedFiles;
}
return failedFiles.isEmpty();