diff --git a/include/eepp/ui/uiwindow.hpp b/include/eepp/ui/uiwindow.hpp index 6be5ba361..846fd44c6 100644 --- a/include/eepp/ui/uiwindow.hpp +++ b/include/eepp/ui/uiwindow.hpp @@ -25,7 +25,8 @@ enum UIWindowFlags { UI_WIN_MODAL = ( 1 << 8 ), UI_WIN_SHADOW = ( 1 << 9 ), UI_WIN_FRAME_BUFFER = ( 1 << 10 ), - UI_WIN_COLOR_BUFFER = ( 1 << 11 ) + UI_WIN_COLOR_BUFFER = ( 1 << 11 ), + UI_WIN_EPHEMERAL = ( 1 << 12 ), // Windows is closed when focus is lost }; static const Uint32 UI_WIN_DEFAULT_FLAGS = UI_WIN_CLOSE_BUTTON | @@ -242,6 +243,8 @@ class EE_API UIWindow : public UIWidget { virtual void matrixUnset(); + virtual Uint32 onFocusLoss(); + void fixChildsSize(); void doResize( const NodeMessage* Msg ); @@ -297,6 +300,8 @@ class EE_API UIWindow : public UIWidget { void forcedApplyStyle(); void sendWindowToFront(); + + void checkEphemeralClose(); }; }} // namespace EE::UI diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 418f2b7c7..0fce04cba 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -1481,14 +1481,15 @@ Uint32 UICodeEditor::onMouseMove( const Vector2i& position, const Uint32& flags mDoc->setSelection( selection ); } - if ( minimapHover || localPos.y <= mPluginsTopSpace ) { + if ( minimapHover ) { getUISceneNode()->setCursor( Cursor::Arrow ); } else { checkMouseOverColor( position ); checkMouseOverLink( position ); - updateMouseCursor( position.asFloat() ); + if ( localPos.y >= mPluginsTopSpace ) + updateMouseCursor( position.asFloat() ); } if ( mShowFoldingRegion && !mFoldsAlwaysVisible ) { diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index 7d30838a0..bd91efca6 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -84,7 +85,7 @@ UIWindow::UIWindow( UIWindow::WindowBaseContainerType type, const StyleConfig& w mContainer->setClipType( ClipType::ContentBox ); mContainer->enableReportSizeChangeToChilds(); mContainer->addEventListener( Event::OnPositionChange, - [this] ( auto event ) { onContainerPositionChange( event ); } ); + [this]( auto event ) { onContainerPositionChange( event ); } ); updateWinFlags(); @@ -788,6 +789,10 @@ Uint32 UIWindow::onMessage( const NodeMessage* Msg ) { sendWindowToFront(); break; } + case NodeMessage::FocusLoss: { + checkEphemeralClose(); + break; + } case NodeMessage::MouseDown: { doResize( Msg ); break; @@ -1128,8 +1133,8 @@ UIWindow* UIWindow::showWhenReady() { if ( mWindowReady ) { show(); } else { - hide(); mShowWhenReady = true; + hide(); } return this; } @@ -1384,6 +1389,11 @@ void UIWindow::matrixUnset() { } } +Uint32 UIWindow::onFocusLoss() { + checkEphemeralClose(); + return UIWidget::onFocusLoss(); +} + bool UIWindow::ownsFrameBuffer() { return 0 != ( mStyleConfig.WinFlags & UI_WIN_FRAME_BUFFER ); } @@ -1808,4 +1818,11 @@ void UIWindow::sendWindowToFront() { sendCommonEvent( Event::OnWindowToFront ); } +void UIWindow::checkEphemeralClose() { + Node* focusNode = getUISceneNode()->getUIEventDispatcher()->getFocusNode(); + if ( !mShowWhenReady && ( mStyleConfig.WinFlags & UI_WIN_EPHEMERAL ) && focusNode != this && + !inParentTreeOf( focusNode ) ) + closeWindow(); +} + }} // namespace EE::UI diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index 9d5f58287..1222693a9 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,106 @@ static json getURIAndPositionJSON( UICodeEditor* editor ) { return data; } +class LSPSymbolInfoTreeModel : public Model { + public: + static std::shared_ptr create( UISceneNode* uiSceneNode, + LSPSymbolInformationList&& data, + const std::string& query = "" ) { + return std::make_shared( uiSceneNode, std::move( data ), query ); + } + + explicit LSPSymbolInfoTreeModel( UISceneNode* uiSceneNode, LSPSymbolInformationList&& info, + const std::string& query = "" ) : + mUISceneNode( uiSceneNode ), mInfo( std::move( info ) ) { + for ( auto& info : mInfo ) + info.updateParentsRefs(); + if ( !query.empty() ) + filter( String::toLower( query ) ); + } + + size_t rowCount( const ModelIndex& index ) const override { + if ( !index.isValid() ) + return mInfo.size(); + if ( index.internalId() == -1 ) + return mInfo[index.row()].children.size(); + if ( index.internalData() ) + return static_cast( index.internalData() )->children.size(); + return 0; + }; + + size_t columnCount( const ModelIndex& ) const override { return 1; } + + ModelIndex index( int row, int column, const ModelIndex& parent ) const override { + if ( !parent.isValid() ) + return createIndex( row, column, &mInfo[row], -1 ); + if ( parent.internalData() ) { + LSPSymbolInformation* parentNode = + static_cast( parent.internalData() ); + return createIndex( row, column, &parentNode->children[row], parent.row() ); + } + return {}; + } + + ModelIndex parentIndex( const ModelIndex& index ) const override { + if ( !index.isValid() || index.internalId() == -1 ) + return {}; + if ( index.internalData() ) { + LSPSymbolInformation* node = static_cast( index.internalData() ); + if ( !node->parent ) + return {}; + return createIndex( index.internalId(), 0, node->parent ); + } + return {}; + } + + Variant data( const ModelIndex& index, ModelRole role ) const override { + LSPSymbolInformation* node = static_cast( index.internalData() ); + if ( node == nullptr ) + return {}; + + if ( role == ModelRole::Display ) { + return Variant( node->name.c_str() ); + } else if ( role == ModelRole::Icon ) { + return mUISceneNode->findIcon( LSPSymbolKindHelper::toIconString( node->kind ) ); + } + return {}; + } + + protected: + UISceneNode* mUISceneNode{ nullptr }; + LSPSymbolInformationList mInfo; + + std::optional filterNode( const LSPSymbolInformation& node, + const std::string& query ) { + LSPSymbolInformation filteredNode( node.name, node.kind, node.range, node.detail ); + + for ( const auto& child : node.children ) { + if ( auto filteredChild = filterNode( child, query ); filteredChild ) { + filteredChild->parent = &filteredNode; + filteredNode.children.push_back( std::move( *filteredChild ) ); + } + } + + if ( String::toLower( node.name ).find( query ) != std::string::npos || + !filteredNode.children.empty() ) + return filteredNode; + + return std::nullopt; + } + + void filter( const std::string& query ) { + std::vector filteredRoots; + + for ( const auto& rootNode : mInfo ) + if ( auto filteredRoot = filterNode( rootNode, query ); filteredRoot ) + filteredRoots.push_back( std::move( *filteredRoot ) ); + + mInfo = std::move( filteredRoots ); + for ( auto& i : mInfo ) + i.updateParentsRefs(); + } +}; + class LSPLocationModel : public Model { public: enum CustomInfo { URI, TextRange }; @@ -443,6 +544,10 @@ void LSPClientPlugin::setDocumentSymbols( const URI& docURI, LSPSymbolInformatio mDocFlatSymbols[docURI] = !LSPSymbolInformationListHelper::isFlat( res ) ? LSPSymbolInformationListHelper::flatten( res ) : res; + + for ( auto& r : res ) + r.updateParentsRefs(); + mDocSymbols[docURI] = std::move( res ); getManager()->getSplitter()->forEachDoc( [docURI, this]( TextDocument& doc ) { @@ -498,6 +603,11 @@ TextDocument* LSPClientPlugin::getDocumentFromURI( const URI& uri ) { bool LSPClientPlugin::onMouseClick( UICodeEditor* editor, const Vector2i& pos, const Uint32& flags ) { + if ( mBreadcrumb && editor->convertToNodeSpace( pos.asFloat() ).y < mPluginTopSpace ) { + editor->getDocument().execute( "lsp-show-document-symbols", editor ); + return true; + } + Input* input = editor->getUISceneNode()->getWindow()->getInput(); Uint32 mod = input->getSanitizedModState(); if ( mod != ( KEYMOD_LALT | KeyMod::getDefaultModifier() ) || ( flags & EE_BUTTON_LMASK ) == 0 ) @@ -1004,6 +1114,7 @@ void LSPClientPlugin::loadLSPConfig( std::vector& lsps, const std mKeyBindings["lsp-rename-symbol-under-cursor"] = "mod+shift+r"; mKeyBindings["lsp-symbol-references"] = "mod+shift+u"; mKeyBindings["lsp-format-range"] = "alt+shift+f"; + mKeyBindings["lsp-show-document-symbols"] = "mod+shift+l"; } if ( j.contains( "keybindings" ) ) { @@ -1335,6 +1446,10 @@ void LSPClientPlugin::onRegister( UICodeEditor* editor ) { } ); doc.setCommand( "lsp-plugin-restart", [this] { mManager->reload( getId() ); } ); + + doc.setCommand( "lsp-show-document-symbols", [this]( TextDocument::Client* client ) { + showDocumentSymbols( static_cast( client ) ); + } ); } std::vector listeners; @@ -1357,10 +1472,19 @@ void LSPClientPlugin::onRegister( UICodeEditor* editor ) { editor->addEventListener( Event::OnDocumentChanged, [this, editor]( const Event* ) { TextDocument* oldDoc = mEditorDocs[editor]; TextDocument* newDoc = editor->getDocumentRef().get(); - Lock l( mDocMutex ); - mDocs.erase( oldDoc ); - mDocCurrentSymbols.erase( oldDoc->getURI() ); - mEditorDocs[editor] = newDoc; + URI docURI; + { + Lock l( mDocMutex ); + docURI = oldDoc->getURI(); + mDocs.erase( oldDoc ); + mEditorDocs[editor] = newDoc; + } + + { + Lock l( mDocCurrentSymbolsMutex ); + mDocCurrentSymbols.erase( docURI ); + } + updateCurrentSymbol( editor->getDocument() ); } ) ); @@ -1452,35 +1576,43 @@ void LSPClientPlugin::onUnregister( UICodeEditor* editor ) { if ( mShuttingDown ) return; - Lock l( mDocMutex ); - TextDocument* doc = &editor->getDocument(); - const auto& cbs = mEditors[editor]; - for ( auto listener : cbs ) - editor->removeEventListener( listener ); + URI docURI; + { + Lock l( mDocMutex ); + TextDocument* doc = &editor->getDocument(); + docURI = doc->getURI(); + const auto& cbs = mEditors[editor]; + for ( auto listener : cbs ) + editor->removeEventListener( listener ); - if ( mBreadcrumb ) - editor->unregisterTopSpace( this ); + if ( mBreadcrumb ) + editor->unregisterTopSpace( this ); - mEditors.erase( editor ); - mEditorsTags.erase( editor ); - mEditorDocs.erase( editor ); - for ( const auto& ieditor : mEditorDocs ) { - if ( ieditor.second == doc ) - return; + mEditors.erase( editor ); + mEditorsTags.erase( editor ); + mEditorDocs.erase( editor ); + for ( const auto& ieditor : mEditorDocs ) { + if ( ieditor.second == doc ) + return; + } + + if ( editor->hasDocument() ) + for ( auto& kb : mKeyBindings ) + editor->getDocument().removeCommand( kb.first ); + + { + Lock lds( mDocSymbolsMutex ); + mDocSymbols.erase( doc->getURI() ); + mDocFlatSymbols.erase( doc->getURI() ); + } + + mDocs.erase( doc ); } - if ( editor->hasDocument() ) - for ( auto& kb : mKeyBindings ) - editor->getDocument().removeCommand( kb.first ); - { - Lock lds( mDocSymbolsMutex ); - mDocSymbols.erase( doc->getURI() ); - mDocFlatSymbols.erase( doc->getURI() ); + Lock l2( mDocCurrentSymbolsMutex ); + mDocCurrentSymbols.erase( docURI ); } - - mDocs.erase( doc ); - mDocCurrentSymbols.erase( doc->getURI() ); } bool LSPClientPlugin::onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* menu, @@ -1535,6 +1667,10 @@ bool LSPClientPlugin::onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* me i18n( "lsp_refresh_semantic_highlighting", "Refresh Semantic Highlighting" ), "refresh" ); + if ( cap.documentSymbolProvider ) + addFn( "lsp-show-document-symbols", + i18n( "show-document-symbols", "Show Document Symbols" ), "symbol-function" ); + if ( server->getDefinition().language == "cpp" || server->getDefinition().language == "c" ) addFn( "lsp-switch-header-source", i18n( "lsp_switch_header_source", "Switch Header/Source" ), "filetype-hpp" ); @@ -1645,6 +1781,19 @@ void LSPClientPlugin::tryDisplayTooltip( UICodeEditor* editor, const LSPHover& r bool LSPClientPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position, const Uint32& flags ) { + if ( mBreadcrumb && editor->convertToNodeSpace( position.asFloat() ).y < mPluginTopSpace ) { + if ( !mHoveringBreadcrumb ) { + mHoveringBreadcrumb = true; + editor->invalidateDraw(); + } + getUISceneNode()->setCursor( Cursor::Hand ); + return false; + } + if ( mHoveringBreadcrumb ) { + mHoveringBreadcrumb = false; + editor->invalidateDraw(); + } + if ( flags != 0 ) { tryHideTooltip( editor, position ); return false; @@ -1682,6 +1831,15 @@ bool LSPClientPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& positio return editor->getTooltip() && editor->getTooltip()->isVisible() && mSymbolInfoShowing; } +bool LSPClientPlugin::onMouseLeave( UICodeEditor* editor, const Vector2i&, const Uint32& ) { + if ( mHoveringBreadcrumb ) { + mHoveringBreadcrumb = false; + editor->invalidateDraw(); + } + + return false; +} + void LSPClientPlugin::onFocusLoss( UICodeEditor* editor ) { hideTooltip( editor ); } @@ -1735,7 +1893,8 @@ void LSPClientPlugin::drawTop( UICodeEditor* editor, const Vector2f& screenStart isPath = false; } - Color textColor( editor->getColorScheme().getEditorColor( SyntaxStyleTypes::LineNumber2 ) ); + Color textColor( editor->getColorScheme().getEditorColor( + mHoveringBreadcrumb ? SyntaxStyleTypes::Text : SyntaxStyleTypes::LineNumber2 ) ); const auto& workspace = getManager()->getWorkspaceFolder(); if ( isPath && !workspace.empty() && String::startsWith( path, workspace ) ) path = path.substr( workspace.size() ); @@ -1746,7 +1905,7 @@ void LSPClientPlugin::drawTop( UICodeEditor* editor, const Vector2f& screenStart auto drawn = Text::draw( String::fromUtf8( path ), pos, font, fontSize, textColor ); - Lock l( mDocSymbolsMutex ); + Lock l( mDocCurrentSymbolsMutex ); auto symbolsInfoIt = mDocCurrentSymbols.find( editor->getDocument().getURI() ); if ( symbolsInfoIt == mDocCurrentSymbols.end() ) return; @@ -1799,39 +1958,121 @@ void LSPClientPlugin::updateCurrentSymbol( TextDocument& doc ) { if ( !mBreadcrumb ) return; - Lock l( mDocSymbolsMutex ); + std::vector symbolsInfo; URI uri = doc.getURI(); - auto symbolsIt = mDocSymbols.find( uri ); - if ( symbolsIt == mDocSymbols.end() ) { - mDocCurrentSymbols[uri] = {}; - return; + + { + mDocSymbolsMutex.lock(); + + auto symbolsIt = mDocSymbols.find( uri ); + if ( symbolsIt == mDocSymbols.end() ) { + mDocSymbolsMutex.unlock(); + Lock l( mDocCurrentSymbolsMutex ); + mDocCurrentSymbols[uri] = {}; + return; + } + + LSPSymbolInformationList* list = &symbolsIt->second; + auto sel = doc.getSelection(); + LSPSymbolInformationList::iterator foundIt; + + bool found = false; + do { + foundIt = std::lower_bound( list->begin(), list->end(), sel, + []( const LSPSymbolInformation& cur, + const TextRange& sel ) { return cur.range < sel; } ); + found = foundIt != list->end() && foundIt->range.contains( sel ); + if ( found ) { + symbolsInfo.push_back( { String::fromUtf8( foundIt->name ), + LSPSymbolKindHelper::toIconString( foundIt->kind ) } ); + if ( foundIt->children.empty() ) + break; + list = &foundIt->children; + } else + break; + } while ( found ); + + mDocSymbolsMutex.unlock(); } - LSPSymbolInformationList* list = &symbolsIt->second; - auto sel = doc.getSelection(); - LSPSymbolInformationList::iterator foundIt; - std::vector symbolsInfo; - - bool found = false; - do { - foundIt = std::lower_bound( list->begin(), list->end(), sel, - []( const LSPSymbolInformation& cur, const TextRange& sel ) { - return cur.range < sel; - } ); - found = foundIt != list->end() && foundIt->range.contains( sel ); - if ( found ) { - symbolsInfo.push_back( { String::fromUtf8( foundIt->name ), - LSPSymbolKindHelper::toIconString( foundIt->kind ) } ); - if ( foundIt->children.empty() ) - break; - list = &foundIt->children; - } else - break; - } while ( found ); - + Lock l( mDocCurrentSymbolsMutex ); mDocCurrentSymbols[uri] = std::move( symbolsInfo ); } +void LSPClientPlugin::showDocumentSymbols( UICodeEditor* editor ) { + TextDocument& doc = editor->getDocument(); + URI uri = doc.getURI(); + + auto model = createDocSymbolsModel( uri ); + if ( !model ) + return; + + getUISceneNode()->getRoot()->setFocus(); + UIWindow* win = UIWindow::NewOpt( UIMessageBox::WindowBaseContainerType::LINEAR_LAYOUT ); + win->setMinWindowSize( 400, getUISceneNode()->getSize().getHeight() * 0.7f ); + win->setKeyBindingCommand( "closeWindow", [win, editor] { + win->closeWindow(); + editor->setFocus(); + } ); + win->getKeyBindings().addKeybind( { KEY_ESCAPE }, "closeWindow" ); + win->setWindowFlags( UI_WIN_NO_DECORATION | UI_WIN_SHADOW | UI_WIN_MODAL | UI_WIN_EPHEMERAL ); + win->center(); + UITextInput* input = UITextInput::New(); + input->setParent( win->getContainer() ); + input->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); + input->setHint( i18n( "search_symbols_ellipsis", "Search Symbols..." ) ); + + UITreeView* tv = UITreeView::New(); + tv->setHeadersVisible( false ); + tv->setAutoExpandOnSingleColumn( true ); + tv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed ); + tv->setLayoutWeight( 1 ); + tv->setParent( win->getContainer() ); + tv->setModel( model ); + tv->expandAll(); + tv->setFocusOnSelection( false ); + win->show(); + input->setFocus(); + + input->on( Event::KeyDown, [tv, input]( const Event* event ) { + tv->forceKeyDown( *event->asKeyEvent() ); + input->setFocus(); + } ); + + input->on( Event::OnTextChanged, [tv, input, uri, this]( const Event* ) { + tv->setModel( createDocSymbolsModel( uri, input->getText().toUtf8() ) ); + tv->expandAll(); + } ); + + tv->setOnSelection( [editor]( const ModelIndex& index ) { + LSPSymbolInformation* node = static_cast( index.internalData() ); + editor->getDocument().setSelection( node->range.start() ); + editor->scrollTo( node->range.start(), true ); + } ); + + input->on( Event::OnPressEnter, + [win]( const Event* ) { win->executeKeyBindingCommand( "closeWindow" ); } ); + + tv->on( Event::OnModelEvent, [win]( const Event* event ) { + const ModelEvent* modelEvent = static_cast( event ); + if ( modelEvent->getModelEventType() == ModelEventType::Open ) + win->executeKeyBindingCommand( "closeWindow" ); + } ); +} + +std::shared_ptr +LSPClientPlugin::createDocSymbolsModel( URI uri, const std::string& query ) { + LSPSymbolInformationList docSymbolsCopy; + { + Lock l( mDocSymbolsMutex ); + auto docSymbols = mDocSymbols.find( uri ); + if ( docSymbols == mDocSymbols.end() ) + return nullptr; + docSymbolsCopy = docSymbols->second; + } + return LSPSymbolInfoTreeModel::create( getUISceneNode(), std::move( docSymbolsCopy ), query ); +} + const LSPClientServerManager& LSPClientPlugin::getClientManager() const { return mClientManager; } diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp index b6e849d4c..7e452de52 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp @@ -19,6 +19,8 @@ using namespace EE::UI; namespace ecode { +class LSPSymbolInfoTreeModel; + // Implementation of the LSP Client: // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/ class LSPClientPlugin : public Plugin { @@ -55,6 +57,9 @@ class LSPClientPlugin : public Plugin { virtual bool onMouseMove( UICodeEditor* editor, const Vector2i& position, const Uint32& flags ); + virtual bool onMouseLeave( UICodeEditor* editor, const Vector2i& position, + const Uint32& flags ); + virtual void onFocusLoss( UICodeEditor* editor ); virtual bool onKeyDown( UICodeEditor*, const KeyEvent& ); @@ -103,6 +108,7 @@ class LSPClientPlugin : public Plugin { Clock mClock; Mutex mDocMutex; Mutex mDocSymbolsMutex; + Mutex mDocCurrentSymbolsMutex; UnorderedMap> mEditors; UnorderedMap> mEditorsTags; UnorderedSet mDocs; @@ -118,6 +124,7 @@ class LSPClientPlugin : public Plugin { bool mSilence{ false }; bool mTrimLogs{ false }; bool mBreadcrumb{ true }; + bool mHoveringBreadcrumb{ false }; StyleSheetLength mBreadcrumbHeight{ "20dp" }; UnorderedMap mKeyBindings; /* cmd, shortcut */ UnorderedMap> mDelayedDocs; @@ -202,6 +209,11 @@ class LSPClientPlugin : public Plugin { void renameSymbol( UICodeEditor* editor ); void updateCurrentSymbol( TextDocument& doc ); + + void showDocumentSymbols( UICodeEditor* editor ); + + std::shared_ptr createDocSymbolsModel( URI uri, + const std::string& query = "" ); }; } // namespace ecode diff --git a/src/tools/ecode/plugins/lsp/lspprotocol.hpp b/src/tools/ecode/plugins/lsp/lspprotocol.hpp index 30a7de1a1..eb371b8a4 100644 --- a/src/tools/ecode/plugins/lsp/lspprotocol.hpp +++ b/src/tools/ecode/plugins/lsp/lspprotocol.hpp @@ -3,7 +3,6 @@ #include #include -#include #include using namespace EE; @@ -381,6 +380,14 @@ struct LSPSymbolInformation { TextRange selectionRange; double score = 0.0; std::vector children; + LSPSymbolInformation* parent{ nullptr }; + + void updateParentsRefs() { + for ( auto& child : children ) { + child.parent = this; + child.updateParentsRefs(); + } + } }; using LSPSymbolInformationList = std::vector; diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index f4c8687cd..02689abb7 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -1675,7 +1675,7 @@ UIPopUpMenu* SettingsMenu::createToolsMenu() { mToolsMenu ->add( i18n( "document_symbol_find_ellipsis", "Search Document Symbol..." ), findIcon( "search" ), getKeybind( "open-document-symbol-search" ) ) - ->setId( "open-workspace-symbol-search" ); + ->setId( "open-document-symbol-search" ); mToolsMenu ->add( i18n( "go_to_line_ellipsis", "Go to line..." ), findIcon( "go-to-line" ), getKeybind( "go-to-line" ) )