CMake generator: Integrate warnings in confirmation dialog

Task-number: QDS-5856
Change-Id: If95515ee0921598623a024fd7bd8fe8ef3482aa9
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Tapani Mattila
2021-12-27 12:18:58 +02:00
parent 72c3d675a0
commit 85dab69262
6 changed files with 133 additions and 66 deletions

View File

@@ -33,7 +33,7 @@ CheckableFileTreeItem::CheckableFileTreeItem(const FilePath &filePath)
:QStandardItem(filePath.toString())
{
Qt::ItemFlags itemFlags = flags();
if (isFile())
if (!isDir())
itemFlags |= Qt::ItemIsUserCheckable;
itemFlags &= ~(Qt::ItemIsEditable | Qt::ItemIsSelectable);
setFlags(itemFlags);

View File

@@ -27,6 +27,8 @@
#include "cmakegeneratordialogtreemodel.h"
#include "generatecmakelistsconstants.h"
#include <utils/utilsicons.h>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QLayout>
@@ -39,8 +41,15 @@ namespace QmlDesigner {
namespace GenerateCmake {
CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePaths &files)
: QDialog()
: QDialog(),
m_rootDir(rootDir),
m_files(files)
{
setWindowTitle(QCoreApplication::translate("QmlDesigner::GenerateCmake",
"Select Files to Generate"));
m_model = new CMakeGeneratorDialogTreeModel(rootDir, files, this);
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
@@ -51,16 +60,20 @@ CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePa
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
m_model = new CMakeGeneratorDialogTreeModel(rootDir, files, this);
connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText);
QTreeView *tree = new QTreeView(this);
tree->setModel(m_model);
tree->expandAll();
tree->setHeaderHidden(true);
tree->setItemsExpandable(false);
layout->addWidget(tree);
m_notifications = new QTextEdit(this);
m_warningIcon = Utils::Icons::WARNING.pixmap();
refreshNotificationText();
layout->addWidget(tree, 2);
layout->addWidget(m_notifications, 1);
layout->addWidget(buttons);
}
@@ -76,5 +89,47 @@ FilePaths CmakeGeneratorDialog::getFilePaths()
return paths;
}
const QString FILE_CREATE_NOTIFICATION = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"File %1 will be created.\n");
const QString FILE_OVERWRITE_NOTIFICATION = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"File %1 will be overwritten.\n");
void CmakeGeneratorDialog::refreshNotificationText()
{
QTextDocument *document = m_notifications->document();
document->clear();
document->addResource(QTextDocument::ImageResource, QUrl("cmakegendialog://warningicon"), m_warningIcon);
QTextCursor cursor = m_notifications->textCursor();
QTextImageFormat iformat;
iformat.setName("cmakegendialog://warningicon");
QList<CheckableFileTreeItem*> nodes = m_model->items();
for (CheckableFileTreeItem *node : nodes) {
if (!m_files.contains(node->toFilePath()))
continue;
if (!node->toFilePath().exists() && node->isChecked()) {
QString relativePath = QString(node->toFilePath().toString()).remove(m_rootDir.toString()+'/');
cursor.insertText(QString(FILE_CREATE_NOTIFICATION).arg(relativePath));
}
}
if (!document->toPlainText().isEmpty())
cursor.insertBlock();
for (CheckableFileTreeItem *node : nodes) {
if (!m_files.contains(node->toFilePath()))
continue;
if (node->toFilePath().exists() && node->isChecked()) {
QString relativePath = node->toFilePath().relativePath(m_rootDir).toString();
cursor.insertImage(iformat);
cursor.insertText(QString(FILE_OVERWRITE_NOTIFICATION).arg(relativePath));
}
}
}
}
}

View File

@@ -32,6 +32,7 @@
#include <utils/fileutils.h>
#include <QDialog>
#include <QTextEdit>
namespace QmlDesigner {
@@ -39,12 +40,21 @@ namespace GenerateCmake {
class CmakeGeneratorDialog : public QDialog
{
Q_OBJECT
public:
CmakeGeneratorDialog(const Utils::FilePath &rootDir, const Utils::FilePaths &files);
Utils::FilePaths getFilePaths();
public slots:
void refreshNotificationText();
private:
CMakeGeneratorDialogTreeModel *m_model;
QTextEdit *m_notifications;
QVariant m_warningIcon;
Utils::FilePath m_rootDir;
Utils::FilePaths m_files;
};
}

View File

@@ -27,6 +27,8 @@
#include "generatecmakelistsconstants.h"
#include "checkablefiletreeitem.h"
#include <utils/utilsicons.h>
using namespace Utils;
namespace QmlDesigner {
@@ -51,7 +53,7 @@ QVariant CMakeGeneratorDialogTreeModel::data(const QModelIndex &index, int role)
if (index.isValid()) {
const CheckableFileTreeItem *node = constNodeForIndex(index);
if (role == Qt::CheckStateRole) {
if (node->isFile())
if (!node->isDir())
return node->isChecked() ? Qt::Checked : Qt::Unchecked;
return {};
}
@@ -60,8 +62,20 @@ QVariant CMakeGeneratorDialogTreeModel::data(const QModelIndex &index, int role)
return QVariant(fullPath.fileName());
}
else if (role == Qt::DecorationRole) {
if (!node->isFile())
if (node->isFile())
return Utils::Icons::WARNING.icon();
if (node->isDir())
return m_icons->icon(QFileIconProvider::Folder);
else
return Utils::Icons::NEWFILE.icon();
}
else if (role == Qt::ToolTipRole) {
if (node->isFile())
return QCoreApplication::translate("QmlDesigner::GenerateCmake",
"This file already exists and will be overwritten.");
if (!node->toFilePath().exists())
return QCoreApplication::translate("QmlDesigner::GenerateCmake",
"This file or folder will be created.");
}
}
@@ -74,6 +88,7 @@ bool CMakeGeneratorDialogTreeModel::setData(const QModelIndex &index, const QVar
CheckableFileTreeItem *node = nodeForIndex(index);
if (role == Qt::CheckStateRole) {
node->setChecked(value.value<bool>());
emit checkedStateChanged(node);
return true;
}
}
@@ -81,17 +96,26 @@ bool CMakeGeneratorDialogTreeModel::setData(const QModelIndex &index, const QVar
return QStandardItemModel::setData(index, value, role);;
}
const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::items() const
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QList<QStandardItem*> standardItems = findItems("*", Qt::MatchWildcard | Qt::MatchRecursive);
#else
QList<QStandardItem*> standardItems = findItems(".*", Qt::MatchRegularExpression | Qt::MatchRecursive);
#endif
QList<CheckableFileTreeItem*> checkableItems;
for (QStandardItem *item : standardItems)
checkableItems.append(static_cast<CheckableFileTreeItem*>(item));
return checkableItems;
}
const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::checkedItems() const
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QList<QStandardItem*> allItems = findItems("*", Qt::MatchWildcard);
#else
QList<QStandardItem*> allItems = findItems(".*", Qt::MatchRegularExpression);
#endif
QList<CheckableFileTreeItem*> allItems = items();
QList<CheckableFileTreeItem*> checkedItems;
for (QStandardItem *standardItem : allItems) {
CheckableFileTreeItem *item = static_cast<CheckableFileTreeItem*>(standardItem);
for (CheckableFileTreeItem *item : allItems) {
if (item->isChecked())
checkedItems.append(item);
}
@@ -133,6 +157,8 @@ void CMakeGeneratorDialogTreeModel::createNodes(const FilePaths &candidates, QSt
if (file.parentDir() == thisDir) {
CheckableFileTreeItem *fileNode = new CheckableFileTreeItem(file);
fileNode->setChecked(checkedByDefault(file));
if (!file.exists())
fileNode->setChecked(true);
parent->appendRow(fileNode);
}
}

View File

@@ -38,6 +38,8 @@ namespace GenerateCmake {
class CMakeGeneratorDialogTreeModel : public QStandardItemModel
{
Q_OBJECT
public:
CMakeGeneratorDialogTreeModel(const Utils::FilePath &rootDir,
const Utils::FilePaths &files, QObject *parent = nullptr);
@@ -46,10 +48,14 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
const QList<CheckableFileTreeItem*> items() const;
const QList<CheckableFileTreeItem*> checkedItems() const;
const CheckableFileTreeItem* constNodeForIndex(const QModelIndex &index) const;
CheckableFileTreeItem* nodeForIndex(const QModelIndex &index);
signals:
void checkedStateChanged(CheckableFileTreeItem *item);
protected:
bool checkedByDefault(const Utils::FilePath &file) const;
Utils::FilePath rootDir;

View File

@@ -166,17 +166,19 @@ void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles)
const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1");
const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
//const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
// "The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"Cannot Generate CMake Files");
const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"Problems with Generating CMake Files");
//const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
// "Problems with Generating CMake Files");
void showProjectDirErrorDialog(int error)
{
bool isFatal = isErrorFatal(error);
if (isFatal) {
QString fatalList;
QString nonFatalList;
if (error & MissingContentDir)
fatalList.append(QString(DIRNAME_CONTENT) + "\n");
@@ -190,43 +192,9 @@ void showProjectDirErrorDialog(int error)
if (error & MissingImportDir)
fatalList.append(QString(DIRNAME_IMPORT) + "\n");
if (error & MissingAssetImportDir)
nonFatalList.append(QString(DIRNAME_ASSET) + "\n");
if (error & MissingMainCMake)
nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n");
if (error & MissingQmlModules)
nonFatalList.append(QString(FILENAME_MODULES) + "\n");
if (error & MissingMainQml)
nonFatalList.append(QString(FILENAME_MAINQML) + "\n");
if (error & MissingMainCpp)
nonFatalList.append(QString(DIRNAME_CPP)
+ QDir::separator()
+ QString(FILENAME_MAINCPP)
+ "\n");
if (error & MissingMainCppHeader)
nonFatalList.append(QString(DIRNAME_CPP)
+ QDir::separator()
+ QString(FILENAME_MAINCPP_HEADER)
+ "\n");
if (error & MissingEnvHeader)
nonFatalList.append(QString(DIRNAME_CPP)
+ QDir::separator()
+ QString(FILENAME_ENV_HEADER)
+ "\n");
bool isFatal = isErrorFatal(error);
if (isFatal) {
QMessageBox::critical(nullptr,
WARNING_TITLE_FATAL,
WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList + nonFatalList));
}
else {
QMessageBox::warning(nullptr,
WARNING_TITLE_NONFATAL,
WARNING_MISSING_STRUCTURE_NONFATAL.arg(nonFatalList));
WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList));
}
}
@@ -237,6 +205,8 @@ bool showConfirmationDialog(const Utils::FilePath &rootDir)
files.append(file.filePath);
CmakeGeneratorDialog dialog(rootDir, files);
dialog.setMinimumWidth(600);
dialog.setMinimumHeight(640);
if (dialog.exec()) {
Utils::FilePaths confirmedFiles = dialog.getFilePaths();
removeUnconfirmedQueuedFiles(confirmedFiles);