diff options
Diffstat (limited to 'src/plugins/projectexplorer/projectexplorer.cpp')
-rw-r--r-- | src/plugins/projectexplorer/projectexplorer.cpp | 245 |
1 files changed, 154 insertions, 91 deletions
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index c4a15ec526..8a7d3238ef 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -33,6 +33,7 @@ #include "compileoutputwindow.h" #include "configtaskhandler.h" #include "customexecutablerunconfiguration.h" +#include "customparserssettingspage.h" #include "customwizard/customwizard.h" #include "deployablefile.h" #include "deployconfiguration.h" @@ -118,7 +119,6 @@ #include <coreplugin/fileutils.h> #include <coreplugin/findplaceholder.h> #include <coreplugin/icore.h> -#include <coreplugin/id.h> #include <coreplugin/idocument.h> #include <coreplugin/idocumentfactory.h> #include <coreplugin/imode.h> @@ -146,16 +146,17 @@ #include <utils/stringutils.h> #include <utils/utilsicons.h> -#include <QFileInfo> -#include <QSettings> - #include <QAction> +#include <QActionGroup> #include <QApplication> #include <QDir> #include <QFileDialog> +#include <QFileInfo> #include <QInputDialog> #include <QMenu> #include <QMessageBox> +#include <QPair> +#include <QSettings> #include <QThreadPool> #include <QTimer> @@ -182,6 +183,7 @@ using namespace Core; using namespace ProjectExplorer::Internal; +using namespace Utils; namespace ProjectExplorer { @@ -282,6 +284,9 @@ const char SEPARATE_DEBUG_INFO_SETTINGS_KEY[] = "ProjectExplorer/Settings/Separa const char QML_DEBUGGING_SETTINGS_KEY[] = "ProjectExplorer/Settings/QmlDebugging"; const char QT_QUICK_COMPILER_SETTINGS_KEY[] = "ProjectExplorer/Settings/QtQuickCompiler"; +const char CUSTOM_PARSER_COUNT_KEY[] = "ProjectExplorer/Settings/CustomParserCount"; +const char CUSTOM_PARSER_PREFIX_KEY[] = "ProjectExplorer/Settings/CustomParser"; + } // namespace Constants @@ -390,7 +395,7 @@ public: void updateContextMenuActions(); void updateLocationSubMenus(); - void executeRunConfiguration(RunConfiguration *, Core::Id mode); + void executeRunConfiguration(RunConfiguration *, Utils::Id mode); QPair<bool, QString> buildSettingsEnabledForSession(); QPair<bool, QString> buildSettingsEnabled(const Project *pro); @@ -452,7 +457,7 @@ public: void doUpdateRunActions(); - void currentModeChanged(Core::Id mode, Core::Id oldMode); + void currentModeChanged(Utils::Id mode, Utils::Id oldMode); void updateWelcomePage(); @@ -519,6 +524,7 @@ public: QAction *m_openFileAction; QAction *m_projectTreeCollapseAllAction; QAction *m_projectTreeExpandAllAction; + QAction *m_projectTreeExpandNodeAction = nullptr; Utils::ParameterAction *m_closeProjectFilesActionFileMenu; Utils::ParameterAction *m_closeProjectFilesActionContextMenu; QAction *m_searchOnFileSystem; @@ -549,9 +555,10 @@ public: MiniProjectTargetSelector * m_targetSelector; ProjectExplorerSettings m_projectExplorerSettings; BuildPropertiesSettings m_buildPropertiesSettings; + QList<Internal::CustomParserSettings> m_customParsers; bool m_shouldHaveRunConfiguration = false; bool m_shuttingDown = false; - Core::Id m_runMode = Constants::NO_RUN_MODE; + Utils::Id m_runMode = Constants::NO_RUN_MODE; ToolChainManager *m_toolChainManager = nullptr; QStringList m_arguments; @@ -617,7 +624,7 @@ public: RunWorkerFactory m_customExecutableRunWorkerFactory{ RunWorkerFactory::make<SimpleTargetRunner>(), {Constants::NORMAL_RUN_MODE}, - {m_customExecutableRunConfigFactory.id()} + {m_customExecutableRunConfigFactory.runConfigurationId()} }; ProjectFileWizardExtension m_projectFileWizardExtension; @@ -629,6 +636,7 @@ public: CompileOutputSettingsPage m_compileOutputSettingsPage; DeviceSettingsPage m_deviceSettingsPage; SshSettingsPage m_sshSettingsPage; + CustomParsersSettingsPage m_customParsersSettingsPage; ProjectTreeWidgetFactory m_projectTreeFactory; FolderNavigationWidgetFactory m_folderNavigationWidgetFactory; @@ -649,7 +657,9 @@ public: RunWorkerFactory desktopRunWorkerFactory{ RunWorkerFactory::make<SimpleTargetRunner>(), {ProjectExplorer::Constants::NORMAL_RUN_MODE}, - {qmakeRunConfigFactory.id(), qbsRunConfigFactory.id(), cmakeRunConfigFactory.id()} + {qmakeRunConfigFactory.runConfigurationId(), + qbsRunConfigFactory.runConfigurationId(), + cmakeRunConfigFactory.runConfigurationId()} }; }; @@ -752,6 +762,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er ProjectTree *tree = &dd->m_projectTree; connect(tree, &ProjectTree::currentProjectChanged, dd, &ProjectExplorerPluginPrivate::updateContextMenuActions); + connect(tree, &ProjectTree::nodeActionsChanged, + dd, &ProjectExplorerPluginPrivate::updateContextMenuActions); connect(tree, &ProjectTree::currentNodeChanged, dd, &ProjectExplorerPluginPrivate::updateContextMenuActions); connect(tree, &ProjectTree::currentProjectChanged, @@ -813,6 +825,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er }); ProjectPanelFactory::registerFactory(panelFactory); + RunConfiguration::registerAspect<CustomParsersAspect>(); + // context menus ActionContainer *msessionContextMenu = ActionManager::createMenu(Constants::M_SESSIONCONTEXT); @@ -926,7 +940,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er ActionManager::createMenu(ProjectExplorer::Constants::M_OPENTERMINALCONTEXT); openTerminal->setOnAllDisabledBehavior(ActionContainer::Show); dd->m_openTerminalMenu = openTerminal->menu(); - dd->m_openTerminalMenu->setTitle(FileUtils::msgTerminalWithAction()); + dd->m_openTerminalMenu->setTitle(Core::FileUtils::msgTerminalWithAction()); // "open with" submenu ActionContainer * const openWith = @@ -980,7 +994,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er projectTreeContext); mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN); - dd->m_searchOnFileSystem = new QAction(FileUtils::msgFindInDirectory(), this); + dd->m_searchOnFileSystem = new QAction(Core::FileUtils::msgFindInDirectory(), this); cmd = ActionManager::registerAction(dd->m_searchOnFileSystem, Constants::SEARCHONFILESYSTEM, projectTreeContext); mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); @@ -988,14 +1002,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST); mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST); - dd->m_showInGraphicalShell = new QAction(FileUtils::msgGraphicalShellAction(), this); + dd->m_showInGraphicalShell = new QAction(Core::FileUtils::msgGraphicalShellAction(), this); cmd = ActionManager::registerAction(dd->m_showInGraphicalShell, Constants::SHOWINGRAPHICALSHELL, projectTreeContext); mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN); mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES); // Open Terminal Here menu - dd->m_openTerminalHere = new QAction(FileUtils::msgTerminalHereAction(), this); + dd->m_openTerminalHere = new QAction(Core::FileUtils::msgTerminalHereAction(), this); cmd = ActionManager::registerAction(dd->m_openTerminalHere, Constants::OPENTERMINALHERE, projectTreeContext); @@ -1361,7 +1375,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_removeFileAction = new QAction(this); cmd = ActionManager::registerAction(dd->m_removeFileAction, Constants::REMOVEFILE, projectTreeContext); - cmd->setDefaultKeySequence(QKeySequence::Delete); + cmd->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace}); mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); // duplicate file action @@ -1380,7 +1394,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_deleteFileAction = new QAction(tr("Delete File..."), this); cmd = ActionManager::registerAction(dd->m_deleteFileAction, Constants::DELETEFILE, projectTreeContext); - cmd->setDefaultKeySequence(QKeySequence::Delete); + cmd->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace}); mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); // renamefile action @@ -1412,6 +1426,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er // Collapse & Expand. const Id treeGroup = Constants::G_PROJECT_TREE; + + dd->m_projectTreeExpandNodeAction = new QAction(tr("Expand"), this); + connect(dd->m_projectTreeExpandNodeAction, &QAction::triggered, + ProjectTree::instance(), &ProjectTree::expandCurrentNodeRecursively); + Command * const expandNodeCmd = ActionManager::registerAction( + dd->m_projectTreeExpandNodeAction, "ProjectExplorer.ExpandNode", + projectTreeContext); dd->m_projectTreeCollapseAllAction = new QAction(tr("Collapse All"), this); Command * const collapseCmd = ActionManager::registerAction( dd->m_projectTreeCollapseAllAction, Constants::PROJECTTREE_COLLAPSE_ALL, @@ -1423,6 +1444,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er for (Core::ActionContainer * const ac : {mfileContextMenu, msubProjectContextMenu, mfolderContextMenu, mprojectContextMenu, msessionContextMenu}) { ac->addSeparator(treeGroup); + ac->addAction(expandNodeCmd, treeGroup); ac->addAction(collapseCmd, treeGroup); ac->addAction(expandCmd, treeGroup); } @@ -1432,8 +1454,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_projectSelectorAction->setObjectName("KitSelector"); // used for UI introduction dd->m_projectSelectorAction->setCheckable(true); dd->m_projectSelectorAction->setEnabled(false); - QWidget *mainWindow = ICore::mainWindow(); - dd->m_targetSelector = new MiniProjectTargetSelector(dd->m_projectSelectorAction, mainWindow); + dd->m_targetSelector = new MiniProjectTargetSelector(dd->m_projectSelectorAction, ICore::dialogParent()); connect(dd->m_projectSelectorAction, &QAction::triggered, dd->m_targetSelector, &QWidget::show); ModeManager::addProjectSelector(dd->m_projectSelectorAction); @@ -1511,7 +1532,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er tmp = Utils::HostOsInfo::isWindowsHost() ? 1 : 0; dd->m_projectExplorerSettings.stopBeforeBuild = StopBeforeBuild(tmp); dd->m_projectExplorerSettings.terminalMode = static_cast<TerminalMode>(s->value( - Constants::TERMINAL_MODE_SETTINGS_KEY, int(TerminalMode::Smart)).toInt()); + Constants::TERMINAL_MODE_SETTINGS_KEY, int(TerminalMode::Off)).toInt()); dd->m_projectExplorerSettings.closeSourceFilesWithProject = s->value(Constants::CLOSE_FILES_WITH_PROJECT_SETTINGS_KEY, true).toBool(); dd->m_projectExplorerSettings.clearIssuesOnRebuild @@ -1535,6 +1556,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_buildPropertiesSettings.qtQuickCompiler = loadTriStateValue(Constants::QT_QUICK_COMPILER_SETTINGS_KEY); + const int customParserCount = s->value(Constants::CUSTOM_PARSER_COUNT_KEY).toInt(); + for (int i = 0; i < customParserCount; ++i) { + CustomParserSettings settings; + settings.fromMap(s->value(Constants::CUSTOM_PARSER_PREFIX_KEY + + QString::number(i)).toMap()); + dd->m_customParsers << settings; + } + auto buildManager = new BuildManager(this, dd->m_cancelBuildAction); connect(buildManager, &BuildManager::buildStateChanged, dd, &ProjectExplorerPluginPrivate::updateActions); @@ -1985,7 +2014,7 @@ void ProjectExplorerPlugin::extensionsInitialized() const QString gitBinary = Core::ICore::settings()->value("Git/BinaryPath", "git") .toString(); const QStringList rawGitSearchPaths = Core::ICore::settings()->value("Git/Path") - .toString().split(':', QString::SkipEmptyParts); + .toString().split(':', Utils::SkipEmptyParts); const Utils::FilePaths gitSearchPaths = Utils::transform(rawGitSearchPaths, [](const QString &rawPath) { return Utils::FilePath::fromString(rawPath); }); const Utils::FilePath fullGitPath = Utils::Environment::systemEnvironment() @@ -2004,7 +2033,7 @@ void ProjectExplorerPlugin::extensionsInitialized() Command * const cmd = ActionManager::registerAction(parseIssuesAction, "ProjectExplorer.ParseIssuesAction"); connect(parseIssuesAction, &QAction::triggered, this, [] { - ParseIssuesDialog dlg(ICore::mainWindow()); + ParseIssuesDialog dlg(ICore::dialogParent()); dlg.exec(); }); mtools->addAction(cmd); @@ -2068,7 +2097,7 @@ void ProjectExplorerPlugin::openNewProjectDialog() void ProjectExplorerPluginPrivate::showSessionManager() { SessionManager::save(); - SessionDialog sessionDialog(ICore::mainWindow()); + SessionDialog sessionDialog(ICore::dialogParent()); sessionDialog.setAutoLoadSession(dd->m_projectExplorerSettings.autorestoreLastSession); sessionDialog.exec(); dd->m_projectExplorerSettings.autorestoreLastSession = sessionDialog.autoLoadSession(); @@ -2169,6 +2198,12 @@ void ProjectExplorerPluginPrivate::savePersistentSettings() dd->m_buildPropertiesSettings.qmlDebugging.toVariant()); s->setValue(Constants::QT_QUICK_COMPILER_SETTINGS_KEY, dd->m_buildPropertiesSettings.qtQuickCompiler.toVariant()); + + s->setValue(Constants::CUSTOM_PARSER_COUNT_KEY, dd->m_customParsers.count()); + for (int i = 0; i < dd->m_customParsers.count(); ++i) { + s->setValue(Constants::CUSTOM_PARSER_PREFIX_KEY + QString::number(i), + dd->m_customParsers.at(i).toMap()); + } } void ProjectExplorerPlugin::openProjectWelcomePage(const QString &fileName) @@ -2209,7 +2244,7 @@ void ProjectExplorerPlugin::showOpenProjectError(const OpenProjectResult &result QString errorMessage = result.errorMessage(); if (!errorMessage.isEmpty()) { // ignore alreadyOpen - QMessageBox::critical(ICore::mainWindow(), tr("Failed to Open Project"), errorMessage); + QMessageBox::critical(ICore::dialogParent(), tr("Failed to Open Project"), errorMessage); } else { // ignore multiple alreadyOpen Project *alreadyOpen = result.alreadyOpen().constFirst(); @@ -2351,6 +2386,11 @@ QThreadPool *ProjectExplorerPlugin::sharedThreadPool() return &(dd->m_threadPool); } +MiniProjectTargetSelector *ProjectExplorerPlugin::targetSelector() +{ + return dd->m_targetSelector; +} + /*! This function is connected to the ICore::coreOpened signal. If there was no session explicitly loaded, it creates an empty new @@ -2414,7 +2454,7 @@ void ProjectExplorerPluginPrivate::restoreSession() updateActions(); } -void ProjectExplorerPluginPrivate::executeRunConfiguration(RunConfiguration *runConfiguration, Core::Id runMode) +void ProjectExplorerPluginPrivate::executeRunConfiguration(RunConfiguration *runConfiguration, Utils::Id runMode) { const Tasks runConfigIssues = runConfiguration->checkForIssues(); if (!runConfigIssues.isEmpty()) { @@ -2453,7 +2493,7 @@ void ProjectExplorerPluginPrivate::startRunControl(RunControl *runControl) m_outputPane.createNewOutputWindow(runControl); m_outputPane.flash(); // one flash for starting m_outputPane.showTabFor(runControl); - Core::Id runMode = runControl->runMode(); + Utils::Id runMode = runControl->runMode(); const auto popupMode = runMode == Constants::NORMAL_RUN_MODE ? m_outputPane.settings().runOutputMode : runMode == Constants::DEBUG_RUN_MODE @@ -2696,17 +2736,6 @@ ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() m_allProjectDirectoriesFilter.setIsCustomFilter(false); } -QString ProjectExplorerPlugin::displayNameForStepId(Id stepId) -{ - if (stepId == Constants::BUILDSTEPS_CLEAN) - return tr("Clean"); - if (stepId == Constants::BUILDSTEPS_BUILD) - return tr("Build", "Build step"); - if (stepId == Constants::BUILDSTEPS_DEPLOY) - return tr("Deploy"); - return tr("Build", "Build step"); -} - void ProjectExplorerPluginPrivate::runProjectContextMenu() { const Node *node = ProjectTree::currentNode(); @@ -2844,7 +2873,7 @@ static bool hasDeploySettings(Project *pro) }); } -void ProjectExplorerPlugin::runProject(Project *pro, Core::Id mode, const bool forceSkipDeploy) +void ProjectExplorerPlugin::runProject(Project *pro, Utils::Id mode, const bool forceSkipDeploy) { if (!pro) return; @@ -2854,13 +2883,13 @@ void ProjectExplorerPlugin::runProject(Project *pro, Core::Id mode, const bool f runRunConfiguration(rc, mode, forceSkipDeploy); } -void ProjectExplorerPlugin::runStartupProject(Core::Id runMode, bool forceSkipDeploy) +void ProjectExplorerPlugin::runStartupProject(Utils::Id runMode, bool forceSkipDeploy) { runProject(SessionManager::startupProject(), runMode, forceSkipDeploy); } void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc, - Core::Id runMode, + Utils::Id runMode, const bool forceSkipDeploy) { if (!rc->isEnabled()) @@ -2970,7 +2999,7 @@ void ProjectExplorerPluginPrivate::updateDeployActions() doUpdateRunActions(); } -bool ProjectExplorerPlugin::canRunStartupProject(Core::Id runMode, QString *whyNot) +bool ProjectExplorerPlugin::canRunStartupProject(Utils::Id runMode, QString *whyNot) { Project *project = SessionManager::startupProject(); if (!project) { @@ -3236,20 +3265,28 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions() return currentNode->supportsAction(action, currentNode); }; + bool canEditProject = true; + if (project && project->activeTarget()) { + const BuildSystem * const bs = project->activeTarget()->buildSystem(); + if (bs->isParsing() || bs->isWaitingForParse()) + canEditProject = false; + } if (currentNode->asFolderNode()) { // Also handles ProjectNode - m_addNewFileAction->setEnabled(supports(AddNewFile) + m_addNewFileAction->setEnabled(canEditProject && supports(AddNewFile) && !ICore::isNewItemDialogRunning()); - m_addNewSubprojectAction->setEnabled(currentNode->isProjectNodeType() + m_addNewSubprojectAction->setEnabled(canEditProject && currentNode->isProjectNodeType() && supports(AddSubProject) && !ICore::isNewItemDialogRunning()); - m_addExistingProjectsAction->setEnabled(currentNode->isProjectNodeType() + m_addExistingProjectsAction->setEnabled(canEditProject + && currentNode->isProjectNodeType() && supports(AddExistingProject)); - m_removeProjectAction->setEnabled(currentNode->isProjectNodeType() + m_removeProjectAction->setEnabled(canEditProject && currentNode->isProjectNodeType() && supports(RemoveSubProject)); - m_addExistingFilesAction->setEnabled(supports(AddExistingFile)); - m_addExistingDirectoryAction->setEnabled(supports(AddExistingDirectory)); - m_renameFileAction->setEnabled(supports(Rename)); + m_addExistingFilesAction->setEnabled(canEditProject && supports(AddExistingFile)); + m_addExistingDirectoryAction->setEnabled(canEditProject + && supports(AddExistingDirectory)); + m_renameFileAction->setEnabled(canEditProject && supports(Rename)); } else if (auto fileNode = currentNode->asFileNode()) { // Enable and show remove / delete in magic ways: // If both are disabled show Remove @@ -3257,20 +3294,20 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions() // If only removeFile is enabled only show it // If only deleteFile is enable only show it bool isTypeProject = fileNode->fileType() == FileType::Project; - bool enableRemove = !isTypeProject && supports(RemoveFile); + bool enableRemove = canEditProject && !isTypeProject && supports(RemoveFile); m_removeFileAction->setEnabled(enableRemove); - bool enableDelete = !isTypeProject && supports(EraseFile); + bool enableDelete = canEditProject && !isTypeProject && supports(EraseFile); m_deleteFileAction->setEnabled(enableDelete); m_deleteFileAction->setVisible(enableDelete); m_removeFileAction->setVisible(!enableDelete || enableRemove); - m_renameFileAction->setEnabled(!isTypeProject && supports(Rename)); + m_renameFileAction->setEnabled(canEditProject && !isTypeProject && supports(Rename)); const bool currentNodeIsTextFile = isTextFile( currentNode->filePath().toString()); m_diffFileAction->setEnabled(DiffService::instance() && currentNodeIsTextFile && TextEditor::TextDocument::currentTextDocument()); - const bool canDuplicate = supports(AddNewFile) + const bool canDuplicate = canEditProject && supports(AddNewFile) && currentNode->asFileNode()->fileType() != FileType::Project; m_duplicateFileAction->setVisible(canDuplicate); m_duplicateFileAction->setEnabled(canDuplicate); @@ -3390,7 +3427,7 @@ void ProjectExplorerPluginPrivate::addNewSubproject() QVariantMap map; map.insert(QLatin1String(Constants::PREFERRED_PROJECT_NODE), QVariant::fromValue(currentNode)); Project *project = ProjectTree::currentProject(); - Core::Id projectType; + Utils::Id projectType; if (project) { const QStringList profileIds = Utils::transform(ProjectTree::currentProject()->targets(), [](const Target *t) { @@ -3420,7 +3457,7 @@ void ProjectExplorerPluginPrivate::addExistingProjects() QTC_ASSERT(projectNode, return); const QString dir = currentNode->directory(); QStringList subProjectFilePaths = QFileDialog::getOpenFileNames( - ICore::mainWindow(), tr("Choose Project File"), dir, + ICore::dialogParent(), tr("Choose Project File"), dir, projectNode->subProjectFileNamePatterns().join(";;")); if (!ProjectTree::hasNode(projectNode)) return; @@ -3443,7 +3480,7 @@ void ProjectExplorerPluginPrivate::addExistingProjects() if (!failedProjects.empty()) { const QString message = tr("The following subprojects could not be added to project " "\"%1\":").arg(projectNode->managingProject()->displayName()); - QMessageBox::warning(ICore::mainWindow(), tr("Adding Subproject Failed"), + QMessageBox::warning(ICore::dialogParent(), tr("Adding Subproject Failed"), message + "\n " + failedProjects.join("\n ")); return; } @@ -3457,7 +3494,7 @@ void ProjectExplorerPluginPrivate::handleAddExistingFiles() QTC_ASSERT(folderNode, return); - QStringList fileNames = QFileDialog::getOpenFileNames(ICore::mainWindow(), + QStringList fileNames = QFileDialog::getOpenFileNames(ICore::dialogParent(), tr("Add Existing Files"), node->directory()); if (fileNames.isEmpty()) return; @@ -3473,7 +3510,7 @@ void ProjectExplorerPluginPrivate::addExistingDirectory() QTC_ASSERT(folderNode, return); SelectableFilesDialogAddDirectory dialog(Utils::FilePath::fromString(node->directory()), - Utils::FilePaths(), ICore::mainWindow()); + Utils::FilePaths(), ICore::dialogParent()); dialog.setAddFileFilter({}); if (dialog.exec() == QDialog::Accepted) @@ -3496,7 +3533,7 @@ void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStri .arg(folderNode->managingProject()->displayName()) + QLatin1Char('\n'); const QStringList nativeFiles = Utils::transform(notAdded, &QDir::toNativeSeparators); - QMessageBox::warning(ICore::mainWindow(), tr("Adding Files to Project Failed"), + QMessageBox::warning(ICore::dialogParent(), tr("Adding Files to Project Failed"), message + nativeFiles.join(QLatin1Char('\n'))); fileNames = Utils::filtered(fileNames, [¬Added](const QString &f) { return !notAdded.contains(f); }); @@ -3512,7 +3549,7 @@ void ProjectExplorerPluginPrivate::removeProject() return; ProjectNode *projectNode = node->managingProject(); if (projectNode) { - Utils::RemoveFileDialog removeFileDialog(node->filePath().toString(), ICore::mainWindow()); + Utils::RemoveFileDialog removeFileDialog(node->filePath().toString(), ICore::dialogParent()); removeFileDialog.setDeleteFileVisible(false); if (removeFileDialog.exec() == QDialog::Accepted) projectNode->removeSubProject(node->filePath().toString()); @@ -3537,7 +3574,7 @@ void ProjectExplorerPluginPrivate::showInGraphicalShell() { Node *currentNode = ProjectTree::currentNode(); QTC_ASSERT(currentNode, return); - FileUtils::showInGraphicalShell(ICore::mainWindow(), currentNode->path()); + Core::FileUtils::showInGraphicalShell(ICore::dialogParent(), currentNode->path()); } void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env) @@ -3549,7 +3586,7 @@ void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env if (!environment) return; - FileUtils::openTerminal(currentNode->directory(), environment.value()); + Core::FileUtils::openTerminal(currentNode->directory(), environment.value()); } void ProjectExplorerPluginPrivate::openTerminalHereWithRunEnv() @@ -3580,40 +3617,56 @@ void ProjectExplorerPluginPrivate::removeFile() QTC_ASSERT(currentNode && currentNode->asFileNode(), return); const Utils::FilePath filePath = currentNode->filePath(); - Utils::RemoveFileDialog removeFileDialog(filePath.toString(), ICore::mainWindow()); - - if (removeFileDialog.exec() == QDialog::Accepted) { - const bool deleteFile = removeFileDialog.isDeleteFileChecked(); + using NodeAndPath = QPair<const Node *, Utils::FilePath>; + QList<NodeAndPath> filesToRemove{qMakePair(currentNode, currentNode->filePath())}; + QList<NodeAndPath> siblings; + for (const Node * const n : ProjectTree::siblingsWithSameBaseName(currentNode)) + siblings << qMakePair(n, n->filePath()); + + Utils::RemoveFileDialog removeFileDialog(filePath.toString(), ICore::dialogParent()); + if (removeFileDialog.exec() != QDialog::Accepted) + return; - // Re-read the current node, in case the project is re-parsed while the dialog is open - if (!ProjectTree::hasNode(currentNode)) { - QMessageBox::warning(ICore::mainWindow(), tr("Removing File Failed"), - tr("File %1 was not removed, because the project has changed " + const bool deleteFile = removeFileDialog.isDeleteFileChecked(); + + const QMessageBox::StandardButton reply = QMessageBox::question( + Core::ICore::dialogParent(), tr("Remove More Files?"), + tr("Remove these files as well?\n %1") + .arg(Utils::transform<QStringList>(siblings, [](const NodeAndPath &np) { + return np.second.toFileInfo().fileName(); + }).join("\n "))); + if (reply == QMessageBox::Yes) + filesToRemove << siblings; + + for (const NodeAndPath &file : filesToRemove) { + // Nodes can become invalid if the project was re-parsed while the dialog was open + if (!ProjectTree::hasNode(file.first)) { + QMessageBox::warning(ICore::dialogParent(), tr("Removing File Failed"), + tr("File \"%1\" was not removed, because the project has changed " "in the meantime.\nPlease try again.") - .arg(filePath.toUserOutput())); + .arg(file.second.toUserOutput())); return; } // remove from project - FolderNode *folderNode = currentNode->asFileNode()->parentFolderNode(); + FolderNode *folderNode = file.first->asFileNode()->parentFolderNode(); QTC_ASSERT(folderNode, return); const RemovedFilesFromProject status - = folderNode->removeFiles(QStringList(filePath.toString())); + = folderNode->removeFiles(QStringList(file.second.toString())); const bool success = status == RemovedFilesFromProject::Ok || (status == RemovedFilesFromProject::Wildcard && removeFileDialog.isDeleteFileChecked()); if (!success) { - QMessageBox::warning(ICore::mainWindow(), tr("Removing File Failed"), - tr("Could not remove file %1 from project %2.") - .arg(filePath.toUserOutput()) - .arg(folderNode->managingProject()->displayName())); + TaskHub::addTask(BuildSystemTask(Task::Error, + tr("Could not remove file \"%1\" from project \"%2\".") + .arg(filePath.toUserOutput(), folderNode->managingProject()->displayName()), + folderNode->managingProject()->filePath())); if (!deleteFile) - return; + continue; } - FileChangeBlocker changeGuard(filePath.toString()); - FileUtils::removeFile(filePath.toString(), deleteFile); + Core::FileUtils::removeFile(filePath.toString(), deleteFile); } } @@ -3632,7 +3685,7 @@ void ProjectExplorerPluginPrivate::duplicateFile() newFileName.insert(copyTokenIndex, tr("_copy")); bool okPressed; - newFileName = QInputDialog::getText(ICore::mainWindow(), tr("Choose File Name"), + newFileName = QInputDialog::getText(ICore::dialogParent(), tr("Choose File Name"), tr("New file name:"), QLineEdit::Normal, newFileName, &okPressed); if (!okPressed) return; @@ -3644,14 +3697,14 @@ void ProjectExplorerPluginPrivate::duplicateFile() QTC_ASSERT(folderNode, return); QFile sourceFile(filePath); if (!sourceFile.copy(newFilePath)) { - QMessageBox::critical(ICore::mainWindow(), tr("Duplicating File Failed"), + QMessageBox::critical(ICore::dialogParent(), tr("Duplicating File Failed"), tr("Failed to copy file \"%1\" to \"%2\": %3.") .arg(QDir::toNativeSeparators(filePath), QDir::toNativeSeparators(newFilePath), sourceFile.errorString())); return; } if (!folderNode->addFiles(QStringList(newFilePath))) { - QMessageBox::critical(ICore::mainWindow(), tr("Duplicating File Failed"), + QMessageBox::critical(ICore::dialogParent(), tr("Duplicating File Failed"), tr("Failed to add new file \"%1\" to the project.") .arg(QDir::toNativeSeparators(newFilePath))); } @@ -3666,7 +3719,7 @@ void ProjectExplorerPluginPrivate::deleteFile() QString filePath = currentNode->filePath().toString(); QMessageBox::StandardButton button = - QMessageBox::question(ICore::mainWindow(), + QMessageBox::question(ICore::dialogParent(), tr("Delete File"), tr("Delete %1 from file system?") .arg(QDir::toNativeSeparators(filePath)), @@ -3687,7 +3740,7 @@ void ProjectExplorerPluginPrivate::deleteFile() QFile file(filePath); if (file.exists()) { if (!file.remove()) - QMessageBox::warning(ICore::mainWindow(), tr("Deleting File Failed"), + QMessageBox::warning(ICore::dialogParent(), tr("Deleting File Failed"), tr("Could not delete file %1.") .arg(QDir::toNativeSeparators(filePath))); } @@ -3718,7 +3771,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath) if (!folderNode->canRenameFile(oldFilePath, newFilePath)) { QTimer::singleShot(0, [oldFilePath, newFilePath, projectFileName] { - int res = QMessageBox::question(ICore::mainWindow(), + int res = QMessageBox::question(ICore::dialogParent(), tr("Project Editing Failed"), tr("The project file %1 cannot be automatically changed.\n\n" "Rename %2 to %3 anyway?") @@ -3726,14 +3779,13 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath) .arg(QDir::toNativeSeparators(oldFilePath)) .arg(QDir::toNativeSeparators(newFilePath))); if (res == QMessageBox::Yes) { - QTC_CHECK(FileUtils::renameFile(oldFilePath, newFilePath)); + QTC_CHECK(Core::FileUtils::renameFile(oldFilePath, newFilePath)); } - }); return; } - if (FileUtils::renameFile(oldFilePath, newFilePath)) { + if (Core::FileUtils::renameFile(oldFilePath, newFilePath)) { // Tell the project plugin about rename if (!folderNode->renameFile(oldFilePath, newFilePath)) { const QString renameFileError @@ -3743,7 +3795,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath) .arg(projectFileName); QTimer::singleShot(0, [renameFileError]() { - QMessageBox::warning(ICore::mainWindow(), + QMessageBox::warning(ICore::dialogParent(), tr("Project Editing Failed"), renameFileError); }); @@ -3754,9 +3806,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath) .arg(QDir::toNativeSeparators(newFilePath)); QTimer::singleShot(0, [renameFileError]() { - QMessageBox::warning(ICore::mainWindow(), - tr("Cannot Rename File"), - renameFileError); + QMessageBox::warning(ICore::dialogParent(), tr("Cannot Rename File"), renameFileError); }); } } @@ -3839,6 +3889,19 @@ void ProjectExplorerPlugin::showQtSettings() dd->m_buildPropertiesSettings.showQtSettings = true; } +void ProjectExplorerPlugin::setCustomParsers(const QList<CustomParserSettings> &settings) +{ + if (dd->m_customParsers != settings) { + dd->m_customParsers = settings; + emit m_instance->customParsersChanged(); + } +} + +const QList<CustomParserSettings> ProjectExplorerPlugin::customParsers() +{ + return dd->m_customParsers; +} + QStringList ProjectExplorerPlugin::projectFilePatterns() { QStringList patterns; @@ -3890,7 +3953,7 @@ void ProjectExplorerPlugin::updateActions() dd->updateActions(); } -void ProjectExplorerPlugin::activateProjectPanel(Core::Id panelId) +void ProjectExplorerPlugin::activateProjectPanel(Utils::Id panelId) { Core::ModeManager::activateMode(Constants::MODE_SESSION); dd->m_proWindow->activateProjectPanel(panelId); |