From ef951eaea775c150378bbb2ef81c292f72aa7360 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Wed, 30 Sep 2015 18:04:17 +0200 Subject: [PATCH] Class Renaming: Offer to rename files that match the symbols name Task-number: QTCREATORBUG-14696 Change-Id: I6d140dac510e47d1a19d6759148f5f24dad44062 Reviewed-by: Ivan Donchevskii Reviewed-by: Nikolai Kosjar Reviewed-by: Orgad Shaneh --- .../coreplugin/find/searchresultwidget.cpp | 8 ++ .../coreplugin/find/searchresultwidget.h | 2 + .../coreplugin/find/searchresultwindow.cpp | 5 + .../coreplugin/find/searchresultwindow.h | 1 + src/plugins/cpptools/cppfindreferences.cpp | 91 ++++++++++++++++++- src/plugins/cpptools/cppfindreferences.h | 6 ++ src/plugins/cpptools/cppmodelmanager.h | 3 +- 7 files changed, 114 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/find/searchresultwidget.cpp b/src/plugins/coreplugin/find/searchresultwidget.cpp index 2aa443630d..4020060757 100644 --- a/src/plugins/coreplugin/find/searchresultwidget.cpp +++ b/src/plugins/coreplugin/find/searchresultwidget.cpp @@ -185,6 +185,8 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) : m_preserveCaseCheck = new QCheckBox(m_topReplaceWidget); m_preserveCaseCheck->setText(tr("Preser&ve case")); m_preserveCaseCheck->setEnabled(false); + m_renameFilesCheckBox = new QCheckBox(m_topReplaceWidget); + m_renameFilesCheckBox->setVisible(false); m_preserveCaseCheck->setChecked(Find::hasFindFlag(FindPreserveCase)); connect(m_preserveCaseCheck, &QAbstractButton::clicked, Find::instance(), &Find::setPreserveCase); @@ -201,6 +203,7 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) : topReplaceLayout->addWidget(m_replaceTextEdit); topReplaceLayout->addWidget(m_replaceButton); topReplaceLayout->addWidget(m_preserveCaseCheck); + topReplaceLayout->addWidget(m_renameFilesCheckBox); topReplaceLayout->addStretch(2); setShowReplaceUI(m_replaceSupported); setSupportPreserveCase(true); @@ -228,6 +231,11 @@ void SearchResultWidget::setInfo(const QString &label, const QString &toolTip, c m_searchTerm->setVisible(!term.isEmpty()); } +QWidget *SearchResultWidget::additionalReplaceWidget() const +{ + return m_renameFilesCheckBox; +} + void SearchResultWidget::addResult(const QString &fileName, const QString &rowText, Search::TextRange mainRange, diff --git a/src/plugins/coreplugin/find/searchresultwidget.h b/src/plugins/coreplugin/find/searchresultwidget.h index 8fdda24e6d..5c5e3374a6 100644 --- a/src/plugins/coreplugin/find/searchresultwidget.h +++ b/src/plugins/coreplugin/find/searchresultwidget.h @@ -53,6 +53,7 @@ public: ~SearchResultWidget(); void setInfo(const QString &label, const QString &toolTip, const QString &term); + QWidget *additionalReplaceWidget() const; void addResult(const QString &fileName, const QString &lineText, @@ -130,6 +131,7 @@ private: QToolButton *m_replaceButton; QToolButton *m_searchAgainButton; QCheckBox *m_preserveCaseCheck; + QCheckBox *m_renameFilesCheckBox = nullptr; QWidget *m_descriptionContainer; QLabel *m_label; QLabel *m_searchTerm; diff --git a/src/plugins/coreplugin/find/searchresultwindow.cpp b/src/plugins/coreplugin/find/searchresultwindow.cpp index 08fbace981..ce3d0e2a08 100644 --- a/src/plugins/coreplugin/find/searchresultwindow.cpp +++ b/src/plugins/coreplugin/find/searchresultwindow.cpp @@ -643,6 +643,11 @@ void SearchResult::setSearchAgainSupported(bool supported) m_widget->setSearchAgainSupported(supported); } +QWidget *SearchResult::additionalReplaceWidget() const +{ + return m_widget->additionalReplaceWidget(); +} + /*! Adds a single result line to the \gui {Search Results} output pane. diff --git a/src/plugins/coreplugin/find/searchresultwindow.h b/src/plugins/coreplugin/find/searchresultwindow.h index d9a15ab06e..f62c216311 100644 --- a/src/plugins/coreplugin/find/searchresultwindow.h +++ b/src/plugins/coreplugin/find/searchresultwindow.h @@ -61,6 +61,7 @@ public: QString textToReplace() const; int count() const; void setSearchAgainSupported(bool supported); + QWidget *additionalReplaceWidget() const; public slots: void addResult(const QString &fileName, diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index de598e3d61..5426664483 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include #include #include @@ -42,6 +45,7 @@ #include #include +#include #include #include @@ -50,6 +54,7 @@ using namespace Core; using namespace CppTools::Internal; using namespace CppTools; using namespace CPlusPlus; +using namespace ProjectExplorer; static QByteArray getSource(const Utils::FileName &fileName, const WorkingCopy &workingCopy) @@ -336,6 +341,12 @@ void CppFindReferences::findUsages(Symbol *symbol, CppFindReferencesParameters parameters; parameters.symbolId = fullIdForSymbol(symbol); parameters.symbolFileName = QByteArray(symbol->fileName()); + + if (symbol->isClass() || symbol->isForwardClassDeclaration()) { + Overview overview; + parameters.prettySymbolName = overview.prettyName(context.path(symbol).last()); + } + search->setUserData(qVariantFromValue(parameters)); findAll_helper(search, symbol, context); } @@ -382,12 +393,48 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text, m_modelManager->updateSourceFiles(fileNames.toSet()); SearchResultWindow::instance()->hide(); } + + auto search = qobject_cast(sender()); + QTC_ASSERT(search, return); + + CppFindReferencesParameters parameters = search->userData().value(); + if (parameters.filesToRename.isEmpty()) + return; + + auto renameFilesCheckBox = qobject_cast(search->additionalReplaceWidget()); + if (!renameFilesCheckBox || !renameFilesCheckBox->isChecked()) + return; + + const QStringList newPaths = + Utils::transform(parameters.filesToRename, + [¶meters, text](const Node *node) -> QString { + const QFileInfo fi = node->filePath().toFileInfo(); + const QString fileName = fi.fileName(); + QString newName = fileName; + newName.replace(parameters.prettySymbolName, text, Qt::CaseInsensitive); + + if (newName != fileName) { + newName = Utils::matchCaseReplacement(fileName, newName); + + return fi.absolutePath() + "/" + newName; + } + + return QString(); + }); + + for (int i = 0; i < parameters.filesToRename.size(); ++i) { + if (!newPaths.at(i).isEmpty()) { + Node *node = parameters.filesToRename.at(i); + ProjectExplorerPlugin::renameFile(node, newPaths.at(i)); + } + } } void CppFindReferences::searchAgain() { SearchResult *search = qobject_cast(sender()); CppFindReferencesParameters parameters = search->userData().value(); + parameters.filesToRename.clear(); Snapshot snapshot = CppModelManager::instance()->snapshot(); search->restart(); LookupContext context; @@ -467,6 +514,8 @@ Symbol *CppFindReferences::findSymbol(const CppFindReferencesParameters ¶met static void displayResults(SearchResult *search, QFutureWatcher *watcher, int first, int last) { + CppFindReferencesParameters parameters = search->userData().value(); + for (int index = first; index != last; ++index) { Usage result = watcher->future().resultAt(index); search->addResult(result.path.toString(), @@ -474,7 +523,45 @@ static void displayResults(SearchResult *search, QFutureWatcher *watcher, result.lineText, result.col, result.len); + + if (parameters.prettySymbolName.isEmpty()) + continue; + + if (Utils::contains(parameters.filesToRename, Utils::equal(&Node::filePath, result.path))) + continue; + + Node *node = SessionManager::nodeForFile(result.path); + if (!node) // Not part of any project + continue; + + const QFileInfo fi = node->filePath().toFileInfo(); + if (fi.baseName().compare(parameters.prettySymbolName, Qt::CaseInsensitive) == 0) + parameters.filesToRename.append(node); } + + search->setUserData(qVariantFromValue(parameters)); +} + +static void searchFinished(SearchResult *search, QFutureWatcher *watcher) +{ + search->finishSearch(watcher->isCanceled()); + + CppFindReferencesParameters parameters = search->userData().value(); + if (!parameters.filesToRename.isEmpty()) { + const QStringList filesToRename + = Utils::transform(parameters.filesToRename, [](const Node *node) { + return node->filePath().toUserOutput(); + }); + + auto renameCheckBox = qobject_cast(search->additionalReplaceWidget()); + if (renameCheckBox) { + renameCheckBox->setText(CppFindReferences::tr("Re&name %1 files.").arg(filesToRename.size())); + renameCheckBox->setToolTip(CppFindReferences::tr("Files:\n%1").arg(filesToRename.join('\n'))); + renameCheckBox->setVisible(true); + } + } + + watcher->deleteLater(); } void CppFindReferences::openEditor(const SearchResultItem &item) @@ -651,7 +738,9 @@ void CppFindReferences::createWatcher(const QFuture &future, SearchResult { QFutureWatcher *watcher = new QFutureWatcher(); // auto-delete: - connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + connect(watcher, &QFutureWatcherBase::finished, watcher, [search, watcher]() { + searchFinished(search, watcher); + }); connect(watcher, &QFutureWatcherBase::resultsReadyAt, search, [search, watcher](int first, int last) { diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h index 5a2dfc4cc5..422eedb0c9 100644 --- a/src/plugins/cpptools/cppfindreferences.h +++ b/src/plugins/cpptools/cppfindreferences.h @@ -40,6 +40,10 @@ class SearchResultItem; class SearchResult; } // namespace Core +namespace ProjectExplorer { +class Node; +} + namespace CppTools { class CppModelManager; @@ -50,6 +54,8 @@ class CppFindReferencesParameters public: QList symbolId; QByteArray symbolFileName; + QString prettySymbolName; + QVector filesToRename; }; class CppFindReferences: public QObject diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index ce2a042bc9..97a93fce60 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -180,6 +180,8 @@ public: static void setRefactoringEngine(RefactoringEngineInterface *refactoringEngine); static RefactoringEngineInterface *refactoringEngine(); + void renameIncludes(const QString &oldFileName, const QString &newFileName); + signals: /// Project data might be locked while this is emitted. void aboutToRemoveFiles(const QStringList &files); @@ -205,7 +207,6 @@ private: // This should be executed in the GUI thread. friend class Tests::ModelManagerTestHelper; void onAboutToLoadSession(); - void renameIncludes(const QString &oldFileName, const QString &newFileName); void onProjectAdded(ProjectExplorer::Project *project); void onAboutToRemoveProject(ProjectExplorer::Project *project); void onActiveProjectChanged(ProjectExplorer::Project *project); -- GitLab