diff --git a/src/plugins/coreplugin/find/searchresulttreemodel.cpp b/src/plugins/coreplugin/find/searchresulttreemodel.cpp index 09f16f0453b..92dce53da2f 100644 --- a/src/plugins/coreplugin/find/searchresulttreemodel.cpp +++ b/src/plugins/coreplugin/find/searchresulttreemodel.cpp @@ -5,6 +5,7 @@ #include "searchresulttreeitems.h" #include "searchresulttreeitemroles.h" +#include #include #include @@ -27,6 +28,7 @@ public: ~SearchResultTreeModel() override; void setShowReplaceUI(bool show); + void setRelativePaths(bool relative); void setTextEditorFont(const QFont &font, const SearchResultColors &colors); Qt::ItemFlags flags(const QModelIndex &index) const override; @@ -69,6 +71,7 @@ private: QStringList m_currentPath; // the path that belongs to the current parent QFont m_textEditorFont; bool m_showReplaceUI; + bool m_relativePaths; bool m_editorFontIsUsed; }; @@ -76,6 +79,7 @@ SearchResultTreeModel::SearchResultTreeModel(QObject *parent) : QAbstractItemModel(parent) , m_currentParent(nullptr) , m_showReplaceUI(false) + , m_relativePaths(false) , m_editorFontIsUsed(false) { m_rootItem = new SearchResultTreeItem; @@ -106,6 +110,12 @@ void SearchResultTreeModel::setShowReplaceUI(bool show) } } +void SearchResultTreeModel::setRelativePaths(bool relative) +{ + m_relativePaths = relative; + emit dataChanged(index(0, 0), index(rowCount() - 1, 0)); +} + void SearchResultTreeModel::setTextEditorFont(const QFont &font, const SearchResultColors &colors) { emit layoutAboutToBeChanged(); @@ -295,9 +305,15 @@ QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role) result = m_colors.value(row->item.style()).textBackground; break; case ItemDataRoles::ResultLineRole: - case Qt::DisplayRole: result = row->item.lineText(); break; + case Qt::DisplayRole: + if (m_relativePaths && row->isGenerated()) { + result = ICore::pathRelativeToActiveProject(FilePath::fromUserInput(row->item.lineText())).toUserOutput(); + } else { + result = row->item.lineText(); + } + break; case ItemDataRoles::ResultItemRole: result = QVariant::fromValue(row->item); break; @@ -580,6 +596,11 @@ void SearchResultFilterModel::setShowReplaceUI(bool show) sourceModel()->setShowReplaceUI(show); } +void SearchResultFilterModel::setRelativePaths(bool relative) +{ + sourceModel()->setRelativePaths(relative); +} + void SearchResultFilterModel::setTextEditorFont(const QFont &font, const SearchResultColors &colors) { sourceModel()->setTextEditorFont(font, colors); diff --git a/src/plugins/coreplugin/find/searchresulttreemodel.h b/src/plugins/coreplugin/find/searchresulttreemodel.h index 716bcccca32..6a697131aa7 100644 --- a/src/plugins/coreplugin/find/searchresulttreemodel.h +++ b/src/plugins/coreplugin/find/searchresulttreemodel.h @@ -24,6 +24,7 @@ public: void setFilter(SearchResultFilter *filter); void setShowReplaceUI(bool show); + void setRelativePaths(bool relative); void setTextEditorFont(const QFont &font, const Utils::SearchResultColors &colors); QList addResults(const Utils::SearchResultItems &items, SearchResult::AddMode mode); diff --git a/src/plugins/coreplugin/find/searchresulttreeview.cpp b/src/plugins/coreplugin/find/searchresulttreeview.cpp index c246d21fca5..35902360400 100644 --- a/src/plugins/coreplugin/find/searchresulttreeview.cpp +++ b/src/plugins/coreplugin/find/searchresulttreeview.cpp @@ -58,6 +58,11 @@ void SearchResultTreeView::setAutoExpandResults(bool expand) m_autoExpandResults = expand; } +void SearchResultTreeView::setRelativePaths(bool relative) +{ + m_model->setRelativePaths(relative); +} + void SearchResultTreeView::setTextEditorFont(const QFont &font, const SearchResultColors &colors) { m_model->setTextEditorFont(font, colors); diff --git a/src/plugins/coreplugin/find/searchresulttreeview.h b/src/plugins/coreplugin/find/searchresulttreeview.h index 06996fefe09..7a4b3994d70 100644 --- a/src/plugins/coreplugin/find/searchresulttreeview.h +++ b/src/plugins/coreplugin/find/searchresulttreeview.h @@ -22,6 +22,7 @@ public: explicit SearchResultTreeView(QWidget *parent = nullptr); void setAutoExpandResults(bool expand); + void setRelativePaths(bool relative); void setTextEditorFont(const QFont &font, const Utils::SearchResultColors &colors); void setTabWidth(int tabWidth); diff --git a/src/plugins/coreplugin/find/searchresultwidget.cpp b/src/plugins/coreplugin/find/searchresultwidget.cpp index 400f8e06370..c7827e6118e 100644 --- a/src/plugins/coreplugin/find/searchresultwidget.cpp +++ b/src/plugins/coreplugin/find/searchresultwidget.cpp @@ -348,6 +348,11 @@ void SearchResultWidget::setAutoExpandResults(bool expand) m_searchResultTreeView->setAutoExpandResults(expand); } +void SearchResultWidget::setRelativePaths(bool relative) +{ + m_searchResultTreeView->setRelativePaths(relative); +} + void SearchResultWidget::expandAll() { m_searchResultTreeView->expandAll(); diff --git a/src/plugins/coreplugin/find/searchresultwidget.h b/src/plugins/coreplugin/find/searchresultwidget.h index 4a40346343a..42aee6860a7 100644 --- a/src/plugins/coreplugin/find/searchresultwidget.h +++ b/src/plugins/coreplugin/find/searchresultwidget.h @@ -58,6 +58,7 @@ public: void setTabWidth(int tabWidth); void setAutoExpandResults(bool expand); + void setRelativePaths(bool relative); void expandAll(); void collapseAll(); diff --git a/src/plugins/coreplugin/find/searchresultwindow.cpp b/src/plugins/coreplugin/find/searchresultwindow.cpp index 58a9a2fcbe6..8412a57d707 100644 --- a/src/plugins/coreplugin/find/searchresultwindow.cpp +++ b/src/plugins/coreplugin/find/searchresultwindow.cpp @@ -27,6 +27,7 @@ static const char SETTINGSKEYSECTIONNAME[] = "SearchResults"; static const char SETTINGSKEYEXPANDRESULTS[] = "ExpandResults"; +static const char SETTINGSKEYRELATIVEPATHSRESULTS[] = "RelativePathsResults"; // Note that this is a soft limit: If all searches are still running, none of them will be // removed when a new one is started. @@ -73,6 +74,7 @@ namespace Internal { void moveWidgetToTop(SearchResultWidget *widget); void popupRequested(SearchResultWidget *widget, bool focus); void handleExpandCollapseToolButton(bool checked); + void handleRelativePathsToolButton(bool checked); void updateFilterButton(); int indexOfSearchToEvict() const; QList toolBarWidgets(); @@ -82,8 +84,11 @@ namespace Internal { QToolButton *m_expandCollapseButton = nullptr; QToolButton *m_filterButton; QToolButton *m_newSearchButton; + QToolButton *m_relativePathsButton = nullptr; QAction *m_expandCollapseAction = nullptr; + QAction *m_relativePathsAction = nullptr; static const bool m_initiallyExpand; + static const bool m_initiallyRelativePaths; QWidget *m_spacer; QLabel *m_historyLabel = nullptr; QWidget *m_spacer2; @@ -97,6 +102,7 @@ namespace Internal { }; const bool SearchResultWindowPrivate::m_initiallyExpand = false; + const bool SearchResultWindowPrivate::m_initiallyRelativePaths = false; SearchResultWindowPrivate::SearchResultWindowPrivate(SearchResultWindow *window, QWidget *nsp) : q(window), @@ -126,6 +132,17 @@ namespace Internal { m_expandCollapseButton->setDefaultAction(m_expandCollapseAction); Utils::StyleHelper::setPanelWidget(m_expandCollapseButton); + m_relativePathsButton = new QToolButton(m_widget); + + ActionBuilder(window, "Find.RelativePaths") + .setText(Tr::tr("Show Paths in Relation to Active Project")) + .setCheckable(true) + .setIconText("../") + .setEnabled(false) + .bindContextAction(&m_relativePathsAction) + .setCommandAttribute(Command::CA_UpdateText); + m_relativePathsButton->setDefaultAction(m_relativePathsAction); + m_filterButton = new QToolButton(m_widget); m_filterButton->setText(Tr::tr("Filter Results")); m_filterButton->setIcon(Utils::Icons::FILTER.icon()); @@ -141,6 +158,9 @@ namespace Internal { connect(m_expandCollapseAction, &QAction::toggled, this, &SearchResultWindowPrivate::handleExpandCollapseToolButton); + connect(m_relativePathsAction, &QAction::toggled, + this, &SearchResultWindowPrivate::handleRelativePathsToolButton); + connect(m_filterButton, &QToolButton::clicked, this, [this] { if (!isSearchVisible()) return; @@ -160,12 +180,14 @@ namespace Internal { if (focus) m_widget->currentWidget()->setFocus(); m_expandCollapseAction->setEnabled(false); + m_relativePathsAction->setEnabled(false); m_newSearchButton->setEnabled(false); } else { if (focus) m_searchResultWidgets.at(visibleSearchIndex())->setFocusInternally(); m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(true); m_expandCollapseAction->setEnabled(true); + m_relativePathsAction->setEnabled(true); m_newSearchButton->setEnabled(true); } q->navigateStateChanged(); @@ -485,6 +507,7 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label, bool supportsReplace = searchOrSearchAndReplace != SearchOnly; widget->setSupportsReplace(supportsReplace, supportsReplace ? cfgGroup : QString()); widget->setAutoExpandResults(d->m_expandCollapseAction->isChecked()); + widget->setRelativePaths(d->m_relativePathsAction->isChecked()); widget->setInfo(label, toolTip, searchTerm); auto result = new SearchResult(widget); d->m_searchResults.prepend(result); @@ -513,6 +536,7 @@ void SearchResultWindow::clearContents() d->m_currentIndex = 0; d->m_widget->currentWidget()->setFocus(); d->m_expandCollapseAction->setEnabled(false); + d->m_relativePathsAction->setEnabled(false); navigateStateChanged(); d->m_newSearchButton->setEnabled(false); @@ -594,6 +618,18 @@ void SearchResultWindowPrivate::handleExpandCollapseToolButton(bool checked) } } +void SearchResultWindowPrivate::handleRelativePathsToolButton(bool checked) +{ + if (!isSearchVisible()) + return; + m_searchResultWidgets.at(visibleSearchIndex())->setRelativePaths(checked); + if (checked) { + m_relativePathsAction->setText(Tr::tr("Show Full Paths")); + } else { + m_relativePathsAction->setText(Tr::tr("Show Paths in Relation to Active Project")); + } +} + void SearchResultWindowPrivate::updateFilterButton() { m_filterButton->setEnabled(isSearchVisible() @@ -624,6 +660,7 @@ QList SearchResultWindowPrivate::toolBarWidgets() return {m_expandCollapseButton, m_filterButton, m_newSearchButton, + m_relativePathsButton, m_spacer, m_historyLabel, m_spacer2, @@ -639,6 +676,8 @@ void SearchResultWindow::readSettings() s->beginGroup(SETTINGSKEYSECTIONNAME); d->m_expandCollapseAction->setChecked(s->value(SETTINGSKEYEXPANDRESULTS, SearchResultWindowPrivate::m_initiallyExpand).toBool()); + d->m_relativePathsAction->setChecked(s->value(SETTINGSKEYRELATIVEPATHSRESULTS, + SearchResultWindowPrivate::m_initiallyRelativePaths).toBool()); s->endGroup(); } @@ -652,6 +691,9 @@ void SearchResultWindow::writeSettings() s->setValueWithDefault(SETTINGSKEYEXPANDRESULTS, d->m_expandCollapseAction->isChecked(), SearchResultWindowPrivate::m_initiallyExpand); + s->setValueWithDefault(SETTINGSKEYRELATIVEPATHSRESULTS, + d->m_relativePathsAction->isChecked(), + SearchResultWindowPrivate::m_initiallyRelativePaths); s->endGroup(); } diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp index 623c7a6577a..d4fd0d10094 100644 --- a/src/plugins/coreplugin/icore.cpp +++ b/src/plugins/coreplugin/icore.cpp @@ -1093,6 +1093,25 @@ void ICore::restart() exit(); } +/*! + \internal +*/ +void ICore::setRelativePathToProjectFunction(const std::function &func) +{ + m_core->m_relativePathToProject = func; +} + +/*! + \internal +*/ +FilePath ICore::pathRelativeToActiveProject(const FilePath &path) +{ + if (m_core->m_relativePathToProject) + return m_core->m_relativePathToProject(path); + + return path; +} + /*! \internal */ diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h index 124845b3134..693262bba73 100644 --- a/src/plugins/coreplugin/icore.h +++ b/src/plugins/coreplugin/icore.h @@ -134,6 +134,8 @@ signals: public: /* internal use */ + static void setRelativePathToProjectFunction(const std::function &func); + static Utils::FilePath pathRelativeToActiveProject(const Utils::FilePath &path); static QStringList additionalAboutInformation(); static void clearAboutInformation(); static void appendAboutInformation(const QString &line); @@ -166,6 +168,9 @@ public: static IDocument *openFiles(const Utils::FilePaths &filePaths, OpenFilesFlags flags = None, const Utils::FilePath &workingDirectory = {}); + +private: + std::function m_relativePathToProject = nullptr; }; } // namespace Core diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 27390bf884c..11318ef9cec 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -2119,6 +2119,17 @@ void ProjectExplorerPlugin::extensionsInitialized() // Load devices immediately, as other plugins might want to use them DeviceManager::instance()->load(); + + Core::ICore::instance()->setRelativePathToProjectFunction([=](const FilePath& path) -> FilePath + { + ProjectExplorer::Project* p = ProjectExplorer::ProjectTree::currentProject(); + if (p) { + FilePath relPath = path.relativeChildPath(p->projectFilePath().absolutePath()); + return !relPath.isEmpty() ? relPath : path; + } else { + return path; + } + }); } bool ProjectExplorerPlugin::delayedInitialize()