diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 65fba9709f9..577a9f9487b 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -26,12 +26,13 @@ #include "coreplugin.h" #include "designmode.h" #include "editmode.h" -#include "idocument.h" #include "helpmanager.h" -#include "mainwindow.h" -#include "modemanager.h" +#include "idocument.h" #include "infobar.h" #include "iwizardfactory.h" +#include "mainwindow.h" +#include "menubarfilter.h" +#include "modemanager.h" #include "reaper_p.h" #include "themechooser.h" @@ -162,6 +163,8 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) InfoBar::initialize(ICore::settings(), creatorTheme()); } + addAutoReleasedObject(new MenuBarFilter); + IWizardFactory::initialize(); // Make sure we respect the process's umask when creating new files diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index dd6f03bdaa7..d5f1f7f51ed 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -111,7 +111,8 @@ SOURCES += corejsextensions.cpp \ externaltoolmanager.cpp \ systemsettings.cpp \ coreicons.cpp \ - diffservice.cpp + diffservice.cpp \ + menubarfilter.cpp HEADERS += corejsextensions.h \ mainwindow.h \ @@ -222,7 +223,8 @@ HEADERS += corejsextensions.h \ systemsettings.h \ coreicons.h \ editormanager/documentmodel_p.h \ - diffservice.h + diffservice.h \ + menubarfilter.h FORMS += dialogs/newdialog.ui \ dialogs/saveitemsdialog.ui \ diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index eabf668df71..109993bb115 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -32,79 +32,154 @@ Project { Group { name: "General" files: [ - "basefilewizard.cpp", "basefilewizard.h", - "basefilewizardfactory.cpp", "basefilewizardfactory.h", + "basefilewizard.cpp", + "basefilewizard.h", + "basefilewizardfactory.cpp", + "basefilewizardfactory.h", "core.qrc", "core_global.h", "coreconstants.h", - "coreicons.cpp", "coreicons.h", - "corejsextensions.cpp", "corejsextensions.h", - "coreplugin.cpp", "coreplugin.h", - "designmode.cpp", "designmode.h", - "diffservice.cpp", "diffservice.h", - "documentmanager.cpp", "documentmanager.h", - "editmode.cpp", "editmode.h", - "editortoolbar.cpp", "editortoolbar.h", - "externaltool.cpp", "externaltool.h", - "externaltoolmanager.cpp", "externaltoolmanager.h", - "fancyactionbar.cpp", "fancyactionbar.h", "fancyactionbar.qrc", - "fancytabwidget.cpp", "fancytabwidget.h", - "featureprovider.cpp", "featureprovider.h", - "fileiconprovider.cpp", "fileiconprovider.h", - "fileutils.cpp", "fileutils.h", - "findplaceholder.cpp", "findplaceholder.h", - "generalsettings.cpp", "generalsettings.h", "generalsettings.ui", - "generatedfile.cpp", "generatedfile.h", - "helpmanager.cpp", "helpmanager.h", - "icontext.cpp", "icontext.h", - "icore.cpp", "icore.h", - "id.cpp", "id.h", - "idocument.cpp", "idocument.h", - "idocumentfactory.cpp", "idocumentfactory.h", + "coreicons.cpp", + "coreicons.h", + "corejsextensions.cpp", + "corejsextensions.h", + "coreplugin.cpp", + "coreplugin.h", + "designmode.cpp", + "designmode.h", + "diffservice.cpp", + "diffservice.h", + "documentmanager.cpp", + "documentmanager.h", + "editmode.cpp", + "editmode.h", + "editortoolbar.cpp", + "editortoolbar.h", + "externaltool.cpp", + "externaltool.h", + "externaltoolmanager.cpp", + "externaltoolmanager.h", + "fancyactionbar.cpp", + "fancyactionbar.h", + "fancyactionbar.qrc", + "fancytabwidget.cpp", + "fancytabwidget.h", + "featureprovider.cpp", + "featureprovider.h", + "fileiconprovider.cpp", + "fileiconprovider.h", + "fileutils.cpp", + "fileutils.h", + "findplaceholder.cpp", + "findplaceholder.h", + "generalsettings.cpp", + "generalsettings.h", + "generalsettings.ui", + "generatedfile.cpp", + "generatedfile.h", + "helpmanager.cpp", + "helpmanager.h", + "icontext.cpp", + "icontext.h", + "icore.cpp", + "icore.h", + "id.cpp", + "id.h", + "idocument.cpp", + "idocument.h", + "idocumentfactory.cpp", + "idocumentfactory.h", "ifilewizardextension.h", - "imode.cpp", "imode.h", - "inavigationwidgetfactory.cpp", "inavigationwidgetfactory.h", - "infobar.cpp", "infobar.h", - "ioutputpane.cpp", "ioutputpane.h", - "iversioncontrol.cpp", "iversioncontrol.h", - "iwelcomepage.cpp", "iwelcomepage.h", - "iwizardfactory.cpp", "iwizardfactory.h", - "jsexpander.cpp", "jsexpander.h", - "mainwindow.cpp", "mainwindow.h", - "manhattanstyle.cpp", "manhattanstyle.h", - "messagebox.cpp", "messagebox.h", - "messagemanager.cpp", "messagemanager.h", - "messageoutputwindow.cpp", "messageoutputwindow.h", - "mimetypemagicdialog.cpp", "mimetypemagicdialog.h", "mimetypemagicdialog.ui", - "mimetypesettings.cpp", "mimetypesettings.h", + "imode.cpp", + "imode.h", + "inavigationwidgetfactory.cpp", + "inavigationwidgetfactory.h", + "infobar.cpp", + "infobar.h", + "ioutputpane.cpp", + "ioutputpane.h", + "iversioncontrol.cpp", + "iversioncontrol.h", + "iwelcomepage.cpp", + "iwelcomepage.h", + "iwizardfactory.cpp", + "iwizardfactory.h", + "jsexpander.cpp", + "jsexpander.h", + "mainwindow.cpp", + "mainwindow.h", + "manhattanstyle.cpp", + "manhattanstyle.h", + "menubarfilter.cpp", + "menubarfilter.h", + "messagebox.cpp", + "messagebox.h", + "messagemanager.cpp", + "messagemanager.h", + "messageoutputwindow.cpp", + "messageoutputwindow.h", + "mimetypemagicdialog.cpp", + "mimetypemagicdialog.h", + "mimetypemagicdialog.ui", + "mimetypesettings.cpp", + "mimetypesettings.h", "mimetypesettingspage.ui", - "minisplitter.cpp", "minisplitter.h", - "modemanager.cpp", "modemanager.h", - "navigationsubwidget.cpp", "navigationsubwidget.h", - "navigationwidget.cpp", "navigationwidget.h", - "opendocumentstreeview.cpp", "opendocumentstreeview.h", - "outputpane.cpp", "outputpane.h", - "outputpanemanager.cpp", "outputpanemanager.h", - "outputwindow.cpp", "outputwindow.h", - "patchtool.cpp", "patchtool.h", - "plugindialog.cpp", "plugindialog.h", - "reaper.cpp", "reaper.h", "reaper_p.h", - "rightpane.cpp", "rightpane.h", - "settingsdatabase.cpp", "settingsdatabase.h", - "shellcommand.cpp", "shellcommand.h", - "sidebar.cpp", "sidebar.h", - "sidebarwidget.cpp", "sidebarwidget.h", - "statusbarmanager.cpp", "statusbarmanager.h", - "statusbarwidget.cpp", "statusbarwidget.h", - "styleanimator.cpp", "styleanimator.h", - "systemsettings.cpp", "systemsettings.h", "systemsettings.ui", - "textdocument.cpp", "textdocument.h", - "themechooser.cpp", "themechooser.h", - "toolsettings.cpp", "toolsettings.h", - "variablechooser.cpp", "variablechooser.h", - "vcsmanager.cpp", "vcsmanager.h", - "versiondialog.cpp", "versiondialog.h", - "windowsupport.cpp", "windowsupport.h" + "minisplitter.cpp", + "minisplitter.h", + "modemanager.cpp", + "modemanager.h", + "navigationsubwidget.cpp", + "navigationsubwidget.h", + "navigationwidget.cpp", + "navigationwidget.h", + "opendocumentstreeview.cpp", + "opendocumentstreeview.h", + "outputpane.cpp", + "outputpane.h", + "outputpanemanager.cpp", + "outputpanemanager.h", + "outputwindow.cpp", + "outputwindow.h", + "patchtool.cpp", + "patchtool.h", + "plugindialog.cpp", + "plugindialog.h", + "reaper.cpp", + "reaper.h", + "reaper_p.h", + "rightpane.cpp", + "rightpane.h", + "settingsdatabase.cpp", + "settingsdatabase.h", + "shellcommand.cpp", + "shellcommand.h", + "sidebar.cpp", + "sidebar.h", + "sidebarwidget.cpp", + "sidebarwidget.h", + "statusbarmanager.cpp", + "statusbarmanager.h", + "statusbarwidget.cpp", + "statusbarwidget.h", + "styleanimator.cpp", + "styleanimator.h", + "systemsettings.cpp", + "systemsettings.h", + "systemsettings.ui", + "textdocument.cpp", + "textdocument.h", + "themechooser.cpp", + "themechooser.h", + "toolsettings.cpp", + "toolsettings.h", + "variablechooser.cpp", + "variablechooser.h", + "vcsmanager.cpp", + "vcsmanager.h", + "versiondialog.cpp", + "versiondialog.h", + "windowsupport.cpp", + "windowsupport.h", ] } diff --git a/src/plugins/coreplugin/menubarfilter.cpp b/src/plugins/coreplugin/menubarfilter.cpp new file mode 100644 index 00000000000..5c3c4414db8 --- /dev/null +++ b/src/plugins/coreplugin/menubarfilter.cpp @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "menubarfilter.h" + +#include "actionmanager/actioncontainer.h" +#include "actionmanager/actionmanager.h" +#include "coreconstants.h" + +#include +#include +#include +#include + +#include +#include +#include + +using namespace Core::Internal; +using namespace Core; + +MenuBarFilter::MenuBarFilter() +{ + setId("Actions from the menu"); + setDisplayName(tr("Actions from the Menu")); + setShortcutString("t"); +} + +static const QList menuBarActions() +{ + QMenuBar *menuBar = Core::ActionManager::actionContainer(Constants::MENU_BAR)->menuBar(); + QTC_ASSERT(menuBar, return {}); + return menuBar->actions(); +} + +QList MenuBarFilter::matchesFor(QFutureInterface &future, + const QString &entry) +{ + Q_UNUSED(future); + static const QString separators = ". >/"; + static const QRegularExpression seperatorRegExp(QString("[%1]").arg(separators)); + QList entries; + QString normalized = entry; + normalized.replace(seperatorRegExp, separators.at(0)); + const QStringList entryPath = normalized.split(separators.at(0), QString::SkipEmptyParts); + QVector processedMenus; + for (QAction* action : menuBarActions()) + entries << matchesForAction(action, entryPath, QStringList(), processedMenus); + + return entries; +} + +void MenuBarFilter::accept(LocatorFilterEntry selection, QString *newText, + int *selectionStart, int *selectionLength) const +{ + Q_UNUSED(newText); + Q_UNUSED(selectionStart); + Q_UNUSED(selectionLength); + if (auto action = selection.internalData.value>()) + action->trigger(); +} + +void MenuBarFilter::refresh(QFutureInterface &future) +{ + Q_UNUSED(future); +} + +QList MenuBarFilter::matchesForAction(QAction *action, + const QStringList &entryPath, + const QStringList &path, + QVector &processedMenus) +{ + QList entries; + if (!action->isEnabled()) + return entries; + const QString text = Utils::stripAccelerator(action->text()); + if (QMenu *menu = action->menu()) { + if (processedMenus.contains(menu)) + return entries; + processedMenus.append(menu); + if (menu->isEnabled()) { + const QList &actions = menu->actions(); + QStringList menuPath(path); + menuPath << text; + for (QAction *menuAction : actions) + entries << matchesForAction(menuAction, entryPath, menuPath, processedMenus); + } + } else if (!text.isEmpty()) { + int entryIndex = 0; + int entryLength = 0; + int pathIndex = 0; + LocatorFilterEntry::HighlightInfo::DataType highlightType = + LocatorFilterEntry::HighlightInfo::DisplayName; + const QString pathText = path.join(" > "); + QStringList actionPath(path); + if (!entryPath.isEmpty()) { + actionPath << text; + for (const QString &entry : entryPath) { + const QRegularExpression re(".*" + entry + ".*", + QRegularExpression::CaseInsensitiveOption); + pathIndex = actionPath.indexOf(re, pathIndex); + if (pathIndex < 0) + return entries; + } + const QString &lastEntry(entryPath.last()); + entryLength = lastEntry.length(); + entryIndex = text.indexOf(lastEntry, 0, Qt::CaseInsensitive); + if (entryIndex >= 0) { + highlightType = LocatorFilterEntry::HighlightInfo::DisplayName; + } else { + entryIndex = pathText.indexOf(lastEntry, 0, Qt::CaseInsensitive); + QTC_ASSERT(entryIndex >= 0, return entries); + highlightType = LocatorFilterEntry::HighlightInfo::ExtraInfo; + } + } + LocatorFilterEntry filterEntry(this, text, QVariant(), action->icon()); + filterEntry.internalData.setValue(QPointer(action)); + filterEntry.extraInfo = pathText; + filterEntry.highlightInfo = {entryIndex, entryLength, highlightType}; + entries << filterEntry; + } + return entries; +} + +static void requestMenuUpdate(const QAction* action) +{ + if (QMenu *menu = action->menu()) { + emit menu->aboutToShow(); + const QList &actions = menu->actions(); + for (const QAction *menuActions : actions) + requestMenuUpdate(menuActions); + } +} + +void Core::Internal::MenuBarFilter::prepareSearch(const QString &entry) +{ + Q_UNUSED(entry); + for (const QAction *action : menuBarActions()) + requestMenuUpdate(action); +} diff --git a/src/plugins/coreplugin/menubarfilter.h b/src/plugins/coreplugin/menubarfilter.h new file mode 100644 index 00000000000..9251df7da26 --- /dev/null +++ b/src/plugins/coreplugin/menubarfilter.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QMenu; +QT_END_NAMESPACE + +namespace Core { +namespace Internal { + +class MenuBarFilter : public ILocatorFilter +{ +public: + MenuBarFilter(); + + QList matchesFor(QFutureInterface &future, + const QString &entry) override; + void accept(LocatorFilterEntry selection, QString *newText, + int *selectionStart, int *selectionLength) const override; + void refresh(QFutureInterface &future) override; + void prepareSearch(const QString &entry) override; +private: + QList matchesForAction(QAction *action, + const QStringList &entryPath, + const QStringList &path, + QVector &processedMenus); + +}; + +} // namespace Internal +} // namespace Core