Index: kdevplatform/shell/textdocument.h =================================================================== --- kdevplatform/shell/textdocument.h +++ kdevplatform/shell/textdocument.h @@ -85,7 +85,6 @@ Q_PRIVATE_SLOT(d, void modifiedOnDisk(KTextEditor::Document *, bool, KTextEditor::ModificationInterface::ModifiedOnDiskReason)) void newDocumentStatus(KTextEditor::Document*); - void populateContextMenu(KTextEditor::View*, QMenu*); void textChanged(KTextEditor::Document*); void documentUrlChanged(KTextEditor::Document*); void slotDocumentLoaded(); Index: kdevplatform/shell/textdocument.cpp =================================================================== --- kdevplatform/shell/textdocument.cpp +++ kdevplatform/shell/textdocument.cpp @@ -76,19 +76,69 @@ } } +class TextDocumentContextMenuData : public QObject +{ + Q_OBJECT +public: + TextDocumentContextMenuData() + { + } + + ~TextDocumentContextMenuData() + { + delete addedContextMenu; + addedContextMenu = nullptr; + + lastShowMenu = nullptr; + } + + void populateContextMenu( KTextEditor::View* v, QMenu* menu ) + { + if (lastShowMenu) { + foreach ( QAction* action, addedContextMenu->actions() ) { + lastShowMenu->removeAction(action); + } + } + + delete addedContextMenu; + addedContextMenu = new QMenu(); + + EditorContext c(v, v->cursorPosition()); + auto extensions = Core::self()->pluginController()->queryPluginsForContextMenuExtensions(&c, addedContextMenu); + + ContextMenuExtension::populateMenu(addedContextMenu, extensions); + + foreach ( QAction* action, addedContextMenu->actions() ) { + menu->addAction(action); + } + lastShowMenu = menu; + + menu->setTearOffEnabled(true); + } + + // we want to remove the previously added stuff before + // the menu shows again. + // This has to be a static instance because multiple views + // can share the same context menu instance. + QMenu* addedContextMenu = nullptr; + QMenu* lastShowMenu = nullptr; +}; + class TextDocumentPrivate { public: explicit TextDocumentPrivate(TextDocument *textDocument) : q(textDocument) { + if (!contextMenuData) { + contextMenuData = new TextDocumentContextMenuData; + } } ~TextDocumentPrivate() { - delete addedContextMenu; - addedContextMenu = nullptr; - + delete contextMenuData; + contextMenuData = nullptr; saveSessionConfig(); delete document; } @@ -231,10 +281,13 @@ IDocument::DocumentState state = IDocument::Clean; QString encoding; bool loaded = false; - // we want to remove the added stuff when the menu hides - QMenu* addedContextMenu = nullptr; + // there is only a single contextmenu at a time so use a single (static) + // instance of the class keeping track of added menu actions. + static TextDocumentContextMenuData* contextMenuData; }; +TextDocumentContextMenuData* TextDocumentPrivate::contextMenuData = nullptr; + class TextViewPrivate { public: @@ -345,7 +398,7 @@ view->setStatusBarEnabled(Core::self()->partControllerInternal()->showTextEditorStatusBar()); - connect(view, &KTextEditor::View::contextMenuAboutToShow, this, &TextDocument::populateContextMenu); + connect(view, &KTextEditor::View::contextMenuAboutToShow, d->contextMenuData, &TextDocumentContextMenuData::populateContextMenu); if (KTextEditor::CodeCompletionInterface* cc = dynamic_cast(view)) cc->setAutomaticInvocationEnabled(core()->languageController()->completionSettings()->automaticCompletionEnabled()); @@ -670,27 +723,6 @@ notifyContentChanged(); } -void KDevelop::TextDocument::populateContextMenu( KTextEditor::View* v, QMenu* menu ) -{ - if (d->addedContextMenu) { - foreach ( QAction* action, d->addedContextMenu->actions() ) { - menu->removeAction(action); - } - delete d->addedContextMenu; - } - - d->addedContextMenu = new QMenu(); - - EditorContext c(v, v->cursorPosition()); - auto extensions = Core::self()->pluginController()->queryPluginsForContextMenuExtensions(&c, d->addedContextMenu); - - ContextMenuExtension::populateMenu(d->addedContextMenu, extensions); - - foreach ( QAction* action, d->addedContextMenu->actions() ) { - menu->addAction(action); - } -} - void KDevelop::TextDocument::repositoryCheckFinished(bool canRecreate) { if ( d->state != IDocument::Dirty && d->state != IDocument::DirtyAndModified ) { // document is not dirty for whatever reason, nothing to do. @@ -737,3 +769,4 @@ } #include "moc_textdocument.cpp" +#include "textdocument.moc"