diff --git a/src/plugins/qmldesigner/checkablefiletreeitem.cpp b/src/plugins/qmldesigner/checkablefiletreeitem.cpp index ab1834133ed..42a788b8d69 100644 --- a/src/plugins/qmldesigner/checkablefiletreeitem.cpp +++ b/src/plugins/qmldesigner/checkablefiletreeitem.cpp @@ -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); diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.cpp b/src/plugins/qmldesigner/cmakegeneratordialog.cpp index 43820b13a15..a972147051d 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialog.cpp +++ b/src/plugins/qmldesigner/cmakegeneratordialog.cpp @@ -27,6 +27,8 @@ #include "cmakegeneratordialogtreemodel.h" #include "generatecmakelistsconstants.h" +#include + #include #include #include @@ -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 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)); + } + } +} + } } diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.h b/src/plugins/qmldesigner/cmakegeneratordialog.h index 1a5b947348d..cb04eec18d4 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialog.h +++ b/src/plugins/qmldesigner/cmakegeneratordialog.h @@ -32,6 +32,7 @@ #include #include +#include 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; }; } diff --git a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp b/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp index 6c118d86bb0..bb0ba02c8f7 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp +++ b/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.cpp @@ -27,6 +27,8 @@ #include "generatecmakelistsconstants.h" #include "checkablefiletreeitem.h" +#include + 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()); + 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 CMakeGeneratorDialogTreeModel::items() const +{ +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + QList standardItems = findItems("*", Qt::MatchWildcard | Qt::MatchRecursive); +#else + QList standardItems = findItems(".*", Qt::MatchRegularExpression | Qt::MatchRecursive); +#endif + QList checkableItems; + for (QStandardItem *item : standardItems) + checkableItems.append(static_cast(item)); + + return checkableItems; +} const QList CMakeGeneratorDialogTreeModel::checkedItems() const { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QList allItems = findItems("*", Qt::MatchWildcard); -#else - QList allItems = findItems(".*", Qt::MatchRegularExpression); -#endif + QList allItems = items(); + QList checkedItems; - for (QStandardItem *standardItem : allItems) { - CheckableFileTreeItem *item = static_cast(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); } } diff --git a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h b/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h index f890d1d4737..79f358a801f 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h +++ b/src/plugins/qmldesigner/cmakegeneratordialogtreemodel.h @@ -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 items() const; const QList 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; diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index 7359c6fb778..3cadb3a9b07 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -166,67 +166,35 @@ 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) { - QString fatalList; - QString nonFatalList; - - if (error & MissingContentDir) - fatalList.append(QString(DIRNAME_CONTENT) + "\n"); - if (error & MissingAppMainQml) - fatalList.append(QString(DIRNAME_CONTENT) - + QDir::separator() - + QString(FILENAME_APPMAINQML) - + "\n"); - if (error & MissingCppDir) - fatalList.append(QString(DIRNAME_CPP) + "\n"); - 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) { + QString fatalList; + + if (error & MissingContentDir) + fatalList.append(QString(DIRNAME_CONTENT) + "\n"); + if (error & MissingAppMainQml) + fatalList.append(QString(DIRNAME_CONTENT) + + QDir::separator() + + QString(FILENAME_APPMAINQML) + + "\n"); + if (error & MissingCppDir) + fatalList.append(QString(DIRNAME_CPP) + "\n"); + if (error & MissingImportDir) + fatalList.append(QString(DIRNAME_IMPORT) + "\n"); + 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);