forked from qt-creator/qt-creator
The editor factories are already a central place to associate hover handlers with editors, no need to retrieve them later from the object pool again. This also allows for easy handling of more than one active handler per editor. Change-Id: Ie716b96f5ce6b526ee897468635e03e909d81538 Reviewed-by: David Schulz <david.schulz@digia.com>
407 lines
16 KiB
C++
407 lines
16 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
|
** Contact: http://www.qt-project.org/legal
|
|
**
|
|
** 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 Digia. For licensing terms and
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "cppeditorplugin.h"
|
|
|
|
#include "cppautocompleter.h"
|
|
#include "cppclasswizard.h"
|
|
#include "cppcodemodelinspectordialog.h"
|
|
#include "cppeditorconstants.h"
|
|
#include "cppeditor.h"
|
|
#include "cppeditordocument.h"
|
|
#include "cppeditoroutline.h"
|
|
#include "cpphighlighter.h"
|
|
#include "cpphoverhandler.h"
|
|
#include "cppincludehierarchy.h"
|
|
#include "cppoutline.h"
|
|
#include "cppquickfixassistant.h"
|
|
#include "cppquickfixes.h"
|
|
#include "cppsnippetprovider.h"
|
|
#include "cpptypehierarchy.h"
|
|
|
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
|
#include <coreplugin/actionmanager/actionmanager.h>
|
|
#include <coreplugin/coreconstants.h>
|
|
#include <coreplugin/fileiconprovider.h>
|
|
#include <coreplugin/icore.h>
|
|
#include <coreplugin/navigationwidget.h>
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
|
#include <cpptools/cpptoolsconstants.h>
|
|
#include <texteditor/texteditoractionhandler.h>
|
|
#include <texteditor/texteditorconstants.h>
|
|
#include <texteditor/highlighterfactory.h>
|
|
|
|
#include <utils/hostosinfo.h>
|
|
|
|
#include <QCoreApplication>
|
|
#include <QStringList>
|
|
|
|
using namespace Core;
|
|
using namespace TextEditor;
|
|
|
|
namespace CppEditor {
|
|
namespace Internal {
|
|
|
|
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
|
|
|
|
enum { QUICKFIX_INTERVAL = 20 };
|
|
|
|
//////////////////////////// CppEditorFactory /////////////////////////////
|
|
|
|
class CppEditorFactory : public TextEditorFactory
|
|
{
|
|
public:
|
|
CppEditorFactory()
|
|
{
|
|
setId(Constants::CPPEDITOR_ID);
|
|
setDisplayName(qApp->translate("OpenWith::Editors", Constants::CPPEDITOR_DISPLAY_NAME));
|
|
addMimeType(Constants::C_SOURCE_MIMETYPE);
|
|
addMimeType(Constants::C_HEADER_MIMETYPE);
|
|
addMimeType(Constants::CPP_SOURCE_MIMETYPE);
|
|
addMimeType(Constants::CPP_HEADER_MIMETYPE);
|
|
|
|
setDocumentCreator([]() { return new CppEditorDocument; });
|
|
setEditorWidgetCreator([]() { return new CppEditorWidget; });
|
|
setEditorCreator([]() { return new CppEditor; });
|
|
setAutoCompleterCreator([]() { return new CppAutoCompleter; });
|
|
setCommentStyle(Utils::CommentDefinition::CppStyle);
|
|
|
|
setEditorActionHandlers(TextEditorActionHandler::Format
|
|
| TextEditorActionHandler::UnCommentSelection
|
|
| TextEditorActionHandler::UnCollapseAll
|
|
| TextEditorActionHandler::FollowSymbolUnderCursor);
|
|
|
|
addHoverHandler(new CppHoverHandler);
|
|
|
|
if (!Utils::HostOsInfo::isMacHost() && !Utils::HostOsInfo::isWindowsHost()) {
|
|
FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_cpp.png", Constants::CPP_SOURCE_MIMETYPE);
|
|
FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_c.png", Constants::C_SOURCE_MIMETYPE);
|
|
FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_h.png", Constants::CPP_HEADER_MIMETYPE);
|
|
}
|
|
}
|
|
};
|
|
|
|
///////////////////////////////// CppEditorPlugin //////////////////////////////////
|
|
|
|
CppEditorPlugin *CppEditorPlugin::m_instance = 0;
|
|
|
|
CppEditorPlugin::CppEditorPlugin() :
|
|
m_sortedOutline(true),
|
|
m_renameSymbolUnderCursorAction(0),
|
|
m_findUsagesAction(0),
|
|
m_reparseExternallyChangedFiles(0),
|
|
m_openTypeHierarchyAction(0),
|
|
m_openIncludeHierarchyAction(0),
|
|
m_quickFixProvider(0)
|
|
{
|
|
m_instance = this;
|
|
}
|
|
|
|
CppEditorPlugin::~CppEditorPlugin()
|
|
{
|
|
m_instance = 0;
|
|
}
|
|
|
|
CppEditorPlugin *CppEditorPlugin::instance()
|
|
{
|
|
return m_instance;
|
|
}
|
|
|
|
void CppEditorPlugin::setSortedOutline(bool sorted)
|
|
{
|
|
m_sortedOutline = sorted;
|
|
emit outlineSortingChanged(sorted);
|
|
}
|
|
|
|
bool CppEditorPlugin::sortedOutline() const
|
|
{
|
|
return m_sortedOutline;
|
|
}
|
|
|
|
CppQuickFixAssistProvider *CppEditorPlugin::quickFixProvider() const
|
|
{
|
|
return m_quickFixProvider;
|
|
}
|
|
|
|
bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage)
|
|
{
|
|
if (!Core::MimeDatabase::addMimeTypes(QLatin1String(":/cppeditor/CppEditor.mimetypes.xml"), errorMessage))
|
|
return false;
|
|
|
|
addAutoReleasedObject(new CppEditorFactory);
|
|
addAutoReleasedObject(new CppOutlineWidgetFactory);
|
|
addAutoReleasedObject(new CppTypeHierarchyFactory);
|
|
addAutoReleasedObject(new CppIncludeHierarchyFactory);
|
|
addAutoReleasedObject(new CppSnippetProvider);
|
|
|
|
auto hf = new TextEditor::HighlighterFactory;
|
|
hf->setProductType<CppHighlighter>();
|
|
hf->setId(Constants::CPPEDITOR_ID);
|
|
hf->addMimeType(Constants::C_SOURCE_MIMETYPE);
|
|
hf->addMimeType(Constants::C_HEADER_MIMETYPE);
|
|
hf->addMimeType(Constants::CPP_SOURCE_MIMETYPE);
|
|
hf->addMimeType(Constants::CPP_HEADER_MIMETYPE);
|
|
addAutoReleasedObject(hf);
|
|
|
|
m_quickFixProvider = new CppQuickFixAssistProvider;
|
|
addAutoReleasedObject(m_quickFixProvider);
|
|
registerQuickFixes(this);
|
|
|
|
QString trCat = QCoreApplication::translate(Constants::WIZARD_CATEGORY, Constants::WIZARD_TR_CATEGORY);
|
|
|
|
IWizardFactory *wizard = new CppClassWizard;
|
|
wizard->setWizardKind(IWizardFactory::ClassWizard);
|
|
wizard->setCategory(QLatin1String(Constants::WIZARD_CATEGORY));
|
|
wizard->setDisplayCategory(trCat);
|
|
wizard->setDisplayName(tr("C++ Class"));
|
|
wizard->setId(QLatin1String("A.Class"));
|
|
wizard->setDescription(tr("Creates a C++ header and a source file for a new class that you can add to a C++ project."));
|
|
addAutoReleasedObject(wizard);
|
|
|
|
Context context(Constants::CPPEDITOR_ID);
|
|
|
|
ActionContainer *contextMenu = ActionManager::createMenu(Constants::M_CONTEXT);
|
|
|
|
Command *cmd;
|
|
ActionContainer *cppToolsMenu = ActionManager::actionContainer(CppTools::Constants::M_TOOLS_CPP);
|
|
|
|
cmd = ActionManager::command(CppTools::Constants::SWITCH_HEADER_SOURCE);
|
|
contextMenu->addAction(cmd);
|
|
|
|
cmd = ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR);
|
|
contextMenu->addAction(cmd);
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives..."), this);
|
|
cmd = ActionManager::registerAction(openPreprocessorDialog,
|
|
Constants::OPEN_PREPROCESSOR_DIALOG, context);
|
|
cmd->setDefaultKeySequence(QKeySequence());
|
|
connect(openPreprocessorDialog, SIGNAL(triggered()), this, SLOT(showPreProcessorDialog()));
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
QAction *switchDeclarationDefinition = new QAction(tr("Switch Between Function Declaration/Definition"), this);
|
|
cmd = ActionManager::registerAction(switchDeclarationDefinition,
|
|
Constants::SWITCH_DECLARATION_DEFINITION, context, true);
|
|
cmd->setDefaultKeySequence(QKeySequence(tr("Shift+F2")));
|
|
connect(switchDeclarationDefinition, SIGNAL(triggered()),
|
|
this, SLOT(switchDeclarationDefinition()));
|
|
contextMenu->addAction(cmd);
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
cmd = ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT);
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
QAction *openDeclarationDefinitionInNextSplit =
|
|
new QAction(tr("Open Function Declaration/Definition in Next Split"), this);
|
|
cmd = ActionManager::registerAction(openDeclarationDefinitionInNextSplit,
|
|
Constants::OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT, context, true);
|
|
cmd->setDefaultKeySequence(QKeySequence(Utils::HostOsInfo::isMacHost()
|
|
? tr("Meta+E, Shift+F2")
|
|
: tr("Ctrl+E, Shift+F2")));
|
|
connect(openDeclarationDefinitionInNextSplit, SIGNAL(triggered()),
|
|
this, SLOT(openDeclarationDefinitionInNextSplit()));
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
m_findUsagesAction = new QAction(tr("Find Usages"), this);
|
|
cmd = ActionManager::registerAction(m_findUsagesAction, Constants::FIND_USAGES, context);
|
|
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+U")));
|
|
connect(m_findUsagesAction, SIGNAL(triggered()), this, SLOT(findUsages()));
|
|
contextMenu->addAction(cmd);
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
m_openTypeHierarchyAction = new QAction(tr("Open Type Hierarchy"), this);
|
|
cmd = ActionManager::registerAction(m_openTypeHierarchyAction, Constants::OPEN_TYPE_HIERARCHY, context);
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+Shift+T") : tr("Ctrl+Shift+T")));
|
|
connect(m_openTypeHierarchyAction, SIGNAL(triggered()), this, SLOT(openTypeHierarchy()));
|
|
contextMenu->addAction(cmd);
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
m_openIncludeHierarchyAction = new QAction(tr("Open Include Hierarchy"), this);
|
|
cmd = Core::ActionManager::registerAction(m_openIncludeHierarchyAction, Constants::OPEN_INCLUDE_HIERARCHY, context);
|
|
cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+I") : tr("Ctrl+Shift+I")));
|
|
connect(m_openIncludeHierarchyAction, SIGNAL(triggered()), this, SLOT(openIncludeHierarchy()));
|
|
contextMenu->addAction(cmd);
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
// Refactoring sub-menu
|
|
Context globalContext(Core::Constants::C_GLOBAL);
|
|
Command *sep = contextMenu->addSeparator(globalContext);
|
|
sep->action()->setObjectName(QLatin1String(Constants::M_REFACTORING_MENU_INSERTION_POINT));
|
|
contextMenu->addSeparator(globalContext);
|
|
|
|
m_renameSymbolUnderCursorAction = new QAction(tr("Rename Symbol Under Cursor"),
|
|
this);
|
|
cmd = ActionManager::registerAction(m_renameSymbolUnderCursorAction,
|
|
Constants::RENAME_SYMBOL_UNDER_CURSOR,
|
|
context);
|
|
cmd->setDefaultKeySequence(QKeySequence(tr("CTRL+SHIFT+R")));
|
|
connect(m_renameSymbolUnderCursorAction, SIGNAL(triggered()),
|
|
this, SLOT(renameSymbolUnderCursor()));
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
// Update context in global context
|
|
cppToolsMenu->addSeparator(globalContext);
|
|
m_reparseExternallyChangedFiles = new QAction(tr("Reparse Externally Changed Files"), this);
|
|
cmd = ActionManager::registerAction(m_reparseExternallyChangedFiles, Constants::UPDATE_CODEMODEL, globalContext);
|
|
CppTools::CppModelManager *cppModelManager = CppTools::CppModelManager::instance();
|
|
connect(m_reparseExternallyChangedFiles, SIGNAL(triggered()), cppModelManager, SLOT(updateModifiedSourceFiles()));
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
cppToolsMenu->addSeparator(globalContext);
|
|
QAction *inspectCppCodeModel = new QAction(tr("Inspect C++ Code Model..."), this);
|
|
cmd = ActionManager::registerAction(inspectCppCodeModel, Constants::INSPECT_CPP_CODEMODEL, globalContext);
|
|
cmd->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+F12") : tr("Ctrl+Shift+F12")));
|
|
connect(inspectCppCodeModel, SIGNAL(triggered()), this, SLOT(inspectCppCodeModel()));
|
|
cppToolsMenu->addAction(cmd);
|
|
|
|
contextMenu->addSeparator(context);
|
|
|
|
cmd = ActionManager::command(TextEditor::Constants::AUTO_INDENT_SELECTION);
|
|
contextMenu->addAction(cmd);
|
|
|
|
cmd = ActionManager::command(TextEditor::Constants::UN_COMMENT_SELECTION);
|
|
contextMenu->addAction(cmd);
|
|
|
|
connect(ProgressManager::instance(), SIGNAL(taskStarted(Core::Id)),
|
|
this, SLOT(onTaskStarted(Core::Id)));
|
|
connect(ProgressManager::instance(), SIGNAL(allTasksFinished(Core::Id)),
|
|
this, SLOT(onAllTasksFinished(Core::Id)));
|
|
|
|
readSettings();
|
|
return true;
|
|
}
|
|
|
|
void CppEditorPlugin::readSettings()
|
|
{
|
|
m_sortedOutline = ICore::settings()->value(QLatin1String("CppTools/SortedMethodOverview"), true).toBool();
|
|
}
|
|
|
|
void CppEditorPlugin::writeSettings()
|
|
{
|
|
ICore::settings()->setValue(QLatin1String("CppTools/SortedMethodOverview"), m_sortedOutline);
|
|
}
|
|
|
|
void CppEditorPlugin::extensionsInitialized()
|
|
{
|
|
}
|
|
|
|
ExtensionSystem::IPlugin::ShutdownFlag CppEditorPlugin::aboutToShutdown()
|
|
{
|
|
writeSettings();
|
|
return SynchronousShutdown;
|
|
}
|
|
|
|
static CppEditorWidget *currentCppEditorWidget()
|
|
{
|
|
return qobject_cast<CppEditorWidget*>(EditorManager::currentEditor()->widget());
|
|
}
|
|
|
|
void CppEditorPlugin::switchDeclarationDefinition()
|
|
{
|
|
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
|
|
editorWidget->switchDeclarationDefinition(/*inNextSplit*/ false);
|
|
}
|
|
|
|
void CppEditorPlugin::openDeclarationDefinitionInNextSplit()
|
|
{
|
|
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
|
|
editorWidget->switchDeclarationDefinition(/*inNextSplit*/ true);
|
|
}
|
|
|
|
void CppEditorPlugin::renameSymbolUnderCursor()
|
|
{
|
|
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
|
|
editorWidget->renameSymbolUnderCursor();
|
|
}
|
|
|
|
void CppEditorPlugin::findUsages()
|
|
{
|
|
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
|
|
editorWidget->findUsages();
|
|
}
|
|
|
|
void CppEditorPlugin::showPreProcessorDialog()
|
|
{
|
|
if (CppEditorWidget *editorWidget = currentCppEditorWidget())
|
|
editorWidget->showPreProcessorWidget();
|
|
}
|
|
|
|
void CppEditorPlugin::onTaskStarted(Core::Id type)
|
|
{
|
|
if (type == CppTools::Constants::TASK_INDEX) {
|
|
m_renameSymbolUnderCursorAction->setEnabled(false);
|
|
m_findUsagesAction->setEnabled(false);
|
|
m_reparseExternallyChangedFiles->setEnabled(false);
|
|
m_openTypeHierarchyAction->setEnabled(false);
|
|
m_openIncludeHierarchyAction->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
void CppEditorPlugin::onAllTasksFinished(Core::Id type)
|
|
{
|
|
if (type == CppTools::Constants::TASK_INDEX) {
|
|
m_renameSymbolUnderCursorAction->setEnabled(true);
|
|
m_findUsagesAction->setEnabled(true);
|
|
m_reparseExternallyChangedFiles->setEnabled(true);
|
|
m_openTypeHierarchyAction->setEnabled(true);
|
|
m_openIncludeHierarchyAction->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
void CppEditorPlugin::inspectCppCodeModel()
|
|
{
|
|
if (m_cppCodeModelInspectorDialog) {
|
|
ICore::raiseWindow(m_cppCodeModelInspectorDialog);
|
|
} else {
|
|
m_cppCodeModelInspectorDialog = new CppCodeModelInspectorDialog(ICore::mainWindow());
|
|
m_cppCodeModelInspectorDialog->show();
|
|
}
|
|
}
|
|
|
|
void CppEditorPlugin::openTypeHierarchy()
|
|
{
|
|
if (currentCppEditorWidget()) {
|
|
NavigationWidget *navigation = NavigationWidget::instance();
|
|
navigation->activateSubWidget(Constants::TYPE_HIERARCHY_ID);
|
|
emit typeHierarchyRequested();
|
|
}
|
|
}
|
|
|
|
void CppEditorPlugin::openIncludeHierarchy()
|
|
{
|
|
if (currentCppEditorWidget()) {
|
|
Core::NavigationWidget *navigation = Core::NavigationWidget::instance();
|
|
navigation->activateSubWidget(Core::Id(Constants::INCLUDE_HIERARCHY_ID));
|
|
emit includeHierarchyRequested();
|
|
}
|
|
}
|
|
|
|
} // namespace Internal
|
|
} // namespace CppEditor
|