cppeditorplugin.cpp 16.3 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
136 137
    connect(this, SIGNAL(outlineSortingChanged(bool)),
            editor, SLOT(setSortedOutline(bool)));
138 139
}

140
void CppEditorPlugin::setSortedOutline(bool sorted)
141
{
142 143
    m_sortedOutline = sorted;
    emit outlineSortingChanged(sorted);
144 145
}

146
bool CppEditorPlugin::sortedOutline() const
147
{
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 294 295 296
    QAction *inspectCppCodeModel = new QAction(tr("Debug: 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()));

297
    contextMenu->addSeparator(context);
298

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

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

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

310
    readSettings();
con's avatar
con committed
311 312 313
    return true;
}

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

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

324
void CppEditorPlugin::extensionsInitialized()
con's avatar
con committed
325 326 327
{
}

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

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

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

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

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

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

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

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

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

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

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

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

419
Q_EXPORT_PLUGIN(CppEditorPlugin)