TextEditor: remove text editor action handler

Give each editor a context and register editor actions individually for
that context. This removes the need to tell the action handler the
current editor. Additionally all actions are now available in editor
widgets outside of the EditorManager.

Change-Id: I0109866b180889762f8bd8aa07874d8d7c55bfa6
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
David Schulz
2024-03-27 14:00:21 +01:00
parent c459e8d490
commit 411100b037
30 changed files with 924 additions and 955 deletions

View File

@@ -21,6 +21,7 @@
#include "highlighterhelper.h"
#include "highlightersettings.h"
#include "icodestylepreferences.h"
#include "linenumberfilter.h"
#include "marginsettings.h"
#include "refactoroverlay.h"
#include "snippets/snippetoverlay.h"
@@ -28,11 +29,11 @@
#include "tabsettings.h"
#include "textdocument.h"
#include "textdocumentlayout.h"
#include "texteditoractionhandler.h"
#include "texteditorconstants.h"
#include "texteditoroverlay.h"
#include "texteditorsettings.h"
#include "texteditortr.h"
#include "typehierarchy.h"
#include "typingsettings.h"
#include <aggregation/aggregate.h>
@@ -45,7 +46,9 @@
#include <coreplugin/find/basetextfind.h>
#include <coreplugin/find/highlightscrollbarcontroller.h>
#include <coreplugin/icore.h>
#include <coreplugin/locator/locatormanager.h>
#include <coreplugin/manhattanstyle.h>
#include <coreplugin/navigationwidget.h>
#include <utils/algorithm.h>
#include <utils/async.h>
@@ -738,6 +741,14 @@ public:
void openTypeUnderCursor(bool openInNextSplit);
qreal charWidth() const;
// actions
void registerActions();
void updateActions();
void updateOptionalActions();
void updateRedoAction(bool on);
void updateUndoAction(bool on);
void updateCopyAction(bool on);
public:
TextEditorWidget *q;
QWidget *m_toolBarWidget = nullptr;
@@ -753,7 +764,7 @@ public:
QToolButton *m_fileLineEnding = nullptr;
QAction *m_fileLineEndingAction = nullptr;
uint m_optionalActionMask = TextEditorActionHandler::None;
uint m_optionalActionMask = OptionalActions::None;
bool m_contentsChanged = false;
bool m_lastCursorChangeWasInteresting = false;
std::shared_ptr<void> m_suggestionBlocker;
@@ -927,6 +938,30 @@ public:
void updateSuggestion();
void clearCurrentSuggestion();
QTextBlock m_suggestionBlock;
Context m_editorContext;
QAction *m_undoAction = nullptr;
QAction *m_redoAction = nullptr;
QAction *m_copyAction = nullptr;
QAction *m_copyHtmlAction = nullptr;
QAction *m_cutAction = nullptr;
QAction *m_autoIndentAction = nullptr;
QAction *m_autoFormatAction = nullptr;
QAction *m_visualizeWhitespaceAction = nullptr;
QAction *m_textWrappingAction = nullptr;
QAction *m_unCommentSelectionAction = nullptr;
QAction *m_unfoldAllAction = nullptr;
QAction *m_followSymbolAction = nullptr;
QAction *m_followSymbolInNextSplitAction = nullptr;
QAction *m_followToTypeAction = nullptr;
QAction *m_followToTypeInNextSplitAction = nullptr;
QAction *m_findUsageAction = nullptr;
QAction *m_openCallHierarchyAction = nullptr;
QAction *m_openTypeHierarchyAction = nullptr;
QAction *m_renameSymbolAction = nullptr;
QAction *m_jumpToFileAction = nullptr;
QAction *m_jumpToFileInNextSplitAction = nullptr;
QList<QAction *> m_modifyingActions;
};
class TextEditorWidgetFind : public BaseTextFind
@@ -1031,6 +1066,8 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
, m_codeAssistant(parent)
, m_hoverHandlerRunner(parent, m_hoverHandlers)
, m_autoCompleter(new AutoCompleter)
, m_editorContext(
Id(Core::Constants::K_DEFAULT_TEXT_EDITOR_ID).withSuffix(QUuid::createUuid().toString()))
{
m_selectionHighlightOverlay->show();
auto aggregate = new Aggregation::Aggregate;
@@ -1095,6 +1132,15 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
connect(q, &QPlainTextEdit::selectionChanged,
this, &TextEditorWidgetPrivate::slotSelectionChanged);
connect(q, &QPlainTextEdit::undoAvailable,
this, &TextEditorWidgetPrivate::updateUndoAction);
connect(q, &QPlainTextEdit::redoAvailable,
this, &TextEditorWidgetPrivate::updateRedoAction);
connect(q, &QPlainTextEdit::copyAvailable,
this, &TextEditorWidgetPrivate::updateCopyAction);
m_parenthesesMatchingTimer.setSingleShot(true);
m_parenthesesMatchingTimer.setInterval(50);
connect(&m_parenthesesMatchingTimer, &QTimer::timeout,
@@ -1141,6 +1187,14 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
q, &TextEditorWidget::setCompletionSettings);
connect(settings, &TextEditorSettings::extraEncodingSettingsChanged,
q, &TextEditorWidget::setExtraEncodingSettings);
auto context = new Core::IContext(this);
context->setWidget(q);
context->setContext(m_editorContext);
Core::ICore::addContextObject(context);
registerActions();
updateActions();
}
TextEditorWidgetPrivate::~TextEditorWidgetPrivate()
@@ -3810,6 +3864,434 @@ qreal TextEditorWidgetPrivate::charWidth() const
return QFontMetricsF(q->font()).horizontalAdvance(QLatin1Char('x'));
}
void TextEditorWidgetPrivate::registerActions()
{
using namespace Core::Constants;
using namespace TextEditor::Constants;
m_undoAction = ActionBuilder(this, UNDO)
.setContext(m_editorContext)
.addOnTriggered([this] { q->undo(); })
.contextAction();
m_redoAction = ActionBuilder(this, REDO)
.setContext(m_editorContext)
.addOnTriggered([this] { q->redo(); })
.contextAction();
m_copyAction = ActionBuilder(this, COPY)
.setContext(m_editorContext)
.addOnTriggered([this] { q->copy(); })
.contextAction();
m_cutAction = ActionBuilder(this, CUT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->cut(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, PASTE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->paste(); })
.contextAction();
ActionBuilder(this, SELECTALL)
.setContext(m_editorContext)
.addOnTriggered([this] { q->selectAll(); });
ActionBuilder(this, GOTO)
.setContext(m_editorContext)
.addOnTriggered([] { LocatorManager::showFilter(lineNumberFilter()); });
ActionBuilder(this, PRINT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->print(ICore::printer()); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteLine(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_END_OF_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteEndOfLine(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_END_OF_WORD)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteEndOfWord(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_END_OF_WORD_CAMEL_CASE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteEndOfWordCamelCase(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_START_OF_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteStartOfLine(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_START_OF_WORD)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteStartOfWord(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DELETE_START_OF_WORD_CAMEL_CASE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->deleteStartOfWordCamelCase(); })
.contextAction();
ActionBuilder(this, GOTO_BLOCK_START_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoBlockStartWithSelection(); });
ActionBuilder(this, GOTO_BLOCK_END_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoBlockEndWithSelection(); });
m_modifyingActions << ActionBuilder(this, MOVE_LINE_UP)
.setContext(m_editorContext)
.addOnTriggered([this] { q->moveLineUp(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, MOVE_LINE_DOWN)
.setContext(m_editorContext)
.addOnTriggered([this] { q->moveLineDown(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, COPY_LINE_UP)
.setContext(m_editorContext)
.addOnTriggered([this] { q->copyLineUp(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, COPY_LINE_DOWN)
.setContext(m_editorContext)
.addOnTriggered([this] { q->copyLineDown(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, JOIN_LINES)
.setContext(m_editorContext)
.addOnTriggered([this] { q->joinLines(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, INSERT_LINE_ABOVE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->insertLineAbove(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, INSERT_LINE_BELOW)
.setContext(m_editorContext)
.addOnTriggered([this] { q->insertLineBelow(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, SWITCH_UTF8BOM)
.setContext(m_editorContext)
.addOnTriggered([this] { q->switchUtf8bom(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, INDENT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->indent(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, UNINDENT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->unindent(); })
.contextAction();
m_followSymbolAction = ActionBuilder(this, FOLLOW_SYMBOL_UNDER_CURSOR)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openLinkUnderCursor(); })
.contextAction();
m_followSymbolInNextSplitAction = ActionBuilder(this, FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openLinkUnderCursorInNextSplit(); })
.contextAction();
m_followToTypeAction = ActionBuilder(this, FOLLOW_SYMBOL_TO_TYPE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openTypeUnderCursor(); })
.contextAction();
m_followToTypeInNextSplitAction = ActionBuilder(this, FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openTypeUnderCursorInNextSplit(); })
.contextAction();
m_findUsageAction = ActionBuilder(this, FIND_USAGES)
.setContext(m_editorContext)
.addOnTriggered([this] { q->findUsages(); })
.contextAction();
m_renameSymbolAction = ActionBuilder(this, RENAME_SYMBOL)
.setContext(m_editorContext)
.addOnTriggered([this] { q->renameSymbolUnderCursor(); })
.contextAction();
m_jumpToFileAction = ActionBuilder(this, JUMP_TO_FILE_UNDER_CURSOR)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openLinkUnderCursor(); })
.contextAction();
m_jumpToFileInNextSplitAction = ActionBuilder(this, JUMP_TO_FILE_UNDER_CURSOR_IN_NEXT_SPLIT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openLinkUnderCursorInNextSplit(); })
.contextAction();
m_openCallHierarchyAction = ActionBuilder(this, OPEN_CALL_HIERARCHY)
.setContext(m_editorContext)
.addOnTriggered([this] { q->openCallHierarchy(); })
.contextAction();
m_openTypeHierarchyAction = ActionBuilder(this, OPEN_TYPE_HIERARCHY)
.setContext(m_editorContext)
.addOnTriggered([] {
updateTypeHierarchy(NavigationWidget::activateSubWidget(
Constants::TYPE_HIERARCHY_FACTORY_ID, Side::Left));
})
.contextAction();
ActionBuilder(this, VIEW_PAGE_UP)
.setContext(m_editorContext)
.addOnTriggered([this] { q->viewPageUp(); });
ActionBuilder(this, VIEW_PAGE_DOWN)
.setContext(m_editorContext)
.addOnTriggered([this] { q->viewPageDown(); });
ActionBuilder(this, VIEW_LINE_UP)
.setContext(m_editorContext)
.addOnTriggered([this] { q->viewLineUp(); });
ActionBuilder(this, VIEW_LINE_DOWN)
.setContext(m_editorContext)
.addOnTriggered([this] { q->viewLineDown(); });
ActionBuilder(this, SELECT_ENCODING)
.setContext(m_editorContext)
.addOnTriggered([this] { q->selectEncoding(); });
m_modifyingActions << ActionBuilder(this, CIRCULAR_PASTE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->circularPaste(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, NO_FORMAT_PASTE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->pasteWithoutFormat(); })
.contextAction();
m_autoIndentAction = ActionBuilder(this, AUTO_INDENT_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->autoIndent(); })
.contextAction();
m_autoFormatAction = ActionBuilder(this, AUTO_FORMAT_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->autoFormat(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, REWRAP_PARAGRAPH)
.setContext(m_editorContext)
.addOnTriggered([this] { q->rewrapParagraph(); })
.contextAction();
m_visualizeWhitespaceAction = ActionBuilder(this, VISUALIZE_WHITESPACE)
.setContext(m_editorContext)
.addOnToggled(
this,
[this](bool checked) {
DisplaySettings ds = q->displaySettings();
ds.m_visualizeWhitespace = checked;
q->setDisplaySettings(ds);
})
.contextAction();
m_modifyingActions << ActionBuilder(this, CLEAN_WHITESPACE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->cleanWhitespace(); })
.contextAction();
m_textWrappingAction = ActionBuilder(this, TEXT_WRAPPING)
.setContext(m_editorContext)
.addOnToggled(this, [this] (bool checked) {
DisplaySettings ds = q->displaySettings();
ds.m_textWrapping = checked;
q->setDisplaySettings(ds);
})
.contextAction();
m_unCommentSelectionAction = ActionBuilder(this, UN_COMMENT_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->unCommentSelection(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, CUT_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->cutLine(); })
.contextAction();
ActionBuilder(this, COPY_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->copyLine(); });
m_copyHtmlAction = ActionBuilder(this, COPY_WITH_HTML)
.setContext(m_editorContext)
.addOnTriggered([this] { q->copyWithHtml(); })
.contextAction();
ActionBuilder(this, ADD_CURSORS_TO_LINE_ENDS)
.setContext(m_editorContext)
.addOnTriggered([this] { q->addCursorsToLineEnds(); });
ActionBuilder(this, ADD_SELECT_NEXT_FIND_MATCH)
.setContext(m_editorContext)
.addOnTriggered([this] { q->addSelectionNextFindMatch(); });
m_modifyingActions << ActionBuilder(this, DUPLICATE_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->duplicateSelection(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, DUPLICATE_SELECTION_AND_COMMENT)
.setContext(m_editorContext)
.addOnTriggered([this] { q->duplicateSelectionAndComment(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, UPPERCASE_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->uppercaseSelection(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, LOWERCASE_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->lowercaseSelection(); })
.contextAction();
m_modifyingActions << ActionBuilder(this, SORT_LINES)
.setContext(m_editorContext)
.addOnTriggered([this] { q->sortLines(); })
.contextAction();
ActionBuilder(this, FOLD)
.setContext(m_editorContext)
.addOnTriggered([this] { q->foldCurrentBlock(); });
ActionBuilder(this, UNFOLD)
.setContext(m_editorContext)
.addOnTriggered([this] { q->unfoldCurrentBlock(); });
m_unfoldAllAction = ActionBuilder(this, UNFOLD_ALL)
.setContext(m_editorContext)
.addOnTriggered([this] { q->unfoldAll(); })
.contextAction();
ActionBuilder(this, INCREASE_FONT_SIZE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->increaseFontZoom(); });
ActionBuilder(this, DECREASE_FONT_SIZE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->decreaseFontZoom(); });
ActionBuilder(this, RESET_FONT_SIZE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->zoomReset(); });
ActionBuilder(this, GOTO_BLOCK_START)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoBlockStart(); });
ActionBuilder(this, GOTO_BLOCK_END)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoBlockEnd(); });
ActionBuilder(this, SELECT_BLOCK_UP)
.setContext(m_editorContext)
.addOnTriggered([this] { q->selectBlockUp(); });
ActionBuilder(this, SELECT_BLOCK_DOWN)
.setContext(m_editorContext)
.addOnTriggered([this] { q->selectBlockDown(); });
ActionBuilder(this, SELECT_WORD_UNDER_CURSOR)
.setContext(m_editorContext)
.addOnTriggered([this] { q->selectWordUnderCursor(); });
ActionBuilder(this, GOTO_DOCUMENT_START)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoDocumentStart(); });
ActionBuilder(this, GOTO_DOCUMENT_END)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoDocumentEnd(); });
ActionBuilder(this, GOTO_LINE_START)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoLineStart(); });
ActionBuilder(this, GOTO_LINE_END)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoLineEnd(); });
ActionBuilder(this, GOTO_NEXT_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextLine(); });
ActionBuilder(this, GOTO_PREVIOUS_LINE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousLine(); });
ActionBuilder(this, GOTO_PREVIOUS_CHARACTER)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousCharacter(); });
ActionBuilder(this, GOTO_NEXT_CHARACTER)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextCharacter(); });
ActionBuilder(this, GOTO_PREVIOUS_WORD)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousWord(); });
ActionBuilder(this, GOTO_NEXT_WORD)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextWord(); });
ActionBuilder(this, GOTO_PREVIOUS_WORD_CAMEL_CASE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousWordCamelCase(); });
ActionBuilder(this, GOTO_NEXT_WORD_CAMEL_CASE)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextWordCamelCase(); });
ActionBuilder(this, GOTO_LINE_START_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoLineStartWithSelection(); });
ActionBuilder(this, GOTO_LINE_END_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoLineEndWithSelection(); });
ActionBuilder(this, GOTO_NEXT_LINE_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextLineWithSelection(); });
ActionBuilder(this, GOTO_PREVIOUS_LINE_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousLineWithSelection(); });
ActionBuilder(this, GOTO_PREVIOUS_CHARACTER_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousCharacterWithSelection(); });
ActionBuilder(this, GOTO_NEXT_CHARACTER_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextCharacterWithSelection(); });
ActionBuilder(this, GOTO_PREVIOUS_WORD_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousWordWithSelection(); });
ActionBuilder(this, GOTO_NEXT_WORD_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextWordWithSelection(); });
ActionBuilder(this, GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoPreviousWordCamelCaseWithSelection(); });
ActionBuilder(this, GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION)
.setContext(m_editorContext)
.addOnTriggered([this] { q->gotoNextWordCamelCaseWithSelection(); });
// Collect additional modifying actions so we can check for them inside a readonly file
// and disable them
m_modifyingActions << m_autoIndentAction;
m_modifyingActions << m_autoFormatAction;
m_modifyingActions << m_unCommentSelectionAction;
updateOptionalActions();
}
void TextEditorWidgetPrivate::updateActions()
{
bool isWritable = !q->isReadOnly();
for (QAction *a : std::as_const(m_modifyingActions))
a->setEnabled(isWritable);
m_unCommentSelectionAction->setEnabled((m_optionalActionMask & OptionalActions::UnCommentSelection) && isWritable);
m_visualizeWhitespaceAction->setEnabled(q);
if (TextEditorSettings::fontSettings().relativeLineSpacing() == 100) {
m_textWrappingAction->setEnabled(q);
} else {
m_textWrappingAction->setEnabled(false);
m_textWrappingAction->setChecked(false);
}
m_visualizeWhitespaceAction->setChecked(m_displaySettings.m_visualizeWhitespace);
m_textWrappingAction->setChecked(m_displaySettings.m_textWrapping);
updateRedoAction(q->document()->isRedoAvailable());
updateUndoAction(q->document()->isUndoAvailable());
updateCopyAction(q->textCursor().hasSelection());
updateOptionalActions();
}
void TextEditorWidgetPrivate::updateOptionalActions()
{
using namespace OptionalActions;
m_followSymbolAction->setEnabled(m_optionalActionMask & FollowSymbolUnderCursor);
m_followSymbolInNextSplitAction->setEnabled(m_optionalActionMask & FollowSymbolUnderCursor);
m_followToTypeAction->setEnabled(m_optionalActionMask & FollowTypeUnderCursor);
m_followToTypeInNextSplitAction->setEnabled(m_optionalActionMask & FollowTypeUnderCursor);
m_findUsageAction->setEnabled(m_optionalActionMask & FindUsage);
m_jumpToFileAction->setEnabled(m_optionalActionMask & JumpToFileUnderCursor);
m_jumpToFileInNextSplitAction->setEnabled(m_optionalActionMask & JumpToFileUnderCursor);
m_unfoldAllAction->setEnabled(m_optionalActionMask & UnCollapseAll);
m_renameSymbolAction->setEnabled(m_optionalActionMask & RenameSymbol);
m_openCallHierarchyAction->setEnabled(m_optionalActionMask & CallHierarchy);
m_openTypeHierarchyAction->setEnabled(m_optionalActionMask & TypeHierarchy);
bool formatEnabled = (m_optionalActionMask & OptionalActions::Format)
&& !q->isReadOnly();
m_autoIndentAction->setEnabled(formatEnabled);
m_autoFormatAction->setEnabled(formatEnabled);
}
void TextEditorWidgetPrivate::updateRedoAction(bool on)
{
m_redoAction->setEnabled(on);
}
void TextEditorWidgetPrivate::updateUndoAction(bool on)
{
m_undoAction->setEnabled(on);
}
void TextEditorWidgetPrivate::updateCopyAction(bool hasCopyableText)
{
if (m_cutAction)
m_cutAction->setEnabled(hasCopyableText && !q->isReadOnly());
if (m_copyAction)
m_copyAction->setEnabled(hasCopyableText);
if (m_copyHtmlAction)
m_copyHtmlAction->setEnabled(hasCopyableText);
}
bool TextEditorWidget::codeFoldingVisible() const
{
return d->m_codeFoldingVisible;
@@ -8103,6 +8585,7 @@ void TextEditorWidgetPrivate::applyFontSettingsDelayed()
m_fontSettingsNeedsApply = true;
if (q->isVisible())
q->triggerPendingUpdates();
updateActions();
}
void TextEditorWidgetPrivate::markRemoved(TextMark *mark)
@@ -8338,6 +8821,7 @@ void TextEditorWidget::setReadOnly(bool b)
emit readOnlyChanged();
if (b)
setTextInteractionFlags(textInteractionFlags() | Qt::TextSelectableByKeyboard);
d->updateActions();
}
void TextEditorWidget::cut()
@@ -8735,32 +9219,32 @@ void TextEditorWidget::setupFallBackEditor(Id id)
void TextEditorWidget::appendStandardContextMenuActions(QMenu *menu)
{
if (optionalActions() & TextEditorActionHandler::FollowSymbolUnderCursor) {
if (optionalActions() & OptionalActions::FollowSymbolUnderCursor) {
const auto action = ActionManager::command(Constants::FOLLOW_SYMBOL_UNDER_CURSOR)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::FollowTypeUnderCursor) {
if (optionalActions() & OptionalActions::FollowTypeUnderCursor) {
const auto action = ActionManager::command(Constants::FOLLOW_SYMBOL_TO_TYPE)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::FindUsage) {
if (optionalActions() & OptionalActions::FindUsage) {
const auto action = ActionManager::command(Constants::FIND_USAGES)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::RenameSymbol) {
if (optionalActions() & OptionalActions::RenameSymbol) {
const auto action = ActionManager::command(Constants::RENAME_SYMBOL)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::CallHierarchy) {
if (optionalActions() & OptionalActions::CallHierarchy) {
const auto action = ActionManager::command(Constants::OPEN_CALL_HIERARCHY)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
}
if (optionalActions() & TextEditorActionHandler::TypeHierarchy) {
if (optionalActions() & OptionalActions::TypeHierarchy) {
const auto action = ActionManager::command(Constants::OPEN_TYPE_HIERARCHY)->action();
if (!menu->actions().contains(action))
menu->addAction(action);
@@ -8792,7 +9276,7 @@ void TextEditorWidget::setOptionalActions(uint optionalActionMask)
if (d->m_optionalActionMask == optionalActionMask)
return;
d->m_optionalActionMask = optionalActionMask;
emit optionalActionMaskChanged();
d->updateOptionalActions();
}
void TextEditorWidget::addOptionalActions( uint optionalActionMask)
@@ -9492,7 +9976,7 @@ public:
CommentDefinition m_commentDefinition;
QList<BaseHoverHandler *> m_hoverHandlers; // owned
std::unique_ptr<CompletionAssistProvider> m_completionAssistProvider; // owned
std::unique_ptr<TextEditorActionHandler> m_textEditorActionHandler;
int m_optionalActionMask = 0;
bool m_useGenericHighlighter = false;
bool m_duplicatedSupported = true;
bool m_codeFoldingSupported = false;
@@ -9565,9 +10049,9 @@ void TextEditorFactory::setAutoCompleterCreator(const AutoCompleterCreator &crea
d->m_autoCompleterCreator = creator;
}
void TextEditorFactory::setEditorActionHandlers(uint optionalActions)
void TextEditorFactory::setOptionalActionMask(int optionalActions)
{
d->m_textEditorActionHandler.reset(new TextEditorActionHandler(id(), id(), optionalActions));
d->m_optionalActionMask = optionalActions;
}
void TextEditorFactory::addHoverHandler(BaseHoverHandler *handler)
@@ -9613,8 +10097,7 @@ BaseTextEditor *TextEditorFactoryPrivate::createEditorHelper(const TextDocumentP
textEditorWidget->setMarksVisible(m_marksVisible);
textEditorWidget->setParenthesesMatchingEnabled(m_paranthesesMatchinEnabled);
textEditorWidget->setCodeFoldingSupported(m_codeFoldingSupported);
if (m_textEditorActionHandler)
textEditorWidget->setOptionalActions(m_textEditorActionHandler->optionalActions());
textEditorWidget->setOptionalActions(m_optionalActionMask);
BaseTextEditor *editor = m_editorCreator();
editor->setDuplicateSupported(m_duplicatedSupported);