cppeditorplugin.cpp 16.4 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** 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.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

30
#include "cppeditorplugin.h"
31

32
#include "cppclasswizard.h"
con's avatar
con committed
33 34 35
#include "cppeditor.h"
#include "cppeditorconstants.h"
#include "cppfilewizard.h"
36
#include "cpphoverhandler.h"
37
#include "cppoutline.h"
38
#include "cpptypehierarchy.h"
39
#include "cppincludehierarchy.h"
40
#include "cppsnippetprovider.h"
Leandro Melo's avatar
Leandro Melo committed
41
#include "cppquickfixassistant.h"
Nikolai Kosjar's avatar
Nikolai Kosjar committed
42
#include "cppquickfixes.h"
43
#include "cpphighlighterfactory.h"
con's avatar
con committed
44

45 46
#include "cppcodemodelinspectordialog.h"

47
#include <coreplugin/actionmanager/actioncontainer.h>
48 49 50 51
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
52
#include <coreplugin/navigationwidget.h>
53 54
#include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cpptoolsconstants.h>
55
#include <texteditor/texteditoractionhandler.h>
con's avatar
con committed
56
#include <texteditor/texteditorsettings.h>
57

58
#include <utils/hostosinfo.h>
con's avatar
con committed
59

60 61
#include <QCoreApplication>
#include <QStringList>
con's avatar
con committed
62

63
using namespace Core;
64
using namespace CppEditor;
con's avatar
con committed
65 66
using namespace CppEditor::Internal;

Leandro Melo's avatar
Leandro Melo committed
67 68
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);

69 70
enum { QUICKFIX_INTERVAL = 20 };

71
//////////////////////////// CppEditorFactory /////////////////////////////
con's avatar
con committed
72

73
CppEditorFactory::CppEditorFactory(CppEditorPlugin *owner) :
con's avatar
con committed
74 75
    m_owner(owner)
{
76 77 78 79 80 81
    setId(CppEditor::Constants::CPPEDITOR_ID);
    setDisplayName(qApp->translate("OpenWith::Editors", CppEditor::Constants::CPPEDITOR_DISPLAY_NAME));
    addMimeType(CppEditor::Constants::C_SOURCE_MIMETYPE);
    addMimeType(CppEditor::Constants::C_HEADER_MIMETYPE);
    addMimeType(CppEditor::Constants::CPP_SOURCE_MIMETYPE);
    addMimeType(CppEditor::Constants::CPP_HEADER_MIMETYPE);
82

83 84 85 86 87 88
    new TextEditor::TextEditorActionHandler(this, CppEditor::Constants::C_CPPEDITOR,
        TextEditor::TextEditorActionHandler::Format
        | TextEditor::TextEditorActionHandler::UnCommentSelection
        | TextEditor::TextEditorActionHandler::UnCollapseAll
        | TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor);

89
    if (!Utils::HostOsInfo::isMacHost() && !Utils::HostOsInfo::isWindowsHost()) {
90 91 92
        FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_cpp.png", CppEditor::Constants::CPP_SOURCE_MIMETYPE);
        FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_c.png", CppEditor::Constants::C_SOURCE_MIMETYPE);
        FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_h.png", CppEditor::Constants::CPP_HEADER_MIMETYPE);
93
    }
con's avatar
con committed
94 95
}

96
IEditor *CppEditorFactory::createEditor()
con's avatar
con committed
97
{
98
    CPPEditorWidget *editor = new CPPEditorWidget();
con's avatar
con committed
99 100
    editor->setRevisionsVisible(true);
    m_owner->initializeEditor(editor);
101
    return editor->editor();
con's avatar
con committed
102 103
}

104
///////////////////////////////// CppEditorPlugin //////////////////////////////////
con's avatar
con committed
105

106
CppEditorPlugin *CppEditorPlugin::m_instance = 0;
con's avatar
con committed
107

108
CppEditorPlugin::CppEditorPlugin() :
109
    m_sortedOutline(true),
110 111
    m_renameSymbolUnderCursorAction(0),
    m_findUsagesAction(0),
112
    m_reparseExternallyChangedFiles(0),
Leandro Melo's avatar
Leandro Melo committed
113
    m_openTypeHierarchyAction(0),
114
    m_openIncludeHierarchyAction(0),
Leandro Melo's avatar
Leandro Melo committed
115
    m_quickFixProvider(0)
con's avatar
con committed
116 117 118 119
{
    m_instance = this;
}

120
CppEditorPlugin::~CppEditorPlugin()
con's avatar
con committed
121 122 123 124
{
    m_instance = 0;
}

125
CppEditorPlugin *CppEditorPlugin::instance()
con's avatar
con committed
126 127 128 129
{
    return m_instance;
}

130
void CppEditorPlugin::initializeEditor(CPPEditorWidget *editor)
con's avatar
con committed
131
{
Orgad Shaneh's avatar
Orgad Shaneh committed
132
    editor->setLanguageSettingsId(CppTools::Constants::CPP_SETTINGS_ID);
133
    TextEditor::TextEditorSettings::initializeEditor(editor);
con's avatar
con committed
134

135
    // function combo box sorting
Kai Koehne's avatar
Kai Koehne committed
136 137
    connect(this, SIGNAL(outlineSortingChanged(bool)),
            editor, SLOT(setSortedOutline(bool)));
138 139
}

140
void CppEditorPlugin::setSortedOutline(bool sorted)
141
{
Kai Koehne's avatar
Kai Koehne committed
142 143
    m_sortedOutline = sorted;
    emit outlineSortingChanged(sorted);
144 145
}

146
bool CppEditorPlugin::sortedOutline() const
147
{
Kai Koehne's avatar
Kai Koehne committed
148
    return m_sortedOutline;
con's avatar
con committed
149 150
}

151
CppQuickFixAssistProvider *CppEditorPlugin::quickFixProvider() const
Leandro Melo's avatar
Leandro Melo committed
152 153 154
{
    return m_quickFixProvider;
}
155

156
bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage)
con's avatar
con committed
157
{
hjk's avatar
hjk committed
158
    if (!Core::MimeDatabase::addMimeTypes(QLatin1String(":/cppeditor/CppEditor.mimetypes.xml"), errorMessage))
con's avatar
con committed
159 160
        return false;

161
    addAutoReleasedObject(new CppEditorFactory(this));
162
    addAutoReleasedObject(new CppHoverHandler);
163
    addAutoReleasedObject(new CppOutlineWidgetFactory);
164
    addAutoReleasedObject(new CppTypeHierarchyFactory);
165
    addAutoReleasedObject(new CppIncludeHierarchyFactory);
166
    addAutoReleasedObject(new CppSnippetProvider);
167
    addAutoReleasedObject(new CppHighlighterFactory);
168

Leandro Melo's avatar
Leandro Melo committed
169 170
    m_quickFixProvider = new CppQuickFixAssistProvider;
    addAutoReleasedObject(m_quickFixProvider);
Nikolai Kosjar's avatar
Nikolai Kosjar committed
171
    CppEditor::Internal::registerQuickFixes(this);
Roberto Raggi's avatar
Roberto Raggi committed
172

hjk's avatar
hjk committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    QString trCat = QCoreApplication::translate(Constants::WIZARD_CATEGORY, Constants::WIZARD_TR_CATEGORY);

    IWizard *wizard = new CppClassWizard;
    wizard->setWizardKind(IWizard::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);

    wizard = new CppFileWizard(Source);
    wizard->setWizardKind(IWizard::FileWizard);
    wizard->setCategory(QLatin1String(Constants::WIZARD_CATEGORY));
    wizard->setDisplayCategory(trCat);
    wizard->setDisplayName(tr("C++ Class"));
    wizard->setDescription(tr("Creates a C++ source file that you can add to a C++ project."));
    wizard->setDisplayName(tr("C++ Source File"));
    wizard->setId(QLatin1String("B.Source"));
    addAutoReleasedObject(wizard);

    wizard = new CppFileWizard(Header);
    wizard->setWizardKind(IWizard::FileWizard);
    wizard->setCategory(QLatin1String(Constants::WIZARD_CATEGORY));
    wizard->setDisplayCategory(trCat);
    wizard->setDescription(tr("Creates a C++ header file that you can add to a C++ project."));
    wizard->setDisplayName(tr("C++ Header File"));
    wizard->setId(QLatin1String("C.Header"));
    addAutoReleasedObject(wizard);
con's avatar
con committed
202

203
    Context context(CppEditor::Constants::C_CPPEDITOR);
con's avatar
con committed
204

205
    ActionContainer *contextMenu = ActionManager::createMenu(CppEditor::Constants::M_CONTEXT);
con's avatar
con committed
206

207 208
    Command *cmd;
    ActionContainer *cppToolsMenu = ActionManager::actionContainer(CppTools::Constants::M_TOOLS_CPP);
con's avatar
con committed
209

210
    cmd = ActionManager::command(CppTools::Constants::SWITCH_HEADER_SOURCE);
211 212
    contextMenu->addAction(cmd);

213
    cmd = ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR);
mae's avatar
mae committed
214
    contextMenu->addAction(cmd);
215
    cppToolsMenu->addAction(cmd);
con's avatar
con committed
216

217
    QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives..."), this);
218 219 220 221 222 223
    cmd = ActionManager::registerAction(openPreprocessorDialog,
                                        Constants::OPEN_PREPROCESSOR_DIALOG, context);
    cmd->setDefaultKeySequence(QKeySequence());
    connect(openPreprocessorDialog, SIGNAL(triggered()), this, SLOT(showPreProcessorDialog()));
    cppToolsMenu->addAction(cmd);

224
    QAction *switchDeclarationDefinition = new QAction(tr("Switch Between Function Declaration/Definition"), this);
225
    cmd = ActionManager::registerAction(switchDeclarationDefinition,
226
        Constants::SWITCH_DECLARATION_DEFINITION, context, true);
227
    cmd->setDefaultKeySequence(QKeySequence(tr("Shift+F2")));
con's avatar
con committed
228 229
    connect(switchDeclarationDefinition, SIGNAL(triggered()),
            this, SLOT(switchDeclarationDefinition()));
mae's avatar
mae committed
230
    contextMenu->addAction(cmd);
231
    cppToolsMenu->addAction(cmd);
con's avatar
con committed
232

233
    cmd = ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT);
234 235 236
    cppToolsMenu->addAction(cmd);

    QAction *openDeclarationDefinitionInNextSplit =
237
            new QAction(tr("Open Function Declaration/Definition in Next Split"), this);
238
    cmd = ActionManager::registerAction(openDeclarationDefinitionInNextSplit,
239
        Constants::OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT, context, true);
240 241 242
    cmd->setDefaultKeySequence(QKeySequence(Utils::HostOsInfo::isMacHost()
                                            ? tr("Meta+E, Shift+F2")
                                            : tr("Ctrl+E, Shift+F2")));
243 244 245 246
    connect(openDeclarationDefinitionInNextSplit, SIGNAL(triggered()),
            this, SLOT(openDeclarationDefinitionInNextSplit()));
    cppToolsMenu->addAction(cmd);

247
    m_findUsagesAction = new QAction(tr("Find Usages"), this);
248
    cmd = ActionManager::registerAction(m_findUsagesAction, Constants::FIND_USAGES, context);
249
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+U")));
250
    connect(m_findUsagesAction, SIGNAL(triggered()), this, SLOT(findUsages()));
251
    contextMenu->addAction(cmd);
252
    cppToolsMenu->addAction(cmd);
253

254
    m_openTypeHierarchyAction = new QAction(tr("Open Type Hierarchy"), this);
255 256
    cmd = ActionManager::registerAction(m_openTypeHierarchyAction, Constants::OPEN_TYPE_HIERARCHY, context);
    cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+Shift+T") : tr("Ctrl+Shift+T")));
257 258 259 260
    connect(m_openTypeHierarchyAction, SIGNAL(triggered()), this, SLOT(openTypeHierarchy()));
    contextMenu->addAction(cmd);
    cppToolsMenu->addAction(cmd);

261 262 263 264 265 266 267
    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);

268
    // Refactoring sub-menu
269 270
    Context globalContext(Core::Constants::C_GLOBAL);
    Command *sep = contextMenu->addSeparator(globalContext);
271
    sep->action()->setObjectName(QLatin1String(Constants::M_REFACTORING_MENU_INSERTION_POINT));
272
    contextMenu->addSeparator(globalContext);
273 274 275

    m_renameSymbolUnderCursorAction = new QAction(tr("Rename Symbol Under Cursor"),
                                                  this);
276
    cmd = ActionManager::registerAction(m_renameSymbolUnderCursorAction,
277 278
                             Constants::RENAME_SYMBOL_UNDER_CURSOR,
                             context);
279
    cmd->setDefaultKeySequence(QKeySequence(tr("CTRL+SHIFT+R")));
280 281 282 283 284
    connect(m_renameSymbolUnderCursorAction, SIGNAL(triggered()),
            this, SLOT(renameSymbolUnderCursor()));
    cppToolsMenu->addAction(cmd);

    // Update context in global context
285
    cppToolsMenu->addSeparator(globalContext);
286 287
    m_reparseExternallyChangedFiles = new QAction(tr("Reparse Externally Changed Files"), this);
    cmd = ActionManager::registerAction(m_reparseExternallyChangedFiles, Constants::UPDATE_CODEMODEL, globalContext);
288
    CppTools::CppModelManagerInterface *cppModelManager = CppTools::CppModelManagerInterface::instance();
289
    connect(m_reparseExternallyChangedFiles, SIGNAL(triggered()), cppModelManager, SLOT(updateModifiedSourceFiles()));
290
    cppToolsMenu->addAction(cmd);
291

292 293
    cppToolsMenu->addSeparator(globalContext);
    QAction *inspectCppCodeModel = new QAction(tr("Inspect C++ Code Model..."), this);
294 295 296
    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()));
297
    cppToolsMenu->addAction(cmd);
298

299
    contextMenu->addSeparator(context);
300

301
    cmd = ActionManager::command(TextEditor::Constants::AUTO_INDENT_SELECTION);
mae's avatar
mae committed
302
    contextMenu->addAction(cmd);
303

304
    cmd = ActionManager::command(TextEditor::Constants::UN_COMMENT_SELECTION);
mae's avatar
mae committed
305
    contextMenu->addAction(cmd);
306

307 308 309 310
    connect(ProgressManager::instance(), SIGNAL(taskStarted(Core::Id)),
            this, SLOT(onTaskStarted(Core::Id)));
    connect(ProgressManager::instance(), SIGNAL(allTasksFinished(Core::Id)),
            this, SLOT(onAllTasksFinished(Core::Id)));
311

312
    readSettings();
con's avatar
con committed
313 314 315
    return true;
}

316
void CppEditorPlugin::readSettings()
317
{
318
    m_sortedOutline = ICore::settings()->value(QLatin1String("CppTools/SortedMethodOverview"), true).toBool();
319 320
}

321
void CppEditorPlugin::writeSettings()
322
{
323
    ICore::settings()->setValue(QLatin1String("CppTools/SortedMethodOverview"), m_sortedOutline);
324 325
}

326
void CppEditorPlugin::extensionsInitialized()
con's avatar
con committed
327 328 329
{
}

330
ExtensionSystem::IPlugin::ShutdownFlag CppEditorPlugin::aboutToShutdown()
331 332
{
    writeSettings();
333
    return SynchronousShutdown;
334 335
}

336 337 338 339 340
static CPPEditorWidget *currentCppEditorWidget()
{
    return qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget());
}

341
void CppEditorPlugin::switchDeclarationDefinition()
con's avatar
con committed
342
{
343 344
    if (CPPEditorWidget *editorWidget = currentCppEditorWidget())
        editorWidget->switchDeclarationDefinition(/*inNextSplit*/ false);
345 346
}

347
void CppEditorPlugin::openDeclarationDefinitionInNextSplit()
348
{
349 350
    if (CPPEditorWidget *editorWidget = currentCppEditorWidget())
        editorWidget->switchDeclarationDefinition(/*inNextSplit*/ true);
con's avatar
con committed
351 352
}

353
void CppEditorPlugin::renameSymbolUnderCursor()
354
{
355 356
    if (CPPEditorWidget *editorWidget = currentCppEditorWidget())
        editorWidget->renameSymbolUnderCursor();
357 358
}

359
void CppEditorPlugin::findUsages()
360
{
361 362
    if (CPPEditorWidget *editorWidget = currentCppEditorWidget())
        editorWidget->findUsages();
363 364
}

365 366
void CppEditorPlugin::showPreProcessorDialog()
{
367 368
    if (CPPEditorWidget *editorWidget = currentCppEditorWidget())
        editorWidget->showPreProcessorWidget();
369 370
}

371
void CppEditorPlugin::onTaskStarted(Core::Id type)
372
{
373
    if (type == CppTools::Constants::TASK_INDEX) {
374 375
        m_renameSymbolUnderCursorAction->setEnabled(false);
        m_findUsagesAction->setEnabled(false);
376
        m_reparseExternallyChangedFiles->setEnabled(false);
377
        m_openTypeHierarchyAction->setEnabled(false);
378
        m_openIncludeHierarchyAction->setEnabled(false);
379
    }
380 381
}

382
void CppEditorPlugin::onAllTasksFinished(Core::Id type)
383
{
384
    if (type == CppTools::Constants::TASK_INDEX) {
385 386
        m_renameSymbolUnderCursorAction->setEnabled(true);
        m_findUsagesAction->setEnabled(true);
387
        m_reparseExternallyChangedFiles->setEnabled(true);
388
        m_openTypeHierarchyAction->setEnabled(true);
389
        m_openIncludeHierarchyAction->setEnabled(true);
390
    }
391 392
}

393 394 395 396 397 398 399 400 401 402
void CppEditorPlugin::inspectCppCodeModel()
{
    if (m_cppCodeModelInspectorDialog) {
        ICore::raiseWindow(m_cppCodeModelInspectorDialog);
    } else {
        m_cppCodeModelInspectorDialog = new CppCodeModelInspectorDialog(ICore::mainWindow());
        m_cppCodeModelInspectorDialog->show();
    }
}

403
void CppEditorPlugin::openTypeHierarchy()
404
{
405
    if (currentCppEditorWidget()) {
406 407
        NavigationWidget *navigation = NavigationWidget::instance();
        navigation->activateSubWidget(Constants::TYPE_HIERARCHY_ID);
408 409 410 411
        emit typeHierarchyRequested();
    }
}

412 413
void CppEditorPlugin::openIncludeHierarchy()
{
414
    if (currentCppEditorWidget()) {
415 416 417 418 419 420
        Core::NavigationWidget *navigation = Core::NavigationWidget::instance();
        navigation->activateSubWidget(Core::Id(Constants::INCLUDE_HIERARCHY_ID));
        emit includeHierarchyRequested();
    }
}

421
Q_EXPORT_PLUGIN(CppEditorPlugin)