aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r--src/plugins/texteditor/CMakeLists.txt4
-rw-r--r--src/plugins/texteditor/TextEditor.json.in2
-rw-r--r--src/plugins/texteditor/basefilefind.cpp57
-rw-r--r--src/plugins/texteditor/basefilefind.h10
-rw-r--r--src/plugins/texteditor/bookmarkmanager.cpp1
-rw-r--r--src/plugins/texteditor/commentssettings.cpp2
-rw-r--r--src/plugins/texteditor/completionsettingspage.cpp2
-rw-r--r--src/plugins/texteditor/displaysettingspage.cpp2
-rw-r--r--src/plugins/texteditor/findincurrentfile.cpp29
-rw-r--r--src/plugins/texteditor/findinfiles.cpp22
-rw-r--r--src/plugins/texteditor/findinfiles.h7
-rw-r--r--src/plugins/texteditor/findinopenfiles.cpp29
-rw-r--r--src/plugins/texteditor/fontsettings.cpp3
-rw-r--r--src/plugins/texteditor/fontsettingspage.cpp7
-rw-r--r--src/plugins/texteditor/formattexteditor.cpp131
-rw-r--r--src/plugins/texteditor/formattexteditor.h24
-rw-r--r--src/plugins/texteditor/highlighter_test.cpp7
-rw-r--r--src/plugins/texteditor/highlighterhelper.cpp5
-rw-r--r--src/plugins/texteditor/jsoneditor.cpp3
-rw-r--r--src/plugins/texteditor/markdowneditor.cpp43
-rw-r--r--src/plugins/texteditor/plaintexteditorfactory.cpp7
-rw-r--r--src/plugins/texteditor/refactoringchanges.cpp11
-rw-r--r--src/plugins/texteditor/refactoringchanges.h1
-rw-r--r--src/plugins/texteditor/semantichighlighter.cpp30
-rw-r--r--src/plugins/texteditor/semantichighlighter.h7
-rw-r--r--src/plugins/texteditor/snippets/snippetssettings.cpp46
-rw-r--r--src/plugins/texteditor/snippets/snippetssettings.h37
-rw-r--r--src/plugins/texteditor/snippets/snippetssettingspage.cpp21
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.cpp223
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.h78
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.cpp385
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.h79
-rw-r--r--src/plugins/texteditor/textdocument.cpp54
-rw-r--r--src/plugins/texteditor/textdocument.h5
-rw-r--r--src/plugins/texteditor/texteditor.cpp732
-rw-r--r--src/plugins/texteditor/texteditor.h36
-rw-r--r--src/plugins/texteditor/texteditor.qbs11
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.cpp656
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.h68
-rw-r--r--src/plugins/texteditor/texteditorconstants.h2
-rw-r--r--src/plugins/texteditor/texteditorplugin.cpp317
-rw-r--r--src/plugins/texteditor/textmark.cpp2
-rw-r--r--src/plugins/texteditor/typehierarchy.cpp136
-rw-r--r--src/plugins/texteditor/typehierarchy.h39
44 files changed, 1549 insertions, 1824 deletions
diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt
index 886b98390ce..22abf9d8a1e 100644
--- a/src/plugins/texteditor/CMakeLists.txt
+++ b/src/plugins/texteditor/CMakeLists.txt
@@ -92,11 +92,9 @@ add_qtc_plugin(TextEditor
snippets/snippetparser.cpp snippets/snippetparser.h
snippets/snippetprovider.cpp snippets/snippetprovider.h
snippets/snippetscollection.cpp snippets/snippetscollection.h
- snippets/snippetssettings.cpp snippets/snippetssettings.h
snippets/snippetssettingspage.cpp snippets/snippetssettingspage.h
storagesettings.cpp storagesettings.h
syntaxhighlighter.cpp syntaxhighlighter.h
- syntaxhighlighterrunner.cpp syntaxhighlighterrunner.h
tabsettings.cpp tabsettings.h
tabsettingswidget.cpp tabsettingswidget.h
textdocument.cpp textdocument.h
@@ -105,7 +103,6 @@ add_qtc_plugin(TextEditor
texteditor.qrc
texteditor_global.h
texteditortr.h
- texteditoractionhandler.cpp texteditoractionhandler.h
texteditorconstants.cpp texteditorconstants.h
texteditoroverlay.cpp texteditoroverlay.h
texteditorplugin.cpp
@@ -113,6 +110,7 @@ add_qtc_plugin(TextEditor
textindenter.cpp textindenter.h
textmark.cpp textmark.h
textstyles.h
+ typehierarchy.cpp typehierarchy.h
typingsettings.cpp typingsettings.h
)
diff --git a/src/plugins/texteditor/TextEditor.json.in b/src/plugins/texteditor/TextEditor.json.in
index f2b6fbbcf58..42e32325edd 100644
--- a/src/plugins/texteditor/TextEditor.json.in
+++ b/src/plugins/texteditor/TextEditor.json.in
@@ -14,7 +14,7 @@
],
"Category" : "Core",
"Description" : "Text editor framework and the implementation of the basic text editor.",
- "Url" : "http://www.qt.io",
+ "Url" : "https://www.qt.io",
${IDE_PLUGIN_DEPENDENCIES},
"Mimetypes" : [
"<?xml version='1.0'?>",
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 399e275fe4f..d18a75531b3 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -21,7 +21,7 @@
#include <utils/algorithm.h>
#include <utils/fadingindicator.h>
#include <utils/futuresynchronizer.h>
-#include <utils/process.h>
+#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
#include <QComboBox>
@@ -139,8 +139,8 @@ public:
QString title() const override { return Tr::tr("Internal"); }
QString toolTip() const override { return {}; }
QWidget *widget() const override { return m_widget; }
- void readSettings(QtcSettings * /*settings*/) override {}
- void writeSettings(QtcSettings * /*settings*/) const override {}
+ void readSettings(const Store &) override {}
+ void writeSettings(Store &) const override {}
SearchExecutor searchExecutor() const override
{
return [](const FileFindParameters &parameters) {
@@ -442,47 +442,57 @@ FilePath BaseFileFind::searchDir() const
return d->m_searchDir;
}
-void BaseFileFind::writeCommonSettings(QtcSettings *settings)
+void BaseFileFind::writeCommonSettings(
+ Store &s, const QString &defaultFilter, const QString &defaultExclusionFilter) const
{
const auto fromNativeSeparators = [](const QStringList &files) -> QStringList {
return Utils::transform(files, &QDir::fromNativeSeparators);
};
- settings->setValue("filters", fromNativeSeparators(d->m_filterStrings.stringList()));
- if (d->m_filterCombo)
- settings->setValue("currentFilter",
- QDir::fromNativeSeparators(d->m_filterCombo->currentText()));
- settings->setValue("exclusionFilters", fromNativeSeparators(d->m_exclusionStrings.stringList()));
- if (d->m_exclusionCombo)
- settings->setValue("currentExclusionFilter",
- QDir::fromNativeSeparators(d->m_exclusionCombo->currentText()));
+ const QStringList filterStrings = fromNativeSeparators(d->m_filterStrings.stringList());
+ if (filterStrings.size() != 1 || filterStrings.first() != defaultFilter)
+ s.insert("filters", filterStrings);
+ const QString currentFilter = d->m_filterCombo
+ ? QDir::fromNativeSeparators(d->m_filterCombo->currentText())
+ : d->m_filterSetting;
+ if (currentFilter != defaultFilter)
+ s.insert("currentFilter", currentFilter);
+ const QStringList exclusionFilters = fromNativeSeparators(d->m_exclusionStrings.stringList());
+ if (exclusionFilters.size() != 1 || exclusionFilters.first() != defaultExclusionFilter)
+ s.insert("exclusionFilters", exclusionFilters);
+ const QString currentExclusionFilter = d->m_exclusionCombo ? QDir::fromNativeSeparators(
+ d->m_exclusionCombo->currentText())
+ : d->m_exclusionSetting;
+ if (currentExclusionFilter != defaultExclusionFilter)
+ s.insert("currentExclusionFilter", currentExclusionFilter);
for (const SearchEngine *searchEngine : std::as_const(d->m_searchEngines))
- searchEngine->writeSettings(settings);
- settings->setValue("currentSearchEngineIndex", d->m_currentSearchEngineIndex);
+ searchEngine->writeSettings(s);
+ if (d->m_currentSearchEngineIndex != 0)
+ s.insert("currentSearchEngineIndex", d->m_currentSearchEngineIndex);
}
-void BaseFileFind::readCommonSettings(QtcSettings *settings, const QString &defaultFilter,
- const QString &defaultExclusionFilter)
+void BaseFileFind::readCommonSettings(
+ const Store &s, const QString &defaultFilter, const QString &defaultExclusionFilter)
{
const auto toNativeSeparators = [](const QStringList &files) -> QStringList {
return Utils::transform(files, &QDir::toNativeSeparators);
};
- const QStringList filterSetting = settings->value("filters").toStringList();
+ const QStringList filterSetting = s.value("filters").toStringList();
const QStringList filters = filterSetting.isEmpty() ? QStringList(defaultFilter)
: filterSetting;
- const QVariant currentFilter = settings->value("currentFilter");
+ const QVariant currentFilter = s.value("currentFilter");
d->m_filterSetting = currentFilter.isValid() ? currentFilter.toString()
: filters.first();
d->m_filterStrings.setStringList(toNativeSeparators(filters));
if (d->m_filterCombo)
syncComboWithSettings(d->m_filterCombo, d->m_filterSetting);
- QStringList exclusionFilters = settings->value("exclusionFilters").toStringList();
+ QStringList exclusionFilters = s.value("exclusionFilters").toStringList();
if (!exclusionFilters.contains(defaultExclusionFilter))
exclusionFilters << defaultExclusionFilter;
- const QVariant currentExclusionFilter = settings->value("currentExclusionFilter");
+ const QVariant currentExclusionFilter = s.value("currentExclusionFilter");
d->m_exclusionSetting = currentExclusionFilter.isValid() ? currentExclusionFilter.toString()
: exclusionFilters.first();
d->m_exclusionStrings.setStringList(toNativeSeparators(exclusionFilters));
@@ -490,8 +500,8 @@ void BaseFileFind::readCommonSettings(QtcSettings *settings, const QString &defa
syncComboWithSettings(d->m_exclusionCombo, d->m_exclusionSetting);
for (SearchEngine* searchEngine : std::as_const(d->m_searchEngines))
- searchEngine->readSettings(settings);
- const int currentSearchEngineIndex = settings->value("currentSearchEngineIndex", 0).toInt();
+ searchEngine->readSettings(s);
+ const int currentSearchEngineIndex = s.value("currentSearchEngineIndex", 0).toInt();
syncSearchEngineCombo(currentSearchEngineIndex);
}
@@ -594,8 +604,7 @@ FilePaths BaseFileFind::replaceAll(const QString &text, const SearchResultItems
item.mainRange().end.column + 1);
changeSet.replace(start, end, replacement);
}
- file->setChangeSet(changeSet);
- file->apply();
+ file->apply(changeSet);
}
return changes.keys();
diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h
index 47adae4b866..de4286c31b6 100644
--- a/src/plugins/texteditor/basefilefind.h
+++ b/src/plugins/texteditor/basefilefind.h
@@ -69,8 +69,8 @@ public:
virtual QString title() const = 0;
virtual QString toolTip() const = 0; // add %1 placeholder where the find flags should be put
virtual QWidget *widget() const = 0;
- virtual void readSettings(Utils::QtcSettings *settings) = 0;
- virtual void writeSettings(Utils::QtcSettings *settings) const = 0;
+ virtual void readSettings(const Utils::Store &s) = 0;
+ virtual void writeSettings(Utils::Store &settings) const = 0;
virtual SearchExecutor searchExecutor() const = 0;
virtual EditorOpener editorOpener() const { return {}; }
bool isEnabled() const;
@@ -108,8 +108,10 @@ protected:
virtual QString toolTip() const = 0; // see Core::SearchResultWindow::startNewSearch,
// add %1 placeholder where the find flags should be put
- void writeCommonSettings(Utils::QtcSettings *settings);
- void readCommonSettings(Utils::QtcSettings *settings, const QString &defaultFilter, const QString &defaultExclusionFilter);
+ void writeCommonSettings(
+ Utils::Store &s, const QString &defaultFilter, const QString &defaultExclusionFilter) const;
+ void readCommonSettings(
+ const Utils::Store &s, const QString &defaultFilter, const QString &defaultExclusionFilter);
QList<QPair<QWidget *, QWidget *>> createPatternWidgets();
QStringList fileNameFilters() const;
QStringList fileExclusionFilters() const;
diff --git a/src/plugins/texteditor/bookmarkmanager.cpp b/src/plugins/texteditor/bookmarkmanager.cpp
index 6dcb4de6cc5..a61cc587363 100644
--- a/src/plugins/texteditor/bookmarkmanager.cpp
+++ b/src/plugins/texteditor/bookmarkmanager.cpp
@@ -876,6 +876,7 @@ void BookmarkManager::edit()
auto layout = new QFormLayout(&dlg);
auto noteEdit = new QLineEdit(b->note());
noteEdit->setMinimumWidth(300);
+ noteEdit->setFocus();
auto lineNumberSpinbox = new QSpinBox;
lineNumberSpinbox->setRange(1, INT_MAX);
lineNumberSpinbox->setValue(b->lineNumber());
diff --git a/src/plugins/texteditor/commentssettings.cpp b/src/plugins/texteditor/commentssettings.cpp
index bc6f76cb4bd..d3171a94d68 100644
--- a/src/plugins/texteditor/commentssettings.cpp
+++ b/src/plugins/texteditor/commentssettings.cpp
@@ -106,7 +106,7 @@ CommentsSettingsWidget::CommentsSettingsWidget(const CommentsSettings::Data &set
const auto commandPrefixLabel = new QLabel(Tr::tr("Doxygen command prefix:"));
const QString commandPrefixToolTip = Tr::tr(R"(Doxygen allows "@" and "\" to start commands.
By default, "@" is used if the surrounding comment starts with "/**" or "///", and "\" is used
-if the comment starts with "/*!" or "//!)");
+if the comment starts with "/*!" or "//!".)");
commandPrefixLabel->setToolTip(commandPrefixToolTip);
d->m_commandPrefixComboBox.setToolTip(commandPrefixToolTip);
d->m_commandPrefixComboBox.addItem(Tr::tr("Automatic"));
diff --git a/src/plugins/texteditor/completionsettingspage.cpp b/src/plugins/texteditor/completionsettingspage.cpp
index aba86467143..03f45404c6b 100644
--- a/src/plugins/texteditor/completionsettingspage.cpp
+++ b/src/plugins/texteditor/completionsettingspage.cpp
@@ -214,7 +214,7 @@ CompletionSettingsPageWidget::CompletionSettingsPageWidget(CompletionSettingsPag
}
},
Group {
- title(Tr::tr("&Automatically insert matching characters")),
+ title(Tr::tr("&Automatically Insert Matching Characters")),
Row {
Column {
m_insertBrackets,
diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp
index b5435ed5e91..fe914b27ce9 100644
--- a/src/plugins/texteditor/displaysettingspage.cpp
+++ b/src/plugins/texteditor/displaysettingspage.cpp
@@ -108,7 +108,7 @@ public:
rightAligned->setChecked(true);
betweenLines = new QRadioButton(Tr::tr("Between lines"));
- displayAnnotations = new QGroupBox(Tr::tr("Line annotations")),
+ displayAnnotations = new QGroupBox(Tr::tr("Line Annotations")),
displayAnnotations->setCheckable(true);
using namespace Layouting;
diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp
index 7d3ad849972..45121f72d84 100644
--- a/src/plugins/texteditor/findincurrentfile.cpp
+++ b/src/plugins/texteditor/findincurrentfile.cpp
@@ -27,8 +27,8 @@ private:
QString id() const final;
QString displayName() const final;
bool isEnabled() const final;
- void writeSettings(Utils::QtcSettings *settings) final;
- void readSettings(Utils::QtcSettings *settings) final;
+ Utils::Store save() const final;
+ void restore(const Utils::Store &s) final;
QString label() const final;
QString toolTip() const final;
@@ -37,6 +37,9 @@ private:
void handleFileChange(Core::IEditor *editor);
QPointer<Core::IDocument> m_currentDocument;
+
+ // deprecated
+ QByteArray settingsKey() const final;
};
FindInCurrentFile::FindInCurrentFile()
@@ -97,18 +100,24 @@ void FindInCurrentFile::handleFileChange(Core::IEditor *editor)
}
}
-void FindInCurrentFile::writeSettings(QtcSettings *settings)
+const char kDefaultInclusion[] = "*";
+const char kDefaultExclusion[] = "";
+
+Store FindInCurrentFile::save() const
+{
+ Store s;
+ writeCommonSettings(s, kDefaultInclusion, kDefaultExclusion);
+ return s;
+}
+
+void FindInCurrentFile::restore(const Store &s)
{
- settings->beginGroup("FindInCurrentFile");
- writeCommonSettings(settings);
- settings->endGroup();
+ readCommonSettings(s, kDefaultInclusion, kDefaultExclusion);
}
-void FindInCurrentFile::readSettings(QtcSettings *settings)
+QByteArray FindInCurrentFile::settingsKey() const
{
- settings->beginGroup("FindInCurrentFile");
- readCommonSettings(settings, "*", "");
- settings->endGroup();
+ return "FindInCurrentFile";
}
void setupFindInCurrentFile()
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index 955316954b5..9dc68cd6532 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -188,18 +188,24 @@ QWidget *FindInFiles::createConfigWidget()
return m_configWidget;
}
-void FindInFiles::writeSettings(QtcSettings *settings)
+const char kDefaultInclusion[] = "*.cpp,*.h";
+const char kDefaultExclusion[] = "*/.git/*,*/.cvs/*,*/.svn/*,*.autosave,*/build/*";
+
+Store FindInFiles::save() const
+{
+ Store s;
+ writeCommonSettings(s, kDefaultInclusion, kDefaultExclusion);
+ return s;
+}
+
+void FindInFiles::restore(const Utils::Store &s)
{
- settings->beginGroup("FindInFiles");
- writeCommonSettings(settings);
- settings->endGroup();
+ readCommonSettings(s, kDefaultInclusion, kDefaultExclusion);
}
-void FindInFiles::readSettings(QtcSettings *settings)
+QByteArray FindInFiles::settingsKey() const
{
- settings->beginGroup("FindInFiles");
- readCommonSettings(settings, "*.cpp,*.h", "*/.git/*,*/.cvs/*,*/.svn/*,*.autosave");
- settings->endGroup();
+ return "FindInFiles";
}
void FindInFiles::setBaseDirectory(const FilePath &directory)
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index c7803a16ed4..b3bd7b7095b 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -30,8 +30,8 @@ public:
QString id() const override;
QString displayName() const override;
QWidget *createConfigWidget() override;
- void writeSettings(Utils::QtcSettings *settings) override;
- void readSettings(Utils::QtcSettings *settings) override;
+ Utils::Store save() const override;
+ void restore(const Utils::Store &s) override;
bool isValid() const override;
void setDirectory(const Utils::FilePath &directory);
@@ -39,6 +39,9 @@ public:
static void findOnFileSystem(const QString &path);
static FindInFiles *instance();
+ // deprecated
+ QByteArray settingsKey() const override;
+
protected:
QString label() const override;
QString toolTip() const override;
diff --git a/src/plugins/texteditor/findinopenfiles.cpp b/src/plugins/texteditor/findinopenfiles.cpp
index dcd505cbe1f..deeb66e9f5f 100644
--- a/src/plugins/texteditor/findinopenfiles.cpp
+++ b/src/plugins/texteditor/findinopenfiles.cpp
@@ -25,14 +25,17 @@ private:
QString id() const final;
QString displayName() const final;
bool isEnabled() const final;
- void writeSettings(Utils::QtcSettings *settings) final;
- void readSettings(Utils::QtcSettings *settings) final;
+ Utils::Store save() const final;
+ void restore(const Utils::Store &s) final;
QString label() const final;
QString toolTip() const final;
FileContainerProvider fileContainerProvider() const final;
void updateEnabledState() { emit enabledChanged(isEnabled()); }
+
+ // deprecated
+ QByteArray settingsKey() const final;
};
FindInOpenFiles::FindInOpenFiles()
@@ -90,21 +93,25 @@ bool FindInOpenFiles::isEnabled() const
return Core::DocumentModel::entryCount() > 0;
}
-void FindInOpenFiles::writeSettings(QtcSettings *settings)
+const char kDefaultInclusion[] = "*";
+const char kDefaultExclusion[] = "";
+
+Store FindInOpenFiles::save() const
{
- settings->beginGroup("FindInOpenFiles");
- writeCommonSettings(settings);
- settings->endGroup();
+ Store s;
+ writeCommonSettings(s, kDefaultInclusion, kDefaultExclusion);
+ return s;
}
-void FindInOpenFiles::readSettings(QtcSettings *settings)
+void FindInOpenFiles::restore(const Store &s)
{
- settings->beginGroup("FindInOpenFiles");
- readCommonSettings(settings, "*", "");
- settings->endGroup();
+ readCommonSettings(s, kDefaultInclusion, kDefaultExclusion);
}
-
+QByteArray FindInOpenFiles::settingsKey() const
+{
+ return "FindInOpenFiles";
+}
void setupFindInOpenFiles()
{
diff --git a/src/plugins/texteditor/fontsettings.cpp b/src/plugins/texteditor/fontsettings.cpp
index e74a37c0d37..44b179d01c8 100644
--- a/src/plugins/texteditor/fontsettings.cpp
+++ b/src/plugins/texteditor/fontsettings.cpp
@@ -491,8 +491,7 @@ static QString defaultFontFamily()
return QLatin1String("Menlo");
const QString sourceCodePro(g_sourceCodePro);
- const QFontDatabase dataBase;
- if (dataBase.hasFamily(sourceCodePro))
+ if (QFontDatabase::hasFamily(sourceCodePro))
return sourceCodePro;
if (Utils::HostOsInfo::isAnyUnixHost())
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index bdd899b7e04..f528496dcf0 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -458,15 +458,14 @@ void FontSettingsPageWidget::updateFontZoom(const FontSettings &fontSettings)
QList<int> FontSettingsPageWidget::pointSizesForSelectedFont() const
{
- QFontDatabase db;
const QString familyName = m_fontComboBox->currentFont().family();
- QList<int> sizeLst = db.pointSizes(familyName);
+ QList<int> sizeLst = QFontDatabase::pointSizes(familyName);
if (!sizeLst.isEmpty())
return sizeLst;
- QStringList styles = db.styles(familyName);
+ QStringList styles = QFontDatabase::styles(familyName);
if (!styles.isEmpty())
- sizeLst = db.pointSizes(familyName, styles.first());
+ sizeLst = QFontDatabase::pointSizes(familyName, styles.first());
if (sizeLst.isEmpty())
sizeLst = QFontDatabase::standardSizes();
diff --git a/src/plugins/texteditor/formattexteditor.cpp b/src/plugins/texteditor/formattexteditor.cpp
index 14f3d4e4e78..4bd358e3e39 100644
--- a/src/plugins/texteditor/formattexteditor.cpp
+++ b/src/plugins/texteditor/formattexteditor.cpp
@@ -12,8 +12,10 @@
#include <utils/async.h>
#include <utils/differ.h>
-#include <utils/process.h>
+#include <utils/expected.h>
+#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
#include <utils/temporarydirectory.h>
#include <utils/textutils.h>
@@ -27,6 +29,17 @@ using namespace std::chrono_literals;
namespace TextEditor {
+struct FormatInput
+{
+ Utils::FilePath filePath;
+ QString sourceData;
+ TextEditor::Command command;
+ int startPos = -1;
+ int endPos = 0;
+};
+
+using FormatOutput = expected_str<QString>;
+
void formatCurrentFile(const Command &command, int startPos, int endPos)
{
if (TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget())
@@ -40,89 +53,80 @@ static QString sourceData(TextEditorWidget *editor, int startPos, int endPos)
: Utils::Text::textAt(editor->textCursor(), startPos, (endPos - startPos));
}
-static FormatTask format(FormatTask task)
+static FormatOutput format(const FormatInput &input)
{
- task.error.clear();
- task.formattedData.clear();
-
- const FilePath executable = task.command.executable();
+ const FilePath executable = input.command.executable();
if (executable.isEmpty())
- return task;
+ return {};
- switch (task.command.processing()) {
+ switch (input.command.processing()) {
case Command::FileProcessing: {
// Save text to temporary file
Utils::TempFileSaver sourceFile(Utils::TemporaryDirectory::masterDirectoryPath()
- + "/qtc_beautifier_XXXXXXXX."
- + task.filePath.suffix());
+ + "/qtc_beautifier_XXXXXXXX." + input.filePath.suffix());
sourceFile.setAutoRemove(true);
- sourceFile.write(task.sourceData.toUtf8());
+ sourceFile.write(input.sourceData.toUtf8());
if (!sourceFile.finalize()) {
- task.error = Tr::tr("Cannot create temporary file \"%1\": %2.")
- .arg(sourceFile.filePath().toUserOutput(), sourceFile.errorString());
- return task;
+ return Utils::make_unexpected(Tr::tr("Cannot create temporary file \"%1\": %2.")
+ .arg(sourceFile.filePath().toUserOutput(), sourceFile.errorString()));
}
// Format temporary file
- QStringList options = task.command.options();
+ QStringList options = input.command.options();
options.replaceInStrings(QLatin1String("%file"), sourceFile.filePath().toString());
Process process;
process.setCommand({executable, options});
process.runBlocking(5s);
if (process.result() != ProcessResult::FinishedWithSuccess) {
- task.error = Tr::tr("Failed to format: %1.").arg(process.exitMessage());
- return task;
+ return Utils::make_unexpected(Tr::tr("Failed to format: %1.")
+ .arg(process.exitMessage()));
}
const QString output = process.cleanedStdErr();
if (!output.isEmpty())
- task.error = executable.toUserOutput() + ": " + output;
+ return Utils::make_unexpected(executable.toUserOutput() + ": " + output);
// Read text back
Utils::FileReader reader;
if (!reader.fetch(sourceFile.filePath(), QIODevice::Text)) {
- task.error = Tr::tr("Cannot read file \"%1\": %2.")
- .arg(sourceFile.filePath().toUserOutput(), reader.errorString());
- return task;
+ return Utils::make_unexpected(Tr::tr("Cannot read file \"%1\": %2.")
+ .arg(sourceFile.filePath().toUserOutput(), reader.errorString()));
}
- task.formattedData = QString::fromUtf8(reader.data());
+ return QString::fromUtf8(reader.data());
}
- return task;
case Command::PipeProcessing: {
Process process;
- QStringList options = task.command.options();
- options.replaceInStrings("%filename", task.filePath.fileName());
- options.replaceInStrings("%file", task.filePath.toString());
+ QStringList options = input.command.options();
+ options.replaceInStrings("%filename", input.filePath.fileName());
+ options.replaceInStrings("%file", input.filePath.toString());
process.setCommand({executable, options});
- process.setWriteData(task.sourceData.toUtf8());
+ process.setWriteData(input.sourceData.toUtf8());
process.start();
if (!process.waitForFinished(5s)) {
- task.error = Tr::tr("Cannot call %1 or some other error occurred. Timeout "
- "reached while formatting file %2.")
- .arg(executable.toUserOutput(), task.filePath.displayName());
- return task;
+ return Utils::make_unexpected(Tr::tr("Cannot call %1 or some other error occurred. "
+ "Timeout reached while formatting file %2.")
+ .arg(executable.toUserOutput(), input.filePath.displayName()));
}
const QString errorText = process.readAllStandardError();
if (!errorText.isEmpty()) {
- task.error = QString("%1: %2").arg(executable.toUserOutput(), errorText);
- return task;
+ return Utils::make_unexpected(QString("%1: %2").arg(executable.toUserOutput(),
+ errorText));
}
- task.formattedData = process.readAllStandardOutput();
+ QString formattedData = process.readAllStandardOutput();
- if (task.command.pipeAddsNewline() && task.formattedData.endsWith('\n')) {
- task.formattedData.chop(1);
- if (task.formattedData.endsWith('\r'))
- task.formattedData.chop(1);
+ if (input.command.pipeAddsNewline() && formattedData.endsWith('\n')) {
+ formattedData.chop(1);
+ if (formattedData.endsWith('\r'))
+ formattedData.chop(1);
}
- if (task.command.returnsCRLF())
- task.formattedData.replace("\r\n", "\n");
+ if (input.command.returnsCRLF())
+ formattedData.replace("\r\n", "\n");
- return task;
+ return formattedData;
}
}
-
- return task;
+ return {};
}
/**
@@ -256,31 +260,26 @@ static void showError(const QString &error)
* Checks the state of @a task and if the formatting was successful calls updateEditorText() with
* the respective members of @a task.
*/
-static void checkAndApplyTask(const FormatTask &task)
+static void checkAndApplyTask(const QPointer<QPlainTextEdit> &textEditor, const FormatInput &input,
+ const FormatOutput &output)
{
- if (!task.error.isEmpty()) {
- showError(task.error);
+ if (!output.has_value()) {
+ showError(output.error());
return;
}
- if (task.formattedData.isEmpty()) {
- showError(Tr::tr("Could not format file %1.").arg(
- task.filePath.displayName()));
+ if (output->isEmpty()) {
+ showError(Tr::tr("Could not format file %1.").arg(input.filePath.displayName()));
return;
}
- QPlainTextEdit *textEditor = task.editor;
if (!textEditor) {
- showError(Tr::tr("File %1 was closed.").arg(
- task.filePath.displayName()));
+ showError(Tr::tr("File %1 was closed.").arg(input.filePath.displayName()));
return;
}
- const QString formattedData = (task.startPos < 0)
- ? task.formattedData
- : QString(textEditor->toPlainText()).replace(
- task.startPos, (task.endPos - task.startPos), task.formattedData);
-
+ const QString formattedData = (input.startPos < 0) ? *output
+ : textEditor->toPlainText().replace(input.startPos, (input.endPos - input.startPos), *output);
updateEditorText(textEditor, formattedData);
}
@@ -298,8 +297,8 @@ void formatEditor(TextEditorWidget *editor, const Command &command, int startPos
const QString sd = sourceData(editor, startPos, endPos);
if (sd.isEmpty())
return;
- checkAndApplyTask(format(FormatTask(editor, editor->textDocument()->filePath(), sd,
- command, startPos, endPos)));
+ const FormatInput input{editor->textDocument()->filePath(), sd, command, startPos, endPos};
+ checkAndApplyTask(editor, input, format(input));
}
/**
@@ -313,18 +312,20 @@ void formatEditorAsync(TextEditorWidget *editor, const Command &command, int sta
if (sd.isEmpty())
return;
- auto watcher = new QFutureWatcher<FormatTask>;
+ auto watcher = new QFutureWatcher<FormatOutput>;
const TextDocument *doc = editor->textDocument();
- QObject::connect(doc, &TextDocument::contentsChanged, watcher, &QFutureWatcher<FormatTask>::cancel);
- QObject::connect(watcher, &QFutureWatcherBase::finished, [watcher] {
+ const FormatInput input{doc->filePath(), sd, command, startPos, endPos};
+ QObject::connect(doc, &TextDocument::contentsChanged, watcher,
+ &QFutureWatcher<FormatOutput>::cancel);
+ QObject::connect(watcher, &QFutureWatcherBase::finished, watcher,
+ [watcher, editor = QPointer<QPlainTextEdit>(editor), input] {
if (watcher->isCanceled())
showError(Tr::tr("File was modified."));
else
- checkAndApplyTask(watcher->result());
+ checkAndApplyTask(editor, input, watcher->result());
watcher->deleteLater();
});
- watcher->setFuture(Utils::asyncRun(&format, FormatTask(editor, doc->filePath(), sd,
- command, startPos, endPos)));
+ watcher->setFuture(Utils::asyncRun(&format, input));
}
} // namespace TextEditor
diff --git a/src/plugins/texteditor/formattexteditor.h b/src/plugins/texteditor/formattexteditor.h
index e1c58cdf94f..929763ecba8 100644
--- a/src/plugins/texteditor/formattexteditor.h
+++ b/src/plugins/texteditor/formattexteditor.h
@@ -10,35 +10,11 @@
#include <utils/filepath.h>
#include <QPlainTextEdit>
-#include <QPointer>
namespace TextEditor {
class TextEditorWidget;
-class TEXTEDITOR_EXPORT FormatTask
-{
-public:
- FormatTask(QPlainTextEdit *_editor, const Utils::FilePath &_filePath, const QString &_sourceData,
- const Command &_command, int _startPos = -1, int _endPos = 0) :
- editor(_editor),
- filePath(_filePath),
- sourceData(_sourceData),
- command(_command),
- startPos(_startPos),
- endPos(_endPos)
- {}
-
- QPointer<QPlainTextEdit> editor;
- Utils::FilePath filePath;
- QString sourceData;
- TextEditor::Command command;
- int startPos = -1;
- int endPos = 0;
- QString formattedData;
- QString error;
-};
-
TEXTEDITOR_EXPORT void formatCurrentFile(const TextEditor::Command &command, int startPos = -1, int endPos = 0);
TEXTEDITOR_EXPORT void formatEditor(TextEditorWidget *editor, const TextEditor::Command &command,
int startPos = -1, int endPos = 0);
diff --git a/src/plugins/texteditor/highlighter_test.cpp b/src/plugins/texteditor/highlighter_test.cpp
index d50c560e23a..2cbd2b75d57 100644
--- a/src/plugins/texteditor/highlighter_test.cpp
+++ b/src/plugins/texteditor/highlighter_test.cpp
@@ -1,11 +1,10 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include "syntaxhighlighterrunner.h"
-
#include "highlighter_test.h"
#include "fontsettings.h"
+#include "syntaxhighlighter.h"
#include "textdocument.h"
#include "texteditor.h"
#include "texteditorsettings.h"
@@ -61,7 +60,7 @@ void GenerigHighlighterTests::initTestCase()
m_editor->editorWidget()->configureGenericHighlighter(
Utils::mimeTypeForName(Utils::Constants::JSON_MIMETYPE));
QVERIFY(m_editor);
- m_editor->textDocument()->syntaxHighlighterRunner()->rehighlight();
+ m_editor->textDocument()->syntaxHighlighter()->rehighlight();
}
using FormatRanges = QList<QTextLayout::FormatRange>;
@@ -214,7 +213,7 @@ void GenerigHighlighterTests::testPreeditText()
block.layout()->setPreeditArea(7, "uaf");
c.endEditBlock();
- m_editor->textDocument()->syntaxHighlighterRunner()->rehighlight();
+ m_editor->textDocument()->syntaxHighlighter()->rehighlight();
const FormatRanges formatRanges = {{0, 4, toFormat(C_VISUAL_WHITESPACE)},
{4, 3, toFormat(C_TYPE)},
diff --git a/src/plugins/texteditor/highlighterhelper.cpp b/src/plugins/texteditor/highlighterhelper.cpp
index 6aa98439c05..e25b935f8ac 100644
--- a/src/plugins/texteditor/highlighterhelper.cpp
+++ b/src/plugins/texteditor/highlighterhelper.cpp
@@ -9,7 +9,6 @@
#include "texteditor.h"
#include "texteditorsettings.h"
#include "texteditortr.h"
-#include "syntaxhighlighterrunner.h"
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/icore.h>
@@ -210,8 +209,8 @@ void reload()
highlightRepository()->reload();
for (auto editor : Core::DocumentModel::editorsForOpenedDocuments()) {
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
- if (auto highlighterRunner = textEditor->textDocument()->syntaxHighlighterRunner();
- highlighterRunner && highlighterRunner->useGenericHighlighter()) {
+ if (auto highlighter = textEditor->textDocument()->syntaxHighlighter();
+ highlighter && qobject_cast<SyntaxHighlighter*>(highlighter)) {
textEditor->editorWidget()->configureGenericHighlighter();
}
}
diff --git a/src/plugins/texteditor/jsoneditor.cpp b/src/plugins/texteditor/jsoneditor.cpp
index d06f215c688..7081394f9be 100644
--- a/src/plugins/texteditor/jsoneditor.cpp
+++ b/src/plugins/texteditor/jsoneditor.cpp
@@ -6,7 +6,6 @@
#include "autocompleter.h"
#include "textdocument.h"
#include "texteditor.h"
-#include "texteditoractionhandler.h"
#include "texteditortr.h"
#include "textindenter.h"
@@ -164,7 +163,7 @@ public:
setDocumentCreator([] { return new TextDocument(JSON_EDITOR_ID); });
setAutoCompleterCreator([] { return new JsonAutoCompleter; });
setIndenterCreator([](QTextDocument *doc) { return new JsonIndenter(doc); });
- setEditorActionHandlers(TextEditorActionHandler::Format);
+ setOptionalActionMask(OptionalActions::Format);
setUseGenericHighlighter(true);
}
};
diff --git a/src/plugins/texteditor/markdowneditor.cpp b/src/plugins/texteditor/markdowneditor.cpp
index dbfdcda2b42..93b580a935e 100644
--- a/src/plugins/texteditor/markdowneditor.cpp
+++ b/src/plugins/texteditor/markdowneditor.cpp
@@ -16,8 +16,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/minisplitter.h>
-#include <texteditor/texteditoractionhandler.h>
-
#include <utils/action.h>
#include <utils/ranges.h>
#include <utils/qtcsettings.h>
@@ -73,7 +71,7 @@ class MarkdownEditor : public IEditor
{
Q_OBJECT
public:
- MarkdownEditor(const TextEditor::TextEditorActionHandler *actionHandler)
+ MarkdownEditor()
: m_document(new TextDocument(MARKDOWNVIEWER_ID))
{
m_document->setMimeType(MARKDOWNVIEWER_MIME_TYPE);
@@ -108,10 +106,25 @@ public:
// editor
m_textEditorWidget = new MarkdownEditorWidget;
- m_textEditorWidget->setOptionalActions(actionHandler->optionalActions());
+ m_textEditorWidget->setOptionalActions(OptionalActions::FollowSymbolUnderCursor);
m_textEditorWidget->setTextDocument(m_document);
m_textEditorWidget->setupGenericHighlighter();
m_textEditorWidget->setMarksVisible(false);
+ QObject::connect(
+ m_textEditorWidget,
+ &TextEditorWidget::saveCurrentStateForNavigationHistory,
+ this,
+ &MarkdownEditor::saveCurrentStateForNavigationHistory);
+ QObject::connect(
+ m_textEditorWidget,
+ &TextEditorWidget::addSavedStateToNavigationHistory,
+ this,
+ &MarkdownEditor::addSavedStateToNavigationHistory);
+ QObject::connect(
+ m_textEditorWidget,
+ &TextEditorWidget::addCurrentStateToNavigationHistory,
+ this,
+ &MarkdownEditor::addCurrentStateToNavigationHistory);
auto context = new IContext(this);
context->setWidget(m_textEditorWidget);
context->setContext(Context(MARKDOWNVIEWER_TEXT_CONTEXT));
@@ -478,6 +491,18 @@ private:
}
}
+ void saveCurrentStateForNavigationHistory() { m_savedNavigationState = saveState(); }
+
+ void addSavedStateToNavigationHistory()
+ {
+ EditorManager::addCurrentPositionToNavigationHistory(m_savedNavigationState);
+ }
+
+ void addCurrentStateToNavigationHistory()
+ {
+ EditorManager::addCurrentPositionToNavigationHistory();
+ }
+
private:
QTimer m_previewTimer;
bool m_performDelayedUpdate = false;
@@ -493,6 +518,7 @@ private:
QAction *m_togglePreviewVisibleAction;
QAction *m_swapViewsAction;
std::optional<QPoint> m_previewRestoreScrollPosition;
+ QByteArray m_savedNavigationState;
};
class MarkdownEditorFactory final : public IEditorFactory
@@ -501,7 +527,6 @@ public:
MarkdownEditorFactory();
private:
- TextEditorActionHandler m_actionHandler;
Action m_emphasisAction;
Action m_strongAction;
Action m_inlineCodeAction;
@@ -512,17 +537,11 @@ private:
};
MarkdownEditorFactory::MarkdownEditorFactory()
- : m_actionHandler(MARKDOWNVIEWER_ID,
- MARKDOWNVIEWER_TEXT_CONTEXT,
- TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor,
- [](IEditor *editor) {
- return static_cast<MarkdownEditor *>(editor)->textEditorWidget();
- })
{
setId(MARKDOWNVIEWER_ID);
setDisplayName(::Core::Tr::tr("Markdown Editor"));
addMimeType(MARKDOWNVIEWER_MIME_TYPE);
- setEditorCreator([this] { return new MarkdownEditor{&m_actionHandler}; });
+ setEditorCreator([] { return new MarkdownEditor; });
const auto textContext = Context(MARKDOWNVIEWER_TEXT_CONTEXT);
const auto context = Context(MARKDOWNVIEWER_ID);
diff --git a/src/plugins/texteditor/plaintexteditorfactory.cpp b/src/plugins/texteditor/plaintexteditorfactory.cpp
index fbaf430284d..ef989ee6216 100644
--- a/src/plugins/texteditor/plaintexteditorfactory.cpp
+++ b/src/plugins/texteditor/plaintexteditorfactory.cpp
@@ -5,7 +5,6 @@
#include "basehoverhandler.h"
#include "textdocument.h"
#include "texteditor.h"
-#include "texteditoractionhandler.h"
#include "texteditorconstants.h"
#include <coreplugin/coreconstants.h>
@@ -40,9 +39,9 @@ public:
setEditorWidgetCreator([]() { return new PlainTextEditorWidget; });
setUseGenericHighlighter(true);
- setEditorActionHandlers(TextEditorActionHandler::Format |
- TextEditorActionHandler::UnCommentSelection |
- TextEditorActionHandler::UnCollapseAll);
+ setOptionalActionMask(
+ OptionalActions::Format | OptionalActions::UnCommentSelection
+ | OptionalActions::UnCollapseAll);
}
};
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp
index ebd487cc370..c8688f2fba5 100644
--- a/src/plugins/texteditor/refactoringchanges.cpp
+++ b/src/plugins/texteditor/refactoringchanges.cpp
@@ -214,6 +214,9 @@ void RefactoringFile::setOpenEditor(bool activate, int pos)
bool RefactoringFile::apply()
{
+ if (m_changes.isEmpty())
+ return true;
+
// test file permissions
if (!m_filePath.isWritableFile()) {
ReadOnlyFilesDialog roDialog(m_filePath, ICore::dialogParent());
@@ -287,6 +290,12 @@ bool RefactoringFile::apply()
return result;
}
+bool RefactoringFile::apply(const Utils::ChangeSet &changeSet)
+{
+ setChangeSet(changeSet);
+ return apply();
+}
+
void RefactoringFile::setupFormattingRanges(const QList<ChangeSet::EditOp> &replaceList)
{
QTextDocument * const doc = m_editor ? m_editor->document() : m_document;
@@ -359,7 +368,7 @@ void RefactoringFile::doFormatting()
Utils::sort(m_formattingCursors, [](const auto &tc1, const auto &tc2) {
return tc1.first.selectionStart() < tc2.first.selectionStart();
});
- static const QString clangFormatLineRemovalBlocker("// QTC_TEMP");
+ static const QString clangFormatLineRemovalBlocker("");
for (auto &[formattingCursor, _] : m_formattingCursors) {
const QTextBlock firstBlock = document->findBlock(formattingCursor.selectionStart());
const QTextBlock lastBlock = document->findBlock(formattingCursor.selectionEnd());
diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h
index 913c731df27..3e043c4f6be 100644
--- a/src/plugins/texteditor/refactoringchanges.h
+++ b/src/plugins/texteditor/refactoringchanges.h
@@ -60,6 +60,7 @@ public:
void setChangeSet(const Utils::ChangeSet &changeSet);
void setOpenEditor(bool activate = false, int pos = -1);
bool apply();
+ bool apply(const Utils::ChangeSet &changeSet);
bool create(const QString &contents, bool reindent, bool openInEditor);
protected:
diff --git a/src/plugins/texteditor/semantichighlighter.cpp b/src/plugins/texteditor/semantichighlighter.cpp
index 9cee346d8b0..0c385d2e4b5 100644
--- a/src/plugins/texteditor/semantichighlighter.cpp
+++ b/src/plugins/texteditor/semantichighlighter.cpp
@@ -5,7 +5,6 @@
#include "syntaxhighlighter.h"
#include "texteditorsettings.h"
-#include "syntaxhighlighterrunner.h"
#include <utils/qtcassert.h>
@@ -75,7 +74,7 @@ const Ranges rangesForResult(
}
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
- SyntaxHighlighterRunner *highlighter,
+ SyntaxHighlighter *highlighter,
const QFuture<HighlightingResult> &future,
int from,
int to,
@@ -114,21 +113,17 @@ void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
formatRanges[range.block].append(range.formatRange);
}
- QList<int> clearBlockNumberVector;
- QMap<int, QList<QTextLayout::FormatRange>> blockNumberMap;
for (auto &[block, ranges] : formatRanges) {
while (currentBlock < block) {
- clearBlockNumberVector.append(currentBlock.blockNumber());
+ highlighter->clearExtraFormats(currentBlock);
currentBlock = currentBlock.next();
}
- blockNumberMap[block.blockNumber()] = ranges;
+ highlighter->setExtraFormats(block, std::move(ranges));
currentBlock = block.next();
}
- highlighter->clearExtraFormats(clearBlockNumberVector);
- highlighter->setExtraFormats(blockNumberMap);
}
-void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
+void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighter *highlighter,
const QList<HighlightingResult> &results,
const QHash<int, QTextCharFormat> &kindToFormat)
{
@@ -139,19 +134,19 @@ void SemanticHighlighter::setExtraAdditionalFormats(SyntaxHighlighterRunner *hig
QTextDocument *doc = highlighter->document();
QTC_ASSERT(doc, return );
- QMap<int, QList<QTextLayout::FormatRange>> blockNumberMap;
+ std::map<QTextBlock, QVector<QTextLayout::FormatRange>> formatRanges;
- for (const HighlightingResult &result : results) {
- const Ranges ranges = rangesForResult(result, doc, kindToFormat);
- for (const Range &range : ranges)
- blockNumberMap[range.block.blockNumber()].append(range.formatRange);
+ for (auto result : results) {
+ for (const Range &range : rangesForResult(result, doc, kindToFormat))
+ formatRanges[range.block].append(range.formatRange);
}
- highlighter->setExtraFormats(blockNumberMap);
+ for (auto &[block, ranges] : formatRanges)
+ highlighter->setExtraFormats(block, std::move(ranges));
}
void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
- SyntaxHighlighterRunner *highlighter, const QFuture<HighlightingResult> &future)
+ SyntaxHighlighter *highlighter, const QFuture<HighlightingResult> &future)
{
const QTextDocument * const doc = highlighter->document();
QTextBlock firstBlockToClear = doc->begin();
@@ -168,7 +163,6 @@ void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
QList<int> clearBlockNumberVector;
for (QTextBlock b = firstBlockToClear; b.isValid(); b = b.next())
- clearBlockNumberVector.append(b.blockNumber());
+ highlighter->clearExtraFormats(b);
- highlighter->clearExtraFormats(clearBlockNumberVector);
}
diff --git a/src/plugins/texteditor/semantichighlighter.h b/src/plugins/texteditor/semantichighlighter.h
index ad1d854b834..f8ae30a0eda 100644
--- a/src/plugins/texteditor/semantichighlighter.h
+++ b/src/plugins/texteditor/semantichighlighter.h
@@ -21,7 +21,6 @@ QT_END_NAMESPACE
namespace TextEditor {
class SyntaxHighlighter;
-class SyntaxHighlighterRunner;
class TEXTEDITOR_EXPORT HighlightingResult
{
@@ -74,7 +73,7 @@ using Splitter = std::function<const QList<std::pair<HighlightingResult, QTextBl
// the (to-1).line result.
// Requires that results of the Future are ordered by line.
void TEXTEDITOR_EXPORT
-incrementalApplyExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
+incrementalApplyExtraAdditionalFormats(SyntaxHighlighter *highlighter,
const QFuture<HighlightingResult> &future,
int from,
int to,
@@ -85,7 +84,7 @@ incrementalApplyExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
// indicated by Result::kind and kindToFormat to the correct location using
// SyntaxHighlighter::setExtraFormats. In contrast to
// incrementalApplyExtraAdditionalFormats the results do not have to be ordered by line.
-void TEXTEDITOR_EXPORT setExtraAdditionalFormats(SyntaxHighlighterRunner *highlighter,
+void TEXTEDITOR_EXPORT setExtraAdditionalFormats(SyntaxHighlighter *highlighter,
const HighlightingResults &results,
const QHash<int, QTextCharFormat> &kindToFormat);
@@ -93,7 +92,7 @@ void TEXTEDITOR_EXPORT setExtraAdditionalFormats(SyntaxHighlighterRunner *highli
// until the end of the document.
// Requires that results of the Future are ordered by line.
void TEXTEDITOR_EXPORT clearExtraAdditionalFormatsUntilEnd(
- SyntaxHighlighterRunner *highlighter, const QFuture<HighlightingResult> &future);
+ SyntaxHighlighter *highlighter, const QFuture<HighlightingResult> &future);
} // namespace SemanticHighlighter
} // namespace TextEditor
diff --git a/src/plugins/texteditor/snippets/snippetssettings.cpp b/src/plugins/texteditor/snippets/snippetssettings.cpp
deleted file mode 100644
index cce25bc7109..00000000000
--- a/src/plugins/texteditor/snippets/snippetssettings.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "snippetssettings.h"
-
-#include <utils/qtcsettings.h>
-
-using namespace Utils;
-
-namespace TextEditor {
-
-const char kGroupPostfix[] = "SnippetsSettings";
-const char kLastUsedSnippetGroup[] = "LastUsedSnippetGroup";
-
-void SnippetsSettings::toSettings(const Key &category, QtcSettings *s) const
-{
- const Key group = category + kGroupPostfix;
- s->beginGroup(group);
- s->setValue(kLastUsedSnippetGroup, m_lastUsedSnippetGroup);
- s->endGroup();
-}
-
-void SnippetsSettings::fromSettings(const Key &category, QtcSettings *s)
-{
- const Key group = category + kGroupPostfix;
- s->beginGroup(group);
- m_lastUsedSnippetGroup = s->value(kLastUsedSnippetGroup, QString()).toString();
- s->endGroup();
-}
-
-void SnippetsSettings::setLastUsedSnippetGroup(const QString &lastUsed)
-{
- m_lastUsedSnippetGroup = lastUsed;
-}
-
-const QString &SnippetsSettings::lastUsedSnippetGroup() const
-{
- return m_lastUsedSnippetGroup;
-}
-
-bool SnippetsSettings::equals(const SnippetsSettings &snippetsSettings) const
-{
- return m_lastUsedSnippetGroup == snippetsSettings.m_lastUsedSnippetGroup;
-}
-
-} // TextEditor
diff --git a/src/plugins/texteditor/snippets/snippetssettings.h b/src/plugins/texteditor/snippets/snippetssettings.h
deleted file mode 100644
index 732d51f6716..00000000000
--- a/src/plugins/texteditor/snippets/snippetssettings.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <QString>
-
-namespace Utils {
-class Key;
-class QtcSettings;
-} // Utils
-
-namespace TextEditor {
-
-class SnippetsSettings
-{
-public:
- SnippetsSettings() = default;
-
- void toSettings(const Utils::Key &category, Utils::QtcSettings *s) const;
- void fromSettings(const Utils::Key &category, Utils::QtcSettings *s);
-
- void setLastUsedSnippetGroup(const QString &lastUsed);
- const QString &lastUsedSnippetGroup() const;
-
- bool equals(const SnippetsSettings &snippetsSettings) const;
-
- friend bool operator==(const SnippetsSettings &a, const SnippetsSettings &b)
- { return a.equals(b); }
- friend bool operator!=(const SnippetsSettings &a, const SnippetsSettings &b)
- { return !a.equals(b); }
-
-private:
- QString m_lastUsedSnippetGroup;
-};
-
-} // TextEditor
diff --git a/src/plugins/texteditor/snippets/snippetssettingspage.cpp b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
index 51deff5ad1f..546d532bbf3 100644
--- a/src/plugins/texteditor/snippets/snippetssettingspage.cpp
+++ b/src/plugins/texteditor/snippets/snippetssettingspage.cpp
@@ -7,7 +7,6 @@
#include "snippetprovider.h"
#include "snippet.h"
#include "snippetscollection.h"
-#include "snippetssettings.h"
#include "../fontsettings.h"
#include "../textdocument.h"
#include "../texteditorconstants.h"
@@ -39,6 +38,8 @@ using namespace Utils;
namespace TextEditor::Internal {
+const char kLastUsedSnippetGroup[] = "TextSnippetsSettings/LastUsedSnippetGroup";
+
// SnippetsTableModel
class SnippetsTableModel : public QAbstractTableModel
@@ -244,8 +245,6 @@ void SnippetsTableModel::replaceSnippet(const Snippet &snippet, const QModelInde
}
}
-// SnippetsSettingsWidget
-
class SnippetsSettingsWidget : public Core::IOptionsPageWidget
{
public:
@@ -275,10 +274,9 @@ private:
bool settingsChanged() const;
void writeSettings();
- const Key m_settingsPrefix{"Text"};
SnippetsTableModel m_model;
bool m_snippetsCollectionChanged = false;
- SnippetsSettings m_settings;
+ QString m_lastUsedSnippetGroup;
QStackedWidget *m_snippetsEditorStack;
QComboBox *m_groupCombo;
@@ -407,9 +405,8 @@ void SnippetsSettingsWidget::loadSettings()
if (m_groupCombo->count() == 0)
return;
- m_settings.fromSettings(m_settingsPrefix, Core::ICore::settings());
- const QString &lastGroupName = m_settings.lastUsedSnippetGroup();
- const int index = m_groupCombo->findText(lastGroupName);
+ m_lastUsedSnippetGroup = Core::ICore::settings()->value(kLastUsedSnippetGroup, QString()).toString();
+ const int index = m_groupCombo->findText(m_lastUsedSnippetGroup);
if (index != -1)
m_groupCombo->setCurrentIndex(index);
else
@@ -421,15 +418,13 @@ void SnippetsSettingsWidget::writeSettings()
if (m_groupCombo->count() == 0)
return;
- m_settings.setLastUsedSnippetGroup(m_groupCombo->currentText());
- m_settings.toSettings(m_settingsPrefix, Core::ICore::settings());
+ m_lastUsedSnippetGroup = m_groupCombo->currentText();
+ Core::ICore::settings()->setValue(kLastUsedSnippetGroup, m_lastUsedSnippetGroup);
}
bool SnippetsSettingsWidget::settingsChanged() const
{
- if (m_settings.lastUsedSnippetGroup() != m_groupCombo->currentText())
- return true;
- return false;
+ return m_lastUsedSnippetGroup != m_groupCombo->currentText();
}
void SnippetsSettingsWidget::loadSnippetGroup(int index)
diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp
index f7db190852d..0162cdeeff0 100644
--- a/src/plugins/texteditor/syntaxhighlighter.cpp
+++ b/src/plugins/texteditor/syntaxhighlighter.cpp
@@ -25,8 +25,6 @@ enum HighlighterTypeProperty
class SyntaxHighlighterPrivate
{
- SyntaxHighlighter *q_ptr = nullptr;
- Q_DECLARE_PUBLIC(SyntaxHighlighter)
public:
SyntaxHighlighterPrivate() = default;
@@ -37,8 +35,10 @@ public:
QPointer<QTextDocument> doc;
+ void updateFormats(int from, int charsRemoved, int charsAdded);
void reformatBlocks(int from, int charsRemoved, int charsAdded);
- void reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded);
+ void reformatBlocks();
+ void reformatBlock(const QTextBlock &block);
inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
inReformatBlocks = true;
@@ -48,7 +48,7 @@ public:
inReformatBlocks = false;
}
- void applyFormatChanges(int from, int charsRemoved, int charsAdded);
+ void applyFormatChanges();
void updateFormats(const FontSettings &fontSettings);
FontSettings fontSettings;
@@ -61,6 +61,11 @@ public:
QList<std::pair<int,TextStyle>> formatCategories;
QTextCharFormat whitespaceFormat;
QString mimeType;
+ bool syntaxInfoUpToDate = false;
+ int highlightStartBlock = 0;
+ int highlightEndBlock = 0;
+ QSet<int> forceRehighlightBlocks;
+ SyntaxHighlighter *q;
};
static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsDelta)
@@ -77,31 +82,30 @@ static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsDelt
void SyntaxHighlighter::delayedRehighlight()
{
- Q_D(SyntaxHighlighter);
if (!d->rehighlightPending)
return;
d->rehighlightPending = false;
- if (document()->isEmpty())
- return;
-
rehighlight();
}
+void SyntaxHighlighter::continueRehighlight()
+{
+ d->reformatBlocks();
+}
+
#ifdef WITH_TESTS
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent, const FontSettings &fontsettings)
- : QObject(parent), d_ptr(new SyntaxHighlighterPrivate(fontsettings))
+ : QObject(parent), d(new SyntaxHighlighterPrivate(fontsettings))
{
- d_ptr->q_ptr = this;
+ d->q = this;
if (parent)
setDocument(parent);
}
#endif
-void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, int charsAdded)
+void SyntaxHighlighterPrivate::applyFormatChanges()
{
- bool formatsChanged = false;
-
QTextLayout *layout = currentBlock.layout();
QList<QTextLayout::FormatRange> ranges;
@@ -111,12 +115,6 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
return range.format.property(SyntaxHighlight).toBool();
});
- if (currentBlock.contains(from)) {
- const int charsDelta = charsAdded - charsRemoved;
- for (QTextLayout::FormatRange &range : ranges)
- formatsChanged |= adjustRange(range, from - currentBlock.position(), charsDelta);
- }
-
QTextCharFormat emptyFormat;
QTextLayout::FormatRange r;
@@ -157,7 +155,7 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
newRanges << r;
}
- formatsChanged = formatsChanged || (newRanges.size() != oldRanges.size());
+ bool formatsChanged = (newRanges.size() != oldRanges.size());
for (int i = 0; !formatsChanged && i < newRanges.size(); ++i) {
const QTextLayout::FormatRange &o = oldRanges.at(i);
@@ -174,85 +172,103 @@ void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, in
void SyntaxHighlighter::reformatBlocks(int from, int charsRemoved, int charsAdded)
{
- Q_D(SyntaxHighlighter);
if (!d->inReformatBlocks)
d->reformatBlocks(from, charsRemoved, charsAdded);
}
-void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
+void SyntaxHighlighterPrivate::updateFormats(int from, int charsRemoved, int charsAdded)
{
- Q_Q(SyntaxHighlighter);
- foldValidator.reset();
+ bool formatsChanged = false;
- rehighlightPending = false;
+ const QTextBlock block = doc->findBlock(from);
+ QTextLayout *layout = block.layout();
- QTextBlock block = doc->findBlock(from);
- if (!block.isValid())
- return;
+ QList<QTextLayout::FormatRange> ranges = layout->formats();
- int endPosition;
- QTextBlock lastBlock = doc->findBlock(from + charsAdded + (charsRemoved > 0 ? 1 : 0));
- if (lastBlock.isValid())
- endPosition = lastBlock.position() + lastBlock.length();
- else
- endPosition = doc->lastBlock().position() + doc->lastBlock().length();
+ const int charsDelta = charsAdded - charsRemoved;
+ for (QTextLayout::FormatRange &range : ranges)
+ formatsChanged |= adjustRange(range, from - block.position(), charsDelta);
- bool forceHighlightOfNextBlock = false;
+ if (formatsChanged) {
+ layout->setFormats(ranges);
+ doc->markContentsDirty(block.position(), block.length());
+ }
+}
- QList<SyntaxHighlighter::Result> vecRes;
+void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
+{
+ updateFormats(from, charsRemoved, charsAdded);
- SyntaxHighlighter::Result resStart;
- resStart.m_state = SyntaxHighlighter::State::Start;
- vecRes << resStart;
+ QTextBlock block = doc->findBlock(from);
+ if (block.isValid() && block.blockNumber() < highlightStartBlock)
+ highlightStartBlock = block.blockNumber();
+ block = doc->findBlock(from + charsAdded + (charsRemoved > 0 ? 1 : 0));
+ if (!block.isValid())
+ highlightEndBlock = doc->blockCount() - 1;
+ else if (block.blockNumber() > highlightEndBlock)
+ highlightEndBlock = block.blockNumber();
- while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
- if (QThread::currentThread()->isInterruptionRequested() || q->isInterrupted()) {
- inReformatBlocks = false;
- emit q->resultsReady({});
- return;
- }
+ reformatBlocks();
+}
- const int stateBeforeHighlight = block.userState();
+void SyntaxHighlighterPrivate::reformatBlocks()
+{
+ QElapsedTimer et;
+ et.start();
- reformatBlock(block, from, charsRemoved, charsAdded);
+ syntaxInfoUpToDate = false;
+ rehighlightPending = false;
- forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
+ foldValidator.reset();
- SyntaxHighlighter::Result res;
- res.m_formatRanges = block.layout()->formats();
- res.fillByBlock(block);
- vecRes << res;
+ bool forceHighlightOfNextBlock = false;
+ QTextBlock block = doc->findBlockByNumber(highlightStartBlock);
+ QTC_ASSERT(block.isValid(), block = doc->firstBlock());
+ QTextBlock endBlock = doc->findBlockByNumber(highlightEndBlock);
+ QTC_ASSERT(endBlock.isValid(), endBlock = doc->lastBlock());
- // Sending data to the text editor in chunks of 200 blocks is a sensible approach.
- // This helps avoid UI slowdowns when applying formatting to the text.
- if (vecRes.size() >= 200) {
- emit q->resultsReady(vecRes);
- vecRes.clear();
+ while (block.isValid()) {
+ if (et.elapsed() > 20)
+ break;
+
+ const int stateBeforeHighlight = block.userState();
+
+ if (forceHighlightOfNextBlock || forceRehighlightBlocks.contains(block.blockNumber())
+ || block.blockNumber() <= highlightEndBlock) {
+ reformatBlock(block);
+ forceRehighlightBlocks.remove(block.blockNumber());
+ forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
}
+ highlightStartBlock = block.blockNumber();
+ if (block == endBlock && !forceHighlightOfNextBlock)
+ break;
block = block.next();
}
formatChanges.clear();
-
foldValidator.finalize();
- SyntaxHighlighter::Result res;
- res.m_state = SyntaxHighlighter::State::Done;
- vecRes << res;
- emit q->resultsReady(vecRes);
+
+ if (endBlock.isValid() && block.isValid() && block.blockNumber() < endBlock.blockNumber()) {
+ QMetaObject::invokeMethod(q, &SyntaxHighlighter::continueRehighlight, Qt::QueuedConnection);
+ if (forceHighlightOfNextBlock)
+ forceRehighlightBlocks << block.blockNumber();
+ } else {
+ highlightEndBlock = 0;
+ syntaxInfoUpToDate = true;
+ emit q->finished();
+ }
}
-void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded)
+void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
{
- Q_Q(SyntaxHighlighter);
-
- Q_ASSERT_X(!currentBlock.isValid(), "SyntaxHighlighter::reformatBlock()", "reFormatBlock() called recursively");
+ QTC_ASSERT(!currentBlock.isValid(), return);
currentBlock = block;
formatChanges.fill(QTextCharFormat(), block.length() - 1);
q->highlightBlock(block.text());
- applyFormatChanges(from, charsRemoved, charsAdded);
+ applyFormatChanges();
foldValidator.process(currentBlock);
@@ -293,9 +309,9 @@ void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from,
Constructs a SyntaxHighlighter with the given \a parent.
*/
SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
- : QObject(parent), d_ptr(new SyntaxHighlighterPrivate)
+ : QObject(parent), d(new SyntaxHighlighterPrivate)
{
- d_ptr->q_ptr = this;
+ d->q = this;
}
/*!
@@ -304,9 +320,9 @@ SyntaxHighlighter::SyntaxHighlighter(QObject *parent)
SyntaxHighlighter.
*/
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
- : QObject(parent), d_ptr(new SyntaxHighlighterPrivate)
+ : QObject(parent), d(new SyntaxHighlighterPrivate)
{
- d_ptr->q_ptr = this;
+ d->q = this;
if (parent)
setDocument(parent);
}
@@ -317,9 +333,9 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
the SyntaxHighlighter.
*/
SyntaxHighlighter::SyntaxHighlighter(QTextEdit *parent)
- : QObject(parent), d_ptr(new SyntaxHighlighterPrivate)
+ : QObject(parent), d(new SyntaxHighlighterPrivate)
{
- d_ptr->q_ptr = this;
+ d->q = this;
if (parent)
setDocument(parent->document());
}
@@ -338,7 +354,6 @@ SyntaxHighlighter::~SyntaxHighlighter()
*/
void SyntaxHighlighter::setDocument(QTextDocument *doc)
{
- Q_D(SyntaxHighlighter);
if (d->doc == doc)
return;
@@ -356,10 +371,7 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc)
documentChanged(oldDoc, d->doc);
if (d->doc) {
connect(d->doc, &QTextDocument::contentsChange, this, &SyntaxHighlighter::reformatBlocks);
- d->rehighlightPending = true;
- QMetaObject::invokeMethod(this,
- &SyntaxHighlighter::delayedRehighlight,
- Qt::QueuedConnection);
+ scheduleRehighlight();
d->foldValidator.setup(qobject_cast<TextDocumentLayout *>(doc->documentLayout()));
}
}
@@ -370,19 +382,16 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc)
*/
QTextDocument *SyntaxHighlighter::document() const
{
- Q_D(const SyntaxHighlighter);
return d->doc;
}
void SyntaxHighlighter::setMimeType(const QString &mimeType)
{
- Q_D(SyntaxHighlighter);
d->mimeType = mimeType;
}
QString SyntaxHighlighter::mimeType() const
{
- Q_D(const SyntaxHighlighter);
return d->mimeType;
}
@@ -395,7 +404,6 @@ QString SyntaxHighlighter::mimeType() const
*/
void SyntaxHighlighter::rehighlight()
{
- Q_D(SyntaxHighlighter);
if (!d->doc)
return;
@@ -403,6 +411,17 @@ void SyntaxHighlighter::rehighlight()
d->rehighlight(cursor, QTextCursor::End);
}
+void SyntaxHighlighter::scheduleRehighlight()
+{
+ if (d->rehighlightPending)
+ return;
+ d->rehighlightPending = true;
+ d->syntaxInfoUpToDate = false;
+ QMetaObject::invokeMethod(this,
+ &SyntaxHighlighter::delayedRehighlight,
+ Qt::QueuedConnection);
+}
+
/*!
\since 4.6
@@ -412,7 +431,6 @@ void SyntaxHighlighter::rehighlight()
*/
void SyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
{
- Q_D(SyntaxHighlighter);
if (!d->doc || !block.isValid() || block.document() != d->doc)
return;
@@ -486,7 +504,6 @@ void SyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
*/
void SyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
{
- Q_D(SyntaxHighlighter);
if (start < 0 || start >= d->formatChanges.count())
return;
@@ -533,7 +550,6 @@ void SyntaxHighlighter::setFormat(int start, int count, const QFont &font)
void SyntaxHighlighter::formatSpaces(const QString &text, int start, int count)
{
- Q_D(const SyntaxHighlighter);
int offset = start;
const int end = std::min(start + count, int(text.length()));
while (offset < end) {
@@ -585,10 +601,7 @@ void SyntaxHighlighter::setFormatWithSpaces(const QString &text, int start, int
*/
QTextCharFormat SyntaxHighlighter::format(int pos) const
{
- Q_D(const SyntaxHighlighter);
- if (pos < 0 || pos >= d->formatChanges.count())
- return QTextCharFormat();
- return d->formatChanges.at(pos);
+ return d->formatChanges.value(pos);
}
/*!
@@ -600,7 +613,6 @@ QTextCharFormat SyntaxHighlighter::format(int pos) const
*/
int SyntaxHighlighter::previousBlockState() const
{
- Q_D(const SyntaxHighlighter);
if (!d->currentBlock.isValid())
return -1;
@@ -617,7 +629,6 @@ int SyntaxHighlighter::previousBlockState() const
*/
int SyntaxHighlighter::currentBlockState() const
{
- Q_D(const SyntaxHighlighter);
if (!d->currentBlock.isValid())
return -1;
@@ -631,7 +642,6 @@ int SyntaxHighlighter::currentBlockState() const
*/
void SyntaxHighlighter::setCurrentBlockState(int newState)
{
- Q_D(SyntaxHighlighter);
if (!d->currentBlock.isValid())
return;
@@ -674,7 +684,6 @@ void SyntaxHighlighter::setCurrentBlockState(int newState)
*/
void SyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data)
{
- Q_D(SyntaxHighlighter);
if (!d->currentBlock.isValid())
return;
@@ -689,7 +698,6 @@ void SyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data)
*/
QTextBlockUserData *SyntaxHighlighter::currentBlockUserData() const
{
- Q_D(const SyntaxHighlighter);
if (!d->currentBlock.isValid())
return nullptr;
@@ -703,7 +711,6 @@ QTextBlockUserData *SyntaxHighlighter::currentBlockUserData() const
*/
QTextBlock SyntaxHighlighter::currentBlock() const
{
- Q_D(const SyntaxHighlighter);
return d->currentBlock;
}
@@ -715,8 +722,6 @@ static bool byStartOfRange(const QTextLayout::FormatRange &range, const QTextLay
void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
const QList<QTextLayout::FormatRange> &formats)
{
- Q_D(SyntaxHighlighter);
-
QList<QTextLayout::FormatRange> formatsCopy = formats;
const int blockLength = block.length();
@@ -766,20 +771,17 @@ void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
d->inReformatBlocks = true;
block.layout()->setFormats(formatsToApply);
- SyntaxHighlighter::Result res;
- res.m_formatRanges = block.layout()->formats();
- res.fillByBlock(block);
- res.m_state = SyntaxHighlighter::State::Extras;
- emit resultsReady({std::move(res)});
-
document()->markContentsDirty(block.position(), blockLength - 1);
d->inReformatBlocks = wasInReformatBlocks;
}
-void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
+bool SyntaxHighlighter::syntaxHighlighterUpToDate() const
{
- Q_D(SyntaxHighlighter);
+ return d->syntaxInfoUpToDate;
+}
+void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
+{
const int blockLength = block.length();
if (block.layout() == nullptr || blockLength == 0)
return;
@@ -793,12 +795,6 @@ void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
d->inReformatBlocks = true;
block.layout()->setFormats(formatsToApply);
- SyntaxHighlighter::Result res;
- res.m_formatRanges = block.layout()->formats();
- res.fillByBlock(block);
- res.m_state = SyntaxHighlighter::State::Extras;
- emit resultsReady({std::move(res)});
-
document()->markContentsDirty(block.position(), blockLength - 1);
d->inReformatBlocks = wasInReformatBlocks;
}
@@ -848,13 +844,11 @@ QList<QColor> SyntaxHighlighter::generateColors(int n, const QColor &background)
void SyntaxHighlighter::setFontSettings(const FontSettings &fontSettings)
{
- Q_D(SyntaxHighlighter);
d->updateFormats(fontSettings);
}
FontSettings SyntaxHighlighter::fontSettings() const
{
- Q_D(const SyntaxHighlighter);
return d->fontSettings;
}
@@ -897,7 +891,6 @@ void SyntaxHighlighter::setTextFormatCategories(int count,
*/
void SyntaxHighlighter::setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories)
{
- Q_D(SyntaxHighlighter);
d->formatCategories = categories;
const int maxCategory = Utils::maxElementOr(categories, {-1, C_TEXT}).first;
d->formats = QList<QTextCharFormat>(maxCategory + 1);
@@ -906,7 +899,6 @@ void SyntaxHighlighter::setTextFormatCategories(const QList<std::pair<int, TextS
QTextCharFormat SyntaxHighlighter::formatForCategory(int category) const
{
- Q_D(const SyntaxHighlighter);
QTC_ASSERT(d->formats.size() > category, return QTextCharFormat());
return d->formats.at(category);
@@ -914,7 +906,6 @@ QTextCharFormat SyntaxHighlighter::formatForCategory(int category) const
QTextCharFormat SyntaxHighlighter::whitespacified(const QTextCharFormat &fmt)
{
- Q_D(SyntaxHighlighter);
QTextCharFormat format = d->whitespaceFormat;
format.setBackground(fmt.background());
return format;
diff --git a/src/plugins/texteditor/syntaxhighlighter.h b/src/plugins/texteditor/syntaxhighlighter.h
index 13d595d82f4..39bb084465c 100644
--- a/src/plugins/texteditor/syntaxhighlighter.h
+++ b/src/plugins/texteditor/syntaxhighlighter.h
@@ -32,7 +32,6 @@ class SyntaxHighlighterPrivate;
class TEXTEDITOR_EXPORT SyntaxHighlighter : public QObject
{
Q_OBJECT
- Q_DECLARE_PRIVATE(SyntaxHighlighter)
public:
SyntaxHighlighter(QObject *parent = nullptr);
SyntaxHighlighter(QTextDocument *parent);
@@ -51,79 +50,16 @@ public:
virtual void setFontSettings(const TextEditor::FontSettings &fontSettings);
TextEditor::FontSettings fontSettings() const;
- enum State {
- Start,
- InProgress,
- Done,
- Extras
- };
-
- struct Result
- {
- void fillByBlock(const QTextBlock &block)
- {
- m_blockNumber = block.blockNumber();
- m_userState = block.userState();
-
- TextBlockUserData *userDate = TextDocumentLayout::textUserData(block);
- if (!userDate)
- return;
-
- m_hasBlockUserData = true;
- m_foldingIndent = userDate->foldingIndent();
- m_ifdefedOut = userDate->ifdefedOut();
- m_foldingStartIncluded = userDate->foldingStartIncluded();
- m_foldingEndIncluded = userDate->foldingEndIncluded();
- m_parentheses = userDate->parentheses();
- m_expectedRawStringSuffix = userDate->expectedRawStringSuffix();
- }
-
- void copyToBlock(QTextBlock &block) const
- {
- block.setUserState(m_userState);
-
- if (!m_hasBlockUserData)
- return;
-
- TextBlockUserData *data = TextDocumentLayout::userData(block);
- data->setExpectedRawStringSuffix(m_expectedRawStringSuffix);
- data->setFoldingIndent(m_foldingIndent);
- data->setFoldingStartIncluded(m_foldingStartIncluded);
- data->setFoldingEndIncluded(m_foldingEndIncluded);
-
- if (m_ifdefedOut)
- data->setIfdefedOut();
- else
- data->clearIfdefedOut();
-
- data->setParentheses(m_parentheses);
- }
-
- int m_blockNumber;
- bool m_hasBlockUserData = false;
-
- int m_foldingIndent : 16;
- uint m_ifdefedOut : 1;
- uint m_foldingStartIncluded : 1;
- uint m_foldingEndIncluded : 1;
-
- Parentheses m_parentheses;
- QByteArray m_expectedRawStringSuffix;
- int m_userState = -1;
- QList<QTextLayout::FormatRange> m_formatRanges;
-
- State m_state = InProgress;
- };
-
- void setInterrupted(bool interrupted) { m_interrupted = interrupted; }
- bool isInterrupted() { return m_interrupted; }
void setExtraFormats(const QTextBlock &block, const QList<QTextLayout::FormatRange> &formats);
virtual void setLanguageFeaturesFlags(unsigned int /*flags*/) {}; // needed for CppHighlighting
virtual void setEnabled(bool /*enabled*/) {}; // needed for DiffAndLogHighlighter
virtual void setDefinitionName(const QString & /*definitionName*/) {} // needed for Highlighter
+ bool syntaxHighlighterUpToDate() const;
+
public slots:
virtual void rehighlight();
+ virtual void scheduleRehighlight();
void rehighlightBlock(const QTextBlock &block);
void clearExtraFormats(const QTextBlock &block);
void reformatBlocks(int from, int charsRemoved, int charsAdded);
@@ -158,18 +94,18 @@ protected:
QTextBlock currentBlock() const;
-protected:
virtual void documentChanged(QTextDocument * /*oldDoc*/, QTextDocument * /*newDoc*/) {};
signals:
- void resultsReady(const QList<Result> &result);
+ void finished();
private:
void setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories);
void delayedRehighlight();
+ void continueRehighlight();
- QScopedPointer<SyntaxHighlighterPrivate> d_ptr;
- std::atomic<bool> m_interrupted = false;
+ friend class SyntaxHighlighterPrivate;
+ std::unique_ptr<SyntaxHighlighterPrivate> d;
#ifdef WITH_TESTS
friend class tst_highlighter;
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.cpp b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
deleted file mode 100644
index 874f8254abf..00000000000
--- a/src/plugins/texteditor/syntaxhighlighterrunner.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "syntaxhighlighterrunner.h"
-
-#include "fontsettings.h"
-#include "textdocumentlayout.h"
-#include "texteditorsettings.h"
-#include "highlighter.h"
-
-#include <utils/algorithm.h>
-#include <utils/textutils.h>
-
-#include <QMetaObject>
-#include <QTextCursor>
-#include <QTextDocument>
-#include <QThread>
-
-namespace TextEditor {
-
-struct BlockPreeditData {
- int position;
- QString text;
-};
-
-class SyntaxHighlighterRunnerPrivate : public QObject
-{
- Q_OBJECT
-public:
- SyntaxHighlighterRunnerPrivate(SyntaxHighlighter *highlighter,
- QTextDocument *document,
- bool async)
- : m_highlighter(highlighter)
- {
- if (async) {
- m_document = new QTextDocument(this);
- m_document->setDocumentLayout(new TextDocumentLayout(m_document));
- } else {
- m_document = document;
- }
-
- m_highlighter->setParent(m_document);
- m_highlighter->setDocument(m_document);
-
- connect(m_highlighter,
- &SyntaxHighlighter::resultsReady,
- this,
- &SyntaxHighlighterRunnerPrivate::resultsReady);
- }
-
- void changeDocument(int from,
- int charsRemoved,
- const QString textAdded,
- const QMap<int, BlockPreeditData> &blocksPreedit)
- {
- QTextCursor cursor(m_document);
- cursor.setPosition(qMin(m_document->characterCount() - 1, from + charsRemoved));
- cursor.setPosition(from, QTextCursor::KeepAnchor);
- cursor.insertText(textAdded);
-
- for (auto it = blocksPreedit.cbegin(); it != blocksPreedit.cend(); ++it) {
- const QTextBlock block = m_document->findBlockByNumber(it.key());
- block.layout()->setPreeditArea(it.value().position, it.value().text);
- }
- }
-
- void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
- {
- QTC_ASSERT(m_highlighter, return);
- for (auto it = formatMap.cbegin(); it != formatMap.cend(); ++it)
- m_highlighter->setExtraFormats(m_document->findBlockByNumber(it.key()), it.value());
- }
-
- void clearExtraFormats(const QList<int> &blockNumbers)
- {
- QTC_ASSERT(m_highlighter, return);
- for (auto it = blockNumbers.cbegin(); it != blockNumbers.cend(); ++it)
- m_highlighter->clearExtraFormats(m_document->findBlockByNumber(*it));
- }
-
- void clearAllExtraFormats()
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->clearAllExtraFormats();
- }
-
- void setFontSettings(const TextEditor::FontSettings &fontSettings)
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->setFontSettings(fontSettings);
- }
-
- void setDefinitionName(const QString &name)
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->setDefinitionName(name);
- }
-
- void setLanguageFeaturesFlags(unsigned int flags)
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->setLanguageFeaturesFlags(flags);
- }
-
- void setEnabled(bool enabled)
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->setEnabled(enabled);
- }
-
- void rehighlight()
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->rehighlight();
- }
-
- void reformatBlocks(int from, int charsRemoved, int charsAdded)
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->reformatBlocks(from, charsRemoved, charsAdded);
- }
-
- void setInterrupted(bool interrupted)
- {
- QTC_ASSERT(m_highlighter, return);
- m_highlighter->setInterrupted(interrupted);
- }
-
- QPointer<SyntaxHighlighter> m_highlighter = nullptr;
- QTextDocument *m_document = nullptr;
-
-signals:
- void resultsReady(const QList<SyntaxHighlighter::Result> &result);
-
-};
-
-void SyntaxHighlighterRunner::HighlightingStatus::notInterrupted(int from,
- int charsRemoved,
- int charsAdded)
-{
- m_from = from;
- m_addedChars = charsAdded;
- m_removedChars = charsRemoved;
- m_current = from;
- m_newFrom = from + m_addedChars;
- m_interruptionRequested = false;
-}
-
-void SyntaxHighlighterRunner::HighlightingStatus::interrupted(int from,
- int charsRemoved,
- int charsAdded)
-{
- m_newFrom = std::min(m_newFrom, from);
- m_newFrom = std::min(m_current, m_newFrom);
- m_removedChars += charsRemoved;
- m_addedChars += charsAdded;
- m_interruptionRequested = true;
-}
-
-void SyntaxHighlighterRunner::HighlightingStatus::applyNewFrom()
-{
- m_from = m_newFrom;
- m_current = m_newFrom;
- m_interruptionRequested = false;
-}
-
-SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
- QTextDocument *document,
- bool async)
- : d(new SyntaxHighlighterRunnerPrivate(highlighter, document, async))
- , m_document(document)
-{
- m_useGenericHighlighter = qobject_cast<Highlighter *>(d->m_highlighter);
-
- if (async) {
- m_thread.emplace();
- d->moveToThread(&*m_thread);
- connect(&*m_thread, &QThread::finished, d, &QObject::deleteLater);
- m_thread->start();
-
- connect(d,
- &SyntaxHighlighterRunnerPrivate::resultsReady,
- this,
- &SyntaxHighlighterRunner::applyFormatRanges);
-
- changeDocument(0, 0, m_document->characterCount());
- connect(m_document,
- &QTextDocument::contentsChange,
- this,
- &SyntaxHighlighterRunner::changeDocument);
-
- m_foldValidator.setup(qobject_cast<TextDocumentLayout *>(document->documentLayout()));
- } else {
- connect(d,
- &SyntaxHighlighterRunnerPrivate::resultsReady,
- this,
- [this](const QList<SyntaxHighlighter::Result> &result) {
- if (result.size() == 1
- && result.at(0).m_state == SyntaxHighlighter::State::Extras)
- return;
-
- auto done = std::find_if(result.cbegin(),
- result.cend(),
- [](const SyntaxHighlighter::Result &res) {
- return res.m_state
- == SyntaxHighlighter::State::Done;
- });
- if (done != result.cend()) {
- m_syntaxInfoUpdated = SyntaxHighlighter::State::Done;
- emit highlightingFinished();
- return;
- }
- m_syntaxInfoUpdated = SyntaxHighlighter::State::InProgress;
- });
- }
-}
-
-SyntaxHighlighterRunner::~SyntaxHighlighterRunner()
-{
- if (m_thread) {
- m_thread->requestInterruption();
- m_thread->quit();
- m_thread->wait();
- } else {
- delete d;
- }
-}
-
-void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::Result> &results)
-{
- if (m_document == nullptr)
- return;
-
- if (m_highlightingStatus.m_interruptionRequested) {
- d->setInterrupted(false);
- m_highlightingStatus.applyNewFrom();
- reformatBlocks(m_highlightingStatus.m_newFrom,
- m_highlightingStatus.m_removedChars,
- m_highlightingStatus.m_addedChars);
- return;
- }
-
- auto processResult = [this](SyntaxHighlighter::Result result, QTextBlock docBlock) {
- if (!docBlock.isValid())
- return;
-
- result.copyToBlock(docBlock);
- m_highlightingStatus.m_current = docBlock.position() + docBlock.length() - 1;
-
- if (result.m_formatRanges != docBlock.layout()->formats()) {
- docBlock.layout()->setFormats(result.m_formatRanges);
- m_document->markContentsDirty(docBlock.position(), docBlock.length());
- }
- };
-
- if (results.size() == 1 && results.at(0).m_state == SyntaxHighlighter::State::Extras) {
- QTextBlock docBlock = m_document->findBlockByNumber(results.at(0).m_blockNumber);
- processResult(results.at(0), docBlock);
- return;
- }
-
- for (const SyntaxHighlighter::Result &result : results) {
- m_syntaxInfoUpdated = result.m_state;
- if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Start) {
- m_foldValidator.reset();
- continue;
- }
- if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Done) {
- m_foldValidator.finalize();
- emit highlightingFinished();
- return;
- }
-
- QTextBlock docBlock = m_document->findBlockByNumber(result.m_blockNumber);
- processResult(result, docBlock);
- m_foldValidator.process(docBlock);
- }
-}
-
-void SyntaxHighlighterRunner::changeDocument(int from, int charsRemoved, int charsAdded)
-{
- QTC_ASSERT(m_document, return);
- SyntaxHighlighter::State prevSyntaxInfoUpdated = m_syntaxInfoUpdated;
- m_syntaxInfoUpdated = SyntaxHighlighter::State::InProgress;
-
- QMap<int, BlockPreeditData> blocksPreedit;
- QTextBlock block = m_document->findBlock(from);
- const QTextBlock endBlock = m_document->findBlock(from + charsAdded);
- while (block.isValid() && block != endBlock) {
- if (QTextLayout *layout = block.layout()) {
- if (const int pos = layout->preeditAreaPosition(); pos != -1)
- blocksPreedit[block.blockNumber()] = {pos, layout->preeditAreaText()};
- }
- block = block.next();
- }
- const QString text = Utils::Text::textAt(QTextCursor(m_document), from, charsAdded);
- QMetaObject::invokeMethod(d, [this, from, charsRemoved, text, blocksPreedit] {
- d->changeDocument(from, charsRemoved, text, blocksPreedit);
- });
-
- if (prevSyntaxInfoUpdated == SyntaxHighlighter::State::InProgress) {
- m_highlightingStatus.interrupted(from, charsRemoved, charsAdded);
- d->setInterrupted(true);
- } else {
- m_highlightingStatus.notInterrupted(from, charsRemoved, charsAdded);
- d->setInterrupted(false);
- }
-}
-
-bool SyntaxHighlighterRunner::useGenericHighlighter() const
-{
- return m_useGenericHighlighter;
-}
-
-void SyntaxHighlighterRunner::setExtraFormats(
- const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
-{
- QMetaObject::invokeMethod(d, [this, formatMap] { d->setExtraFormats(formatMap); });
-}
-
-void SyntaxHighlighterRunner::clearExtraFormats(const QList<int> &blockNumbers)
-{
- QMetaObject::invokeMethod(d, [this, blockNumbers] { d->clearExtraFormats(blockNumbers); });
-}
-
-void SyntaxHighlighterRunner::clearAllExtraFormats()
-{
- QMetaObject::invokeMethod(d, [this] { d->clearAllExtraFormats(); });
-}
-
-void SyntaxHighlighterRunner::setFontSettings(const TextEditor::FontSettings &fontSettings)
-{
- QMetaObject::invokeMethod(d, [this, fontSettings] { d->setFontSettings(fontSettings); });
- rehighlight();
-}
-
-void SyntaxHighlighterRunner::setLanguageFeaturesFlags(unsigned int flags)
-{
- QMetaObject::invokeMethod(d, [this, flags] { d->setLanguageFeaturesFlags(flags); });
-}
-
-void SyntaxHighlighterRunner::setEnabled(bool enabled)
-{
- QMetaObject::invokeMethod(d, [this, enabled] { d->setEnabled(enabled); });
-}
-
-void SyntaxHighlighterRunner::rehighlight()
-{
- if (m_syntaxInfoUpdated == SyntaxHighlighter::State::InProgress) {
- m_highlightingStatus.interrupted(0, 0, m_document->characterCount());
- d->setInterrupted(true);
- } else {
- m_highlightingStatus.notInterrupted(0, 0, m_document->characterCount());
- d->setInterrupted(false);
- QMetaObject::invokeMethod(d, [this] { d->rehighlight(); });
- }
-}
-
-
-void SyntaxHighlighterRunner::reformatBlocks(int from, int charsRemoved, int charsAdded)
-{
- QMetaObject::invokeMethod(
- d,
- [this, from, charsRemoved, charsAdded] {
- d->reformatBlocks(from, charsRemoved, charsAdded);
- });
-}
-
-QString SyntaxHighlighterRunner::definitionName()
-{
- return m_definitionName;
-}
-
-void SyntaxHighlighterRunner::setDefinitionName(const QString &name)
-{
- if (name.isEmpty())
- return;
-
- m_definitionName = name;
- QMetaObject::invokeMethod(d, [this, name] { d->setDefinitionName(name); });
-}
-
-} // namespace TextEditor
-
-#include "syntaxhighlighterrunner.moc"
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.h b/src/plugins/texteditor/syntaxhighlighterrunner.h
deleted file mode 100644
index 16b7c1535c8..00000000000
--- a/src/plugins/texteditor/syntaxhighlighterrunner.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <texteditor/fontsettings.h>
-#include <texteditor/syntaxhighlighter.h>
-#include <texteditor/texteditorsettings.h>
-
-#include <QObject>
-#include <QPointer>
-
-QT_BEGIN_NAMESPACE
-class QTextDocument;
-QT_END_NAMESPACE
-
-namespace TextEditor {
-
-class SyntaxHighlighterRunnerPrivate;
-
-class TEXTEDITOR_EXPORT SyntaxHighlighterRunner : public QObject
-{
- Q_OBJECT
-public:
- using SyntaxHighlighterCreator = std::function<SyntaxHighlighter *()>;
-
- SyntaxHighlighterRunner(SyntaxHighlighter *highlighter, QTextDocument *document, bool async);
- virtual ~SyntaxHighlighterRunner();
-
- void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formats);
- void clearExtraFormats(const QList<int> &blockNumbers);
- void clearAllExtraFormats();
- void setFontSettings(const TextEditor::FontSettings &fontSettings);
- void setLanguageFeaturesFlags(unsigned int flags);
- void setEnabled(bool enabled);
- void rehighlight();
- void reformatBlocks(int from, int charsRemoved, int charsAdded);
-
- QString definitionName();
- void setDefinitionName(const QString &name);
-
- QTextDocument *document() const { return m_document; }
- bool useGenericHighlighter() const;
-
- bool syntaxInfoUpdated() const { return m_syntaxInfoUpdated == SyntaxHighlighter::State::Done; }
-
-signals:
- void highlightingFinished();
-
-private:
- void applyFormatRanges(const QList<SyntaxHighlighter::Result> &results);
- void changeDocument(int from, int charsRemoved, int charsAdded);
-
- SyntaxHighlighterRunnerPrivate *d;
- QPointer<QTextDocument> m_document = nullptr;
- SyntaxHighlighter::State m_syntaxInfoUpdated = SyntaxHighlighter::State::Done;
-
- struct HighlightingStatus
- {
- int m_from = 0;
- int m_addedChars = 0;
- int m_current = 0;
- int m_removedChars = 0;
- int m_newFrom = 0;
- bool m_interruptionRequested = false;
-
- void notInterrupted(int from, int charsRemoved, int charsAdded);
- void interrupted(int from, int charsRemoved, int charsAdded);
- void applyNewFrom();
- } m_highlightingStatus;
-
- bool m_useGenericHighlighter = false;
- QString m_definitionName;
- std::optional<QThread> m_thread;
- TextDocumentLayout::FoldValidator m_foldValidator;
-};
-
-} // namespace TextEditor
-
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 2636ad46e23..7fcfe5c86c2 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -10,10 +10,10 @@
#include "tabsettings.h"
#include "textdocumentlayout.h"
#include "texteditor.h"
+#include "texteditorsettings.h"
#include "texteditortr.h"
#include "textindenter.h"
#include "typingsettings.h"
-#include "syntaxhighlighterrunner.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/diffservice.h>
@@ -64,8 +64,6 @@ public:
~TextDocumentPrivate()
{
- if (m_highlighterRunner)
- m_highlighterRunner->deleteLater();
}
MultiTextCursor indentOrUnindent(const MultiTextCursor &cursor, bool doIndent, const TabSettings &tabSettings);
@@ -101,7 +99,7 @@ public:
TextMarks m_marksCache; // Marks not owned
Utils::Guard m_modificationChangedGuard;
- SyntaxHighlighterRunner *m_highlighterRunner = nullptr;
+ SyntaxHighlighter *m_highlighter = nullptr;
};
MultiTextCursor TextDocumentPrivate::indentOrUnindent(const MultiTextCursor &cursors,
@@ -462,8 +460,8 @@ void TextDocument::applyFontSettings()
block = block.next();
}
updateLayout();
- if (d->m_highlighterRunner)
- d->m_highlighterRunner->setFontSettings(d->m_fontSettings);
+ if (d->m_highlighter)
+ d->m_highlighter->setFontSettings(d->m_fontSettings);
}
const FontSettings &TextDocument::fontSettings() const
@@ -524,15 +522,21 @@ bool TextDocument::applyChangeSet(const ChangeSet &changeSet)
{
if (changeSet.isEmpty())
return true;
- PlainRefactoringFileFactory changes;
- const RefactoringFilePtr file = changes.file(filePath());
- file->setChangeSet(changeSet);
- return file->apply();
+ return PlainRefactoringFileFactory().file(filePath())->apply(changeSet);
}
// the blocks list must be sorted
void TextDocument::setIfdefedOutBlocks(const QList<BlockRange> &blocks)
{
+ if (syntaxHighlighter() && !syntaxHighlighter()->syntaxHighlighterUpToDate()) {
+ connect(syntaxHighlighter(),
+ &SyntaxHighlighter::finished,
+ this,
+ [this, blocks] { setIfdefedOutBlocks(blocks); },
+ Qt::SingleShotConnection);
+ return;
+ }
+
QTextDocument *doc = document();
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
@@ -635,11 +639,6 @@ QTextDocument *TextDocument::document() const
return &d->m_document;
}
-SyntaxHighlighterRunner *TextDocument::syntaxHighlighterRunner() const
-{
- return d->m_highlighterRunner;
-}
-
/*!
* Saves the document to the file specified by \a fileName. If errors occur,
* \a errorString contains their cause.
@@ -911,26 +910,19 @@ bool TextDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type
return reload(errorString);
}
-void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator,
- bool threaded)
+void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator)
{
- delete d->m_highlighterRunner;
-
- static const std::optional<bool> envValue = []() -> std::optional<bool> {
- const QString key("QTC_USE_THREADED_HIGHLIGHTER");
- if (qtcEnvironmentVariableIsSet(key)) {
- const QString value = qtcEnvironmentVariable(key).toUpper();
- return value != "FALSE" && value != "0";
- }
- return {};
- }();
-
SyntaxHighlighter *highlighter = creator();
+ highlighter->setParent(this);
+ highlighter->setDocument(this->document());
highlighter->setFontSettings(TextEditorSettings::fontSettings());
highlighter->setMimeType(mimeType());
- d->m_highlighterRunner = new SyntaxHighlighterRunner(highlighter,
- document(),
- envValue.value_or(threaded));
+ d->m_highlighter = highlighter;
+}
+
+SyntaxHighlighter *TextDocument::syntaxHighlighter() const
+{
+ return d->m_highlighter;
}
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h
index 5879d9e9ec2..b3bf77e5442 100644
--- a/src/plugins/texteditor/textdocument.h
+++ b/src/plugins/texteditor/textdocument.h
@@ -34,7 +34,6 @@ class FontSettings;
class IAssistProvider;
class StorageSettings;
class SyntaxHighlighter;
-class SyntaxHighlighterRunner;
class TabSettings;
class TextDocumentPrivate;
class TextMark;
@@ -127,8 +126,8 @@ public:
QTextDocument *document() const;
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
- void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator, bool threaded = false);
- SyntaxHighlighterRunner *syntaxHighlighterRunner() const;
+ void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator);
+ SyntaxHighlighter *syntaxHighlighter() const;
bool reload(QString *errorString, QTextCodec *codec);
void cleanWhitespace(const QTextCursor &cursor);
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index bea58df3c88..d75db87a166 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -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,13 +29,12 @@
#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 "syntaxhighlighterrunner.h"
#include <aggregation/aggregate.h>
@@ -46,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>
@@ -352,6 +354,7 @@ public:
BaseTextEditorPrivate() = default;
TextEditorFactoryPrivate *m_origin = nullptr;
+ QByteArray m_savedNavigationState;
};
class HoverHandlerRunner
@@ -739,6 +742,14 @@ public:
void openTypeUnderCursor(bool openInNextSplit);
qreal charWidth() const;
+ // actions
+ void registerActions();
+ void updateActions();
+ void updateOptionalActions();
+ void updateRedoAction();
+ void updateUndoAction();
+ void updateCopyAction(bool on);
+
public:
TextEditorWidget *q;
QWidget *m_toolBarWidget = nullptr;
@@ -754,7 +765,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;
@@ -762,7 +773,6 @@ public:
QSharedPointer<TextDocument> m_document;
QList<QMetaObject::Connection> m_documentConnections;
QByteArray m_tempState;
- QByteArray m_tempNavigationState;
bool m_parenthesesMatchingEnabled = false;
QTimer m_parenthesesMatchingTimer;
@@ -928,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
@@ -986,6 +1020,8 @@ void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags)
if (future.resultCount() <= 0)
return;
const SearchResultItems &results = future.result();
+ if (results.isEmpty())
+ return;
const auto cursorForResult = [this](const SearchResultItem &item) {
return selectRange(m_editor->document(), item.mainRange());
};
@@ -1032,6 +1068,7 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
, m_codeAssistant(parent)
, m_hoverHandlerRunner(parent, m_hoverHandlers)
, m_autoCompleter(new AutoCompleter)
+ , m_editorContext(Id::fromString(QUuid::createUuid().toString()))
{
m_selectionHighlightOverlay->show();
auto aggregate = new Aggregation::Aggregate;
@@ -1096,6 +1133,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,
@@ -1142,6 +1188,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()
@@ -1262,15 +1316,15 @@ TextEditorWidget::TextEditorWidget(QWidget *parent)
{
// "Needed", as the creation below triggers ChildEvents that are
// passed to this object's event() which uses 'd'.
- d = nullptr;
- d = new TextEditorWidgetPrivate(this);
-
+ d = std::make_unique<Internal::TextEditorWidgetPrivate>(this);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setLayoutDirection(Qt::LeftToRight);
viewport()->setMouseTracking(true);
setFrameStyle(QFrame::NoFrame);
}
+TextEditorWidget::~TextEditorWidget() = default;
+
void TextEditorWidget::setTextDocument(const QSharedPointer<TextDocument> &doc)
{
d->setDocument(doc);
@@ -1449,12 +1503,6 @@ void TextEditorWidgetPrivate::setDocument(const QSharedPointer<TextDocument> &do
setupFromDefinition(currentDefinition());
}
-TextEditorWidget::~TextEditorWidget()
-{
- delete d;
- d = nullptr;
-}
-
void TextEditorWidget::print(QPrinter *printer)
{
const bool oldFullPage = printer->fullPage();
@@ -1884,6 +1932,12 @@ void TextEditorWidget::setVisualIndentOffset(int offset)
d->m_visualIndentOffset = qMax(0, offset);
}
+void TextEditorWidget::updateUndoRedoActions()
+{
+ d->updateUndoAction();
+ d->updateRedoAction();
+}
+
void TextEditorWidgetPrivate::updateCannotDecodeInfo()
{
q->setReadOnly(m_document->hasDecodingError());
@@ -1935,8 +1989,8 @@ void TextEditorWidgetPrivate::foldLicenseHeader()
QStringList commentMarker;
QStringList docMarker;
HighlighterHelper::Definition def;
- if (SyntaxHighlighterRunner *highlighter = q->textDocument()->syntaxHighlighterRunner())
- def = HighlighterHelper::definitionForName(highlighter->definitionName());
+ if (auto highlighter = qobject_cast<Highlighter *>(q->textDocument()->syntaxHighlighter()))
+ def = highlighter->definition();
if (def.isValid()) {
for (const QString &marker :
@@ -2535,6 +2589,16 @@ void TextEditorWidget::redo()
QPlainTextEdit::redo();
}
+bool TextEditorWidget::isUndoAvailable() const
+{
+ return document()->isUndoAvailable();
+}
+
+bool TextEditorWidget::isRedoAvailable() const
+{
+ return document()->isRedoAvailable();
+}
+
void TextEditorWidget::openLinkUnderCursor()
{
d->openLinkUnderCursor(alwaysOpenLinksInNextSplit());
@@ -3494,10 +3558,10 @@ QByteArray TextEditorWidget::saveState() const
bool TextEditorWidget::singleShotAfterHighlightingDone(std::function<void()> &&f)
{
- if (d->m_document->syntaxHighlighterRunner()
- && !d->m_document->syntaxHighlighterRunner()->syntaxInfoUpdated()) {
- connect(d->m_document->syntaxHighlighterRunner(),
- &SyntaxHighlighterRunner::highlightingFinished,
+ if (d->m_document->syntaxHighlighter()
+ && !d->m_document->syntaxHighlighter()->syntaxHighlighterUpToDate()) {
+ connect(d->m_document->syntaxHighlighter(),
+ &SyntaxHighlighter::finished,
this,
[f = std::move(f)] { f(); }, Qt::SingleShotConnection);
return true;
@@ -3741,10 +3805,11 @@ void TextEditorWidgetPrivate::configureGenericHighlighter(
const QString definitionFilesPath
= TextEditorSettings::highlighterSettings().definitionFilesPath().toString();
- m_document->resetSyntaxHighlighter([definitionFilesPath] {
- return new Highlighter(definitionFilesPath);
+ m_document->resetSyntaxHighlighter([definitionFilesPath, definition] {
+ auto highlighter = new Highlighter(definitionFilesPath);
+ highlighter->setDefinition(definition);
+ return highlighter;
});
- m_document->syntaxHighlighterRunner()->setDefinitionName(definition.name());
m_document->setFontSettings(TextEditorSettings::fontSettings());
}
@@ -3769,8 +3834,8 @@ void TextEditorWidgetPrivate::setupFromDefinition(const KSyntaxHighlighting::Def
KSyntaxHighlighting::Definition TextEditorWidgetPrivate::currentDefinition()
{
- if (SyntaxHighlighterRunner *highlighter = m_document->syntaxHighlighterRunner())
- return HighlighterHelper::definitionForName(highlighter->definitionName());
+ if (auto *highlighter = qobject_cast<Highlighter *>(m_document->syntaxHighlighter()))
+ return highlighter->definition();
return {};
}
@@ -3810,6 +3875,531 @@ qreal TextEditorWidgetPrivate::charWidth() const
return QFontMetricsF(q->font()).horizontalAdvance(QLatin1Char('x'));
}
+void TextEditorWidgetPrivate::registerActions()
+{
+ using namespace Core::Constants;
+ using namespace TextEditor::Constants;
+
+ ActionBuilder(this, Constants::COMPLETE_THIS)
+ .setContext(m_editorContext)
+ .addOnTriggered(this, [this] { q->invokeAssist(Completion); });
+
+ ActionBuilder(this, Constants::FUNCTION_HINT)
+ .setContext(m_editorContext)
+ .addOnTriggered(this, [this] { q->invokeAssist(FunctionHint); });
+
+ ActionBuilder(this, Constants::QUICKFIX_THIS)
+ .setContext(m_editorContext)
+ .addOnTriggered(this, [this] { q->invokeAssist(QuickFix); });
+
+ ActionBuilder(this, Constants::SHOWCONTEXTMENU)
+ .setContext(m_editorContext)
+ .addOnTriggered(this, [this] { q->showContextMenu(); });
+
+ m_undoAction = ActionBuilder(this, UNDO)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->undo(); })
+ .setScriptable(true)
+ .contextAction();
+ m_redoAction = ActionBuilder(this, REDO)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->redo(); })
+ .setScriptable(true)
+ .contextAction();
+ m_copyAction = ActionBuilder(this, COPY)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->copy(); })
+ .setScriptable(true)
+ .contextAction();
+ m_cutAction = ActionBuilder(this, CUT)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->cut(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, PASTE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->paste(); })
+ .setScriptable(true)
+ .contextAction();
+ ActionBuilder(this, SELECTALL)
+ .setContext(m_editorContext)
+ .setScriptable(true)
+ .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(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DELETE_END_OF_LINE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->deleteEndOfLine(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DELETE_END_OF_WORD)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->deleteEndOfWord(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DELETE_END_OF_WORD_CAMEL_CASE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->deleteEndOfWordCamelCase(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DELETE_START_OF_LINE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->deleteStartOfLine(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DELETE_START_OF_WORD)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->deleteStartOfWord(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DELETE_START_OF_WORD_CAMEL_CASE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->deleteStartOfWordCamelCase(); })
+ .setScriptable(true)
+ .contextAction();
+ ActionBuilder(this, GOTO_BLOCK_START_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoBlockStartWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_BLOCK_END_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoBlockEndWithSelection(); })
+ .setScriptable(true);
+ m_modifyingActions << ActionBuilder(this, MOVE_LINE_UP)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->moveLineUp(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, MOVE_LINE_DOWN)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->moveLineDown(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, COPY_LINE_UP)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->copyLineUp(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, COPY_LINE_DOWN)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->copyLineDown(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, JOIN_LINES)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->joinLines(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, INSERT_LINE_ABOVE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->insertLineAbove(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, INSERT_LINE_BELOW)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->insertLineBelow(); })
+ .setScriptable(true)
+ .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(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, UNINDENT)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->unindent(); })
+ .setScriptable(true)
+ .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(); })
+ .setScriptable(true)
+ .contextAction();
+ m_openTypeHierarchyAction = ActionBuilder(this, OPEN_TYPE_HIERARCHY)
+ .setContext(m_editorContext)
+ .addOnTriggered([] {
+ updateTypeHierarchy(NavigationWidget::activateSubWidget(
+ Constants::TYPE_HIERARCHY_FACTORY_ID, Side::Left));
+ })
+ .setScriptable(true)
+ .contextAction();
+ ActionBuilder(this, VIEW_PAGE_UP)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->viewPageUp(); })
+ .setScriptable(true);
+ ActionBuilder(this, VIEW_PAGE_DOWN)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->viewPageDown(); })
+ .setScriptable(true);
+ ActionBuilder(this, VIEW_LINE_UP)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->viewLineUp(); })
+ .setScriptable(true);
+ ActionBuilder(this, VIEW_LINE_DOWN)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->viewLineDown(); })
+ .setScriptable(true);
+
+ 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(); })
+ .setScriptable(true)
+ .contextAction();
+
+ m_autoIndentAction = ActionBuilder(this, AUTO_INDENT_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->autoIndent(); })
+ .setScriptable(true)
+ .contextAction();
+ m_autoFormatAction = ActionBuilder(this, AUTO_FORMAT_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->autoFormat(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, REWRAP_PARAGRAPH)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->rewrapParagraph(); })
+ .setScriptable(true)
+ .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(); })
+ .setScriptable(true)
+ .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(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, CUT_LINE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->cutLine(); })
+ .setScriptable(true)
+ .contextAction();
+ ActionBuilder(this, COPY_LINE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->copyLine(); })
+ .setScriptable(true);
+ m_copyHtmlAction = ActionBuilder(this, COPY_WITH_HTML)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->copyWithHtml(); })
+ .setScriptable(true)
+ .contextAction();
+ ActionBuilder(this, ADD_CURSORS_TO_LINE_ENDS)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->addCursorsToLineEnds(); })
+ .setScriptable(true);
+ ActionBuilder(this, ADD_SELECT_NEXT_FIND_MATCH)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->addSelectionNextFindMatch(); })
+ .setScriptable(true);
+ m_modifyingActions << ActionBuilder(this, DUPLICATE_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->duplicateSelection(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, DUPLICATE_SELECTION_AND_COMMENT)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->duplicateSelectionAndComment(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, UPPERCASE_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->uppercaseSelection(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, LOWERCASE_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->lowercaseSelection(); })
+ .setScriptable(true)
+ .contextAction();
+ m_modifyingActions << ActionBuilder(this, SORT_LINES)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->sortLines(); })
+ .setScriptable(true)
+ .contextAction();
+ ActionBuilder(this, FOLD)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->foldCurrentBlock(); })
+ .setScriptable(true);
+ ActionBuilder(this, UNFOLD)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->unfoldCurrentBlock(); })
+ .setScriptable(true);
+ m_unfoldAllAction = ActionBuilder(this, UNFOLD_ALL)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->unfoldAll(); })
+ .setScriptable(true)
+ .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(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_BLOCK_END)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoBlockEnd(); })
+ .setScriptable(true);
+ ActionBuilder(this, SELECT_BLOCK_UP)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->selectBlockUp(); })
+ .setScriptable(true);
+ ActionBuilder(this, SELECT_BLOCK_DOWN)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->selectBlockDown(); })
+ .setScriptable(true);
+ ActionBuilder(this, SELECT_WORD_UNDER_CURSOR)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->selectWordUnderCursor(); })
+ .setScriptable(true);
+
+ ActionBuilder(this, GOTO_DOCUMENT_START)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoDocumentStart(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_DOCUMENT_END)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoDocumentEnd(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_LINE_START)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoLineStart(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_LINE_END)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoLineEnd(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_LINE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextLine(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_LINE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousLine(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_CHARACTER)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousCharacter(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_CHARACTER)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextCharacter(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_WORD)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousWord(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_WORD)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextWord(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_WORD_CAMEL_CASE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousWordCamelCase(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_WORD_CAMEL_CASE)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextWordCamelCase(); })
+ .setScriptable(true);
+
+ ActionBuilder(this, GOTO_LINE_START_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoLineStartWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_LINE_END_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoLineEndWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_LINE_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextLineWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_LINE_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousLineWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_CHARACTER_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousCharacterWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_CHARACTER_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextCharacterWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_WORD_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousWordWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_WORD_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextWordWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoPreviousWordCamelCaseWithSelection(); })
+ .setScriptable(true);
+ ActionBuilder(this, GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION)
+ .setContext(m_editorContext)
+ .addOnTriggered([this] { q->gotoNextWordCamelCaseWithSelection(); })
+ .setScriptable(true);
+
+ // 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();
+ updateUndoAction();
+ 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()
+{
+ m_redoAction->setEnabled(q->isRedoAvailable());
+}
+
+void TextEditorWidgetPrivate::updateUndoAction()
+{
+ m_undoAction->setEnabled(q->isUndoAvailable());
+}
+
+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;
@@ -5127,7 +5717,8 @@ void TextEditorWidgetPrivate::setupBlockLayout(const PaintEventData &data,
blockData.layout = data.block.layout();
QTextOption option = blockData.layout->textOption();
- if (data.suppressSyntaxInIfdefedOutBlock && TextDocumentLayout::ifdefedOut(data.block)) {
+ if (data.suppressSyntaxInIfdefedOutBlock
+ && TextDocumentLayout::ifdefedOut(data.block)) {
option.setFlags(option.flags() | QTextOption::SuppressColors);
painter.setPen(data.ifdefedOutFormat.foreground().color());
} else {
@@ -5746,8 +6337,8 @@ void TextEditorWidgetPrivate::paintCodeFolding(QPainter &painter,
TextBlockUserData *nextBlockUserData = TextDocumentLayout::textUserData(nextBlock);
bool drawBox = nextBlockUserData
- && TextDocumentLayout::foldingIndent(data.block) < nextBlockUserData->foldingIndent();
-
+ && TextDocumentLayout::foldingIndent(data.block)
+ < nextBlockUserData->foldingIndent();
const int blockNumber = data.block.blockNumber();
bool active = blockNumber == extraAreaHighlightFoldBlockNumber;
@@ -5796,7 +6387,7 @@ void TextEditorWidgetPrivate::paintRevisionMarker(QPainter &painter,
void TextEditorWidget::extraAreaPaintEvent(QPaintEvent *e)
{
- ExtraAreaPaintEventData data(this, d);
+ ExtraAreaPaintEventData data(this, d.get());
QTC_ASSERT(data.documentLayout, return);
QPainter painter(d->m_extraArea);
@@ -5903,7 +6494,7 @@ void TextEditorWidgetPrivate::slotUpdateRequest(const QRect &r, int dy)
void TextEditorWidgetPrivate::saveCurrentCursorPositionForNavigation()
{
m_lastCursorChangeWasInteresting = true;
- m_tempNavigationState = q->saveState();
+ emit q->saveCurrentStateForNavigationHistory();
}
void TextEditorWidgetPrivate::updateCurrentLineHighlight()
@@ -5959,8 +6550,7 @@ void TextEditorWidget::slotCursorPositionChanged()
<< "indent:" << BaseTextDocumentLayout::userData(textCursor().block())->foldingIndent();
#endif
if (!d->m_contentsChanged && d->m_lastCursorChangeWasInteresting) {
- if (EditorManager::currentEditor() && EditorManager::currentEditor()->widget() == this)
- EditorManager::addCurrentPositionToNavigationHistory(d->m_tempNavigationState);
+ emit addSavedStateToNavigationHistory();
d->m_lastCursorChangeWasInteresting = false;
} else if (d->m_contentsChanged) {
d->saveCurrentCursorPositionForNavigation();
@@ -6266,7 +6856,6 @@ void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
{
const Qt::MouseButton button = e->button();
if (d->m_linkPressed && d->isMouseNavigationEvent(e) && button == Qt::LeftButton) {
- EditorManager::addCurrentPositionToNavigationHistory();
bool inNextSplit = ((e->modifiers() & Qt::AltModifier) && !alwaysOpenLinksInNextSplit())
|| (alwaysOpenLinksInNextSplit() && !(e->modifiers() & Qt::AltModifier));
@@ -6988,13 +7577,13 @@ bool TextEditorWidget::openLink(const Utils::Link &link, bool inNextSplit)
#endif
QString url = link.targetFilePath.toString();
- if (url.startsWith(u"https://"_qs) || url.startsWith(u"http://"_qs)) {
+ if (url.startsWith(u"https://") || url.startsWith(u"http://")) {
QDesktopServices::openUrl(url);
return true;
}
if (!inNextSplit && textDocument()->filePath() == link.targetFilePath) {
- EditorManager::addCurrentPositionToNavigationHistory();
+ emit addCurrentStateToNavigationHistory();
gotoLine(link.targetLine, link.targetColumn, true, true);
setFocus();
return true;
@@ -7027,11 +7616,12 @@ void TextEditorWidgetPrivate::requestUpdateLink(QMouseEvent *e)
return;
// Check that the mouse was actually on the text somewhere
- bool onText = q->cursorRect(cursor).right() >= e->x();
+ const int posX = e->position().x();
+ bool onText = q->cursorRect(cursor).right() >= posX;
if (!onText) {
QTextCursor nextPos = cursor;
nextPos.movePosition(QTextCursor::Right);
- onText = q->cursorRect(nextPos).right() >= e->x();
+ onText = q->cursorRect(nextPos).right() >= posX;
}
if (onText) {
@@ -8102,6 +8692,7 @@ void TextEditorWidgetPrivate::applyFontSettingsDelayed()
m_fontSettingsNeedsApply = true;
if (q->isVisible())
q->triggerPendingUpdates();
+ updateActions();
}
void TextEditorWidgetPrivate::markRemoved(TextMark *mark)
@@ -8183,7 +8774,7 @@ void TextEditorWidget::setDisplaySettings(const DisplaySettings &ds)
optionFlags.setFlag(QTextOption::AddSpaceForLineAndParagraphSeparators);
optionFlags.setFlag(QTextOption::ShowTabsAndSpaces, ds.m_visualizeWhitespace);
if (optionFlags != currentOptionFlags) {
- if (SyntaxHighlighterRunner *highlighter = textDocument()->syntaxHighlighterRunner())
+ if (SyntaxHighlighter *highlighter = textDocument()->syntaxHighlighter())
highlighter->rehighlight();
QTextOption option = document()->defaultTextOption();
option.setFlags(optionFlags);
@@ -8337,6 +8928,7 @@ void TextEditorWidget::setReadOnly(bool b)
emit readOnlyChanged();
if (b)
setTextInteractionFlags(textInteractionFlags() | Qt::TextSelectableByKeyboard);
+ d->updateActions();
}
void TextEditorWidget::cut()
@@ -8462,7 +9054,7 @@ QMimeData *TextEditorWidget::createMimeDataFromSelection(bool withHtml) const
} else {
const int startPosition = current.position() - selectionStart
- removedCount;
- int endPosition = startPosition + current.text().count();
+ int endPosition = startPosition + current.text().size();
if (current != last)
endPosition++;
removedCount += endPosition - startPosition;
@@ -8641,7 +9233,7 @@ void TextEditorWidget::dragLeaveEvent(QDragLeaveEvent *)
void TextEditorWidget::dragMoveEvent(QDragMoveEvent *e)
{
const QRect rect = cursorRect(d->m_dndCursor);
- d->m_dndCursor = cursorForPosition(e->pos());
+ d->m_dndCursor = cursorForPosition(e->position().toPoint());
if (!rect.isNull())
viewport()->update(rect);
viewport()->update(cursorRect(d->m_dndCursor));
@@ -8659,7 +9251,7 @@ void TextEditorWidget::dropEvent(QDropEvent *e)
// Update multi text cursor before inserting data
MultiTextCursor cursor = multiTextCursor();
cursor.beginEditBlock();
- const QTextCursor eventCursor = cursorForPosition(e->pos());
+ const QTextCursor eventCursor = cursorForPosition(e->position().toPoint());
if (e->dropAction() == Qt::MoveAction && e->source() == viewport())
cursor.removeSelectedText();
cursor.setCursors({eventCursor});
@@ -8734,31 +9326,36 @@ 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() & OptionalActions::TypeHierarchy) {
+ const auto action = ActionManager::command(Constants::OPEN_TYPE_HIERARCHY)->action();
+ if (!menu->actions().contains(action))
+ menu->addAction(action);
+ }
menu->addSeparator();
appendMenuActionsFromContext(menu, Constants::M_STANDARDCONTEXTMENU);
@@ -8786,7 +9383,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)
@@ -9003,6 +9600,23 @@ void BaseTextEditor::select(int toPos)
editorWidget()->setTextCursor(tc);
}
+void BaseTextEditor::saveCurrentStateForNavigationHistory()
+{
+ d->m_savedNavigationState = saveState();
+}
+
+void BaseTextEditor::addSavedStateToNavigationHistory()
+{
+ if (EditorManager::currentEditor() == this)
+ EditorManager::addCurrentPositionToNavigationHistory(d->m_savedNavigationState);
+}
+
+void BaseTextEditor::addCurrentStateToNavigationHistory()
+{
+ if (EditorManager::currentEditor() == this)
+ EditorManager::addCurrentPositionToNavigationHistory();
+}
+
void TextEditorWidgetPrivate::updateCursorPosition()
{
m_contextHelpItem = HelpItem();
@@ -9402,7 +10016,7 @@ void TextEditorWidget::setupGenericHighlighter()
setLineSeparatorsAllowed(true);
connect(textDocument(), &IDocument::filePathChanged,
- d, &TextEditorWidgetPrivate::reconfigure);
+ d.get(), &TextEditorWidgetPrivate::reconfigure);
}
//
@@ -9486,7 +10100,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;
@@ -9559,9 +10173,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)
@@ -9607,8 +10221,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);
@@ -9635,6 +10248,21 @@ BaseTextEditor *TextEditorFactoryPrivate::createEditorHelper(const TextDocumentP
[editor](EditorManager::OpenEditorFlags flags) {
EditorManager::activateEditor(editor, flags);
});
+ QObject::connect(
+ textEditorWidget,
+ &TextEditorWidget::saveCurrentStateForNavigationHistory,
+ editor,
+ &BaseTextEditor::saveCurrentStateForNavigationHistory);
+ QObject::connect(
+ textEditorWidget,
+ &TextEditorWidget::addSavedStateToNavigationHistory,
+ editor,
+ &BaseTextEditor::addSavedStateToNavigationHistory);
+ QObject::connect(
+ textEditorWidget,
+ &TextEditorWidget::addCurrentStateToNavigationHistory,
+ editor,
+ &BaseTextEditor::addCurrentStateToNavigationHistory);
if (m_useGenericHighlighter)
textEditorWidget->setupGenericHighlighter();
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 85344a8dbd0..7fc56e87337 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -85,6 +85,22 @@ enum TextMarkRequestKind
TaskMarkRequest
};
+namespace OptionalActions {
+enum Mask {
+ None = 0,
+ Format = 1,
+ UnCommentSelection = 2,
+ UnCollapseAll = 4,
+ FollowSymbolUnderCursor = 8,
+ FollowTypeUnderCursor = 16,
+ JumpToFileUnderCursor = 32,
+ RenameSymbol = 64,
+ FindUsage = 128,
+ CallHierarchy = 256,
+ TypeHierarchy = 512,
+};
+} // namespace OptionalActions
+
class TEXTEDITOR_EXPORT BaseTextEditor : public Core::IEditor
{
Q_OBJECT
@@ -153,6 +169,11 @@ public:
private:
friend class TextEditorFactory;
friend class Internal::TextEditorFactoryPrivate;
+
+ void saveCurrentStateForNavigationHistory();
+ void addSavedStateToNavigationHistory();
+ void addCurrentStateToNavigationHistory();
+
Internal::BaseTextEditorPrivate *d;
};
@@ -441,6 +462,9 @@ public:
virtual void undo();
virtual void redo();
+ virtual bool isUndoAvailable() const;
+ virtual bool isRedoAvailable() const;
+
void openLinkUnderCursor();
void openLinkUnderCursorInNextSplit();
void openTypeUnderCursor();
@@ -511,9 +535,13 @@ signals:
void requestUsages(const QTextCursor &cursor);
void requestRename(const QTextCursor &cursor);
void requestCallHierarchy(const QTextCursor &cursor);
- void optionalActionMaskChanged();
void toolbarOutlineChanged(QWidget *newOutline);
+ // used by the IEditor
+ void saveCurrentStateForNavigationHistory();
+ void addSavedStateToNavigationHistory();
+ void addCurrentStateToNavigationHistory();
+
protected:
QTextBlock blockForVisibleRow(int row) const;
QTextBlock blockForVerticalOffset(int offset) const;
@@ -569,6 +597,8 @@ protected:
void setVisualIndentOffset(int offset);
+ void updateUndoRedoActions();
+
public:
QString selectedText() const;
@@ -637,7 +667,7 @@ protected:
virtual void slotCodeStyleSettingsChanged(const QVariant &); // Used in CppEditor
private:
- Internal::TextEditorWidgetPrivate *d;
+ std::unique_ptr<Internal::TextEditorWidgetPrivate> d;
friend class BaseTextEditor;
friend class TextEditorFactory;
friend class Internal::TextEditorFactoryPrivate;
@@ -689,7 +719,7 @@ public:
void setSyntaxHighlighterCreator(const SyntaxHighLighterCreator &creator);
void setUseGenericHighlighter(bool enabled);
void setAutoCompleterCreator(const AutoCompleterCreator &creator);
- void setEditorActionHandlers(uint optionalActions);
+ void setOptionalActionMask(int optionalActions);
void addHoverHandler(BaseHoverHandler *handler);
void setCompletionAssistProvider(CompletionAssistProvider *provider);
diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs
index 821d9a4a479..ccb298a5aa8 100644
--- a/src/plugins/texteditor/texteditor.qbs
+++ b/src/plugins/texteditor/texteditor.qbs
@@ -124,8 +124,6 @@ QtcPlugin {
"storagesettings.h",
"syntaxhighlighter.cpp",
"syntaxhighlighter.h",
- "syntaxhighlighterrunner.cpp",
- "syntaxhighlighterrunner.h",
"tabsettings.cpp",
"tabsettings.h",
"tabsettingswidget.cpp",
@@ -137,9 +135,8 @@ QtcPlugin {
"texteditor.cpp",
"texteditor.h",
"texteditor.qrc",
- "texteditor_global.h", "texteditortr.h",
- "texteditoractionhandler.cpp",
- "texteditoractionhandler.h",
+ "texteditor_global.h",
+ "texteditortr.h",
"texteditorconstants.cpp",
"texteditorconstants.h",
"texteditoroverlay.cpp",
@@ -152,6 +149,8 @@ QtcPlugin {
"textmark.cpp",
"textmark.h",
"textstyles.h",
+ "typehierarchy.cpp",
+ "typehierarchy.h",
"typingsettings.cpp",
"typingsettings.h",
]
@@ -223,8 +222,6 @@ QtcPlugin {
"snippetprovider.h",
"snippetscollection.cpp",
"snippetscollection.h",
- "snippetssettings.cpp",
- "snippetssettings.h",
"snippetssettingspage.cpp",
"snippetssettingspage.h",
]
diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp
deleted file mode 100644
index 240e8498ed1..00000000000
--- a/src/plugins/texteditor/texteditoractionhandler.cpp
+++ /dev/null
@@ -1,656 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "texteditoractionhandler.h"
-
-#include "texteditor.h"
-#include "displaysettings.h"
-#include "fontsettings.h"
-#include "linenumberfilter.h"
-#include "texteditortr.h"
-#include "texteditorsettings.h"
-
-#include <aggregation/aggregate.h>
-
-#include <coreplugin/locator/locatormanager.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/actionmanager/command.h>
-
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QAction>
-
-#include <functional>
-
-using namespace Core;
-
-namespace TextEditor {
-namespace Internal {
-
-class TextEditorActionHandlerPrivate : public QObject
-{
-public:
- TextEditorActionHandlerPrivate(Utils::Id editorId, Utils::Id contextId, uint optionalActions);
-
- QAction *registerActionHelper(Utils::Id id,
- bool scriptable,
- const QString &title,
- const QKeySequence &keySequence,
- Utils::Id menueGroup,
- ActionContainer *container,
- std::function<void(bool)> slot)
- {
- auto result = new QAction(title, this);
- Command *command
- = ActionManager::registerAction(result, id, Context(m_contextId), scriptable);
- if (!keySequence.isEmpty())
- command->setDefaultKeySequence(keySequence);
-
- if (container && menueGroup.isValid())
- container->addAction(command, menueGroup);
-
- connect(result, &QAction::triggered, slot);
- return result;
- }
-
- QAction *registerAction(Utils::Id id,
- std::function<void(TextEditorWidget *)> slot,
- bool scriptable = false,
- const QString &title = QString(),
- const QKeySequence &keySequence = QKeySequence(),
- Utils::Id menueGroup = Utils::Id(),
- ActionContainer *container = nullptr)
- {
- return registerActionHelper(id,
- scriptable,
- title,
- keySequence,
- menueGroup,
- container,
- [this, slot, id](bool) {
- if (m_currentEditorWidget)
- slot(m_currentEditorWidget);
- else if (m_unhandledCallback)
- m_unhandledCallback(id, m_currentEditor);
- });
- }
-
- QAction *registerBoolAction(Utils::Id id,
- std::function<void(TextEditorWidget *, bool)> slot,
- bool scriptable = false,
- const QString &title = QString(),
- const QKeySequence &keySequence = QKeySequence(),
- Utils::Id menueGroup = Utils::Id(),
- ActionContainer *container = nullptr)
- {
- return registerActionHelper(id, scriptable, title, keySequence, menueGroup, container,
- [this, slot](bool on) { if (m_currentEditorWidget) slot(m_currentEditorWidget, on); });
- }
-
- QAction *registerIntAction(Utils::Id id,
- std::function<void(TextEditorWidget *, int)> slot,
- bool scriptable = false,
- const QString &title = QString(),
- const QKeySequence &keySequence = QKeySequence(),
- Utils::Id menueGroup = Utils::Id(),
- ActionContainer *container = nullptr)
- {
- return registerActionHelper(id, scriptable, title, keySequence, menueGroup, container,
- [this, slot](bool on) { if (m_currentEditorWidget) slot(m_currentEditorWidget, on); });
- }
-
- void createActions();
-
- void updateActions();
- void updateOptionalActions();
- void updateRedoAction(bool on);
- void updateUndoAction(bool on);
- void updateCopyAction(bool on);
-
- void updateCurrentEditor(IEditor *editor);
-
- void setCanUndoCallback(const TextEditorActionHandler::Predicate &callback);
- void setCanRedoCallback(const TextEditorActionHandler::Predicate &callback);
-
-public:
- TextEditorActionHandler::TextEditorWidgetResolver m_findTextWidget;
- 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_renameSymbolAction = nullptr;
- QAction *m_jumpToFileAction = nullptr;
- QAction *m_jumpToFileInNextSplitAction = nullptr;
- QList<QAction *> m_modifyingActions;
-
- uint m_optionalActions = TextEditorActionHandler::None;
- QPointer<TextEditorWidget> m_currentEditorWidget;
- QPointer<IEditor> m_currentEditor;
- Utils::Id m_editorId;
- Utils::Id m_contextId;
-
- TextEditorActionHandler::Predicate m_canUndoCallback;
- TextEditorActionHandler::Predicate m_canRedoCallback;
-
- TextEditorActionHandler::UnhandledCallback m_unhandledCallback;
-};
-
-TextEditorActionHandlerPrivate::TextEditorActionHandlerPrivate
- (Utils::Id editorId, Utils::Id contextId, uint optionalActions)
- : m_optionalActions(optionalActions)
- , m_editorId(editorId)
- , m_contextId(contextId)
-{
- createActions();
- connect(EditorManager::instance(),
- &EditorManager::currentEditorChanged,
- this,
- &TextEditorActionHandlerPrivate::updateCurrentEditor);
- connect(TextEditorSettings::instance(), &TextEditorSettings::fontSettingsChanged,
- this, &TextEditorActionHandlerPrivate::updateActions);
-}
-
-void TextEditorActionHandlerPrivate::createActions()
-{
- using namespace Core::Constants;
- using namespace TextEditor::Constants;
-
- m_undoAction = registerAction(UNDO,
- [] (TextEditorWidget *w) { w->undo(); }, true, Tr::tr("&Undo"));
- m_redoAction = registerAction(REDO,
- [] (TextEditorWidget *w) { w->redo(); }, true, Tr::tr("&Redo"));
- m_copyAction = registerAction(COPY,
- [] (TextEditorWidget *w) { w->copy(); }, true);
- m_cutAction = registerAction(CUT,
- [] (TextEditorWidget *w) { w->cut(); }, true);
- m_modifyingActions << registerAction(PASTE,
- [] (TextEditorWidget *w) { w->paste(); }, true);
- registerAction(SELECTALL,
- [] (TextEditorWidget *w) { w->selectAll(); }, true);
- registerAction(GOTO, [](TextEditorWidget *) {
- LocatorManager::showFilter(lineNumberFilter());
- });
- m_modifyingActions << registerAction(PRINT, [](TextEditorWidget *widget) {
- widget->print(ICore::printer());
- });
- m_modifyingActions << registerAction(DELETE_LINE,
- [] (TextEditorWidget *w) { w->deleteLine(); }, true, Tr::tr("Delete &Line"));
- m_modifyingActions << registerAction(DELETE_END_OF_LINE,
- [] (TextEditorWidget *w) { w->deleteEndOfLine(); }, true, Tr::tr("Delete Line from Cursor On"));
- m_modifyingActions << registerAction(DELETE_END_OF_WORD,
- [] (TextEditorWidget *w) { w->deleteEndOfWord(); }, true, Tr::tr("Delete Word from Cursor On"));
- m_modifyingActions << registerAction(DELETE_END_OF_WORD_CAMEL_CASE,
- [] (TextEditorWidget *w) { w->deleteEndOfWordCamelCase(); }, true, Tr::tr("Delete Word Camel Case from Cursor On"));
- m_modifyingActions << registerAction(
- DELETE_START_OF_LINE,
- [](TextEditorWidget *w) { w->deleteStartOfLine(); },
- true,
- Tr::tr("Delete Line up to Cursor"),
- Core::useMacShortcuts ? QKeySequence(Tr::tr("Ctrl+Backspace")) : QKeySequence());
- m_modifyingActions << registerAction(DELETE_START_OF_WORD,
- [] (TextEditorWidget *w) { w->deleteStartOfWord(); }, true, Tr::tr("Delete Word up to Cursor"));
- m_modifyingActions << registerAction(DELETE_START_OF_WORD_CAMEL_CASE,
- [] (TextEditorWidget *w) { w->deleteStartOfWordCamelCase(); }, true, Tr::tr("Delete Word Camel Case up to Cursor"));
- registerAction(GOTO_BLOCK_START_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoBlockStartWithSelection(); }, true, Tr::tr("Go to Block Start with Selection"),
- QKeySequence(Tr::tr("Ctrl+{")));
- registerAction(GOTO_BLOCK_END_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoBlockEndWithSelection(); }, true, Tr::tr("Go to Block End with Selection"),
- QKeySequence(Tr::tr("Ctrl+}")));
- m_modifyingActions << registerAction(MOVE_LINE_UP,
- [] (TextEditorWidget *w) { w->moveLineUp(); }, true, Tr::tr("Move Line Up"),
- QKeySequence(Tr::tr("Ctrl+Shift+Up")));
- m_modifyingActions << registerAction(MOVE_LINE_DOWN,
- [] (TextEditorWidget *w) { w->moveLineDown(); }, true, Tr::tr("Move Line Down"),
- QKeySequence(Tr::tr("Ctrl+Shift+Down")));
- m_modifyingActions << registerAction(COPY_LINE_UP,
- [] (TextEditorWidget *w) { w->copyLineUp(); }, true, Tr::tr("Copy Line Up"),
- QKeySequence(Tr::tr("Ctrl+Alt+Up")));
- m_modifyingActions << registerAction(COPY_LINE_DOWN,
- [] (TextEditorWidget *w) { w->copyLineDown(); }, true, Tr::tr("Copy Line Down"),
- QKeySequence(Tr::tr("Ctrl+Alt+Down")));
- m_modifyingActions << registerAction(JOIN_LINES,
- [] (TextEditorWidget *w) { w->joinLines(); }, true, Tr::tr("Join Lines"),
- QKeySequence(Tr::tr("Ctrl+J")));
- m_modifyingActions << registerAction(INSERT_LINE_ABOVE,
- [] (TextEditorWidget *w) { w->insertLineAbove(); }, true, Tr::tr("Insert Line Above Current Line"),
- QKeySequence(Tr::tr("Ctrl+Shift+Return")));
- m_modifyingActions << registerAction(INSERT_LINE_BELOW,
- [] (TextEditorWidget *w) { w->insertLineBelow(); }, true, Tr::tr("Insert Line Below Current Line"),
- QKeySequence(Tr::tr("Ctrl+Return")));
- m_modifyingActions << registerAction(SWITCH_UTF8BOM,
- [] (TextEditorWidget *w) { w->switchUtf8bom(); }, true, Tr::tr("Toggle UTF-8 BOM"));
- m_modifyingActions << registerAction(INDENT,
- [] (TextEditorWidget *w) { w->indent(); }, true, Tr::tr("Indent"));
- m_modifyingActions << registerAction(UNINDENT,
- [] (TextEditorWidget *w) { w->unindent(); }, true, Tr::tr("Unindent"));
- m_followSymbolAction = registerAction(FOLLOW_SYMBOL_UNDER_CURSOR,
- [] (TextEditorWidget *w) { w->openLinkUnderCursor(); }, true, Tr::tr("Follow Symbol Under Cursor"),
- QKeySequence(Qt::Key_F2));
- m_followSymbolInNextSplitAction = registerAction(FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT,
- [] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, Tr::tr("Follow Symbol Under Cursor in Next Split"),
- QKeySequence(Utils::HostOsInfo::isMacHost() ? Tr::tr("Meta+E, F2") : Tr::tr("Ctrl+E, F2")));
- m_followToTypeAction = registerAction(FOLLOW_SYMBOL_TO_TYPE,
- [] (TextEditorWidget *w) { w->openTypeUnderCursor(); }, true, Tr::tr("Follow Type Under Cursor"),
- QKeySequence(Tr::tr("Ctrl+Shift+F2")));
- m_followToTypeInNextSplitAction = registerAction(FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT,
- [] (TextEditorWidget *w) { w->openTypeUnderCursorInNextSplit(); }, true, Tr::tr("Follow Type Under Cursor in Next Split"),
- QKeySequence(Utils::HostOsInfo::isMacHost() ? Tr::tr("Meta+E, Shift+F2") : Tr::tr("Ctrl+E, Ctrl+Shift+F2")));
- m_findUsageAction = registerAction(FIND_USAGES,
- [] (TextEditorWidget *w) { w->findUsages(); }, true, Tr::tr("Find References to Symbol Under Cursor"),
- QKeySequence(Tr::tr("Ctrl+Shift+U")));
- m_renameSymbolAction = registerAction(RENAME_SYMBOL,
- [] (TextEditorWidget *w) { w->renameSymbolUnderCursor(); }, true, Tr::tr("Rename Symbol Under Cursor"),
- QKeySequence(Tr::tr("Ctrl+Shift+R")));
- m_jumpToFileAction = registerAction(JUMP_TO_FILE_UNDER_CURSOR,
- [] (TextEditorWidget *w) { w->openLinkUnderCursor(); }, true, Tr::tr("Jump to File Under Cursor"),
- QKeySequence(Qt::Key_F2));
- m_jumpToFileInNextSplitAction = registerAction(JUMP_TO_FILE_UNDER_CURSOR_IN_NEXT_SPLIT,
- [] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, Tr::tr("Jump to File Under Cursor in Next Split"),
- QKeySequence(Utils::HostOsInfo::isMacHost() ? Tr::tr("Meta+E, F2") : Tr::tr("Ctrl+E, F2")).toString());
- m_openCallHierarchyAction = registerAction(OPEN_CALL_HIERARCHY,
- [] (TextEditorWidget *w) { w->openCallHierarchy(); }, true, Tr::tr("Open Call Hierarchy"));
-
- registerAction(VIEW_PAGE_UP,
- [] (TextEditorWidget *w) { w->viewPageUp(); }, true, Tr::tr("Move the View a Page Up and Keep the Cursor Position"),
- QKeySequence(Tr::tr("Ctrl+PgUp")));
- registerAction(VIEW_PAGE_DOWN,
- [] (TextEditorWidget *w) { w->viewPageDown(); }, true, Tr::tr("Move the View a Page Down and Keep the Cursor Position"),
- QKeySequence(Tr::tr("Ctrl+PgDown")));
- registerAction(VIEW_LINE_UP,
- [] (TextEditorWidget *w) { w->viewLineUp(); }, true, Tr::tr("Move the View a Line Up and Keep the Cursor Position"),
- QKeySequence(Tr::tr("Ctrl+Up")));
- registerAction(VIEW_LINE_DOWN,
- [] (TextEditorWidget *w) { w->viewLineDown(); }, true, Tr::tr("Move the View a Line Down and Keep the Cursor Position"),
- QKeySequence(Tr::tr("Ctrl+Down")));
-
- // register "Edit" Menu Actions
- ActionContainer *editMenu = ActionManager::actionContainer(M_EDIT);
- registerAction(SELECT_ENCODING,
- [] (TextEditorWidget *w) { w->selectEncoding(); }, false, Tr::tr("Select Encoding..."),
- QKeySequence(), G_EDIT_OTHER, editMenu);
- m_modifyingActions << registerAction(CIRCULAR_PASTE,
- [] (TextEditorWidget *w) { w->circularPaste(); }, false, Tr::tr("Paste from Clipboard History"),
- QKeySequence(Tr::tr("Ctrl+Shift+V")), G_EDIT_COPYPASTE, editMenu);
- m_modifyingActions << registerAction(NO_FORMAT_PASTE,
- [] (TextEditorWidget *w) { w->pasteWithoutFormat(); }, false, Tr::tr("Paste Without Formatting"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Ctrl+Alt+Shift+V") : QString()), G_EDIT_COPYPASTE, editMenu);
-
- // register "Edit -> Advanced" Menu Actions
- ActionContainer *advancedEditMenu = ActionManager::actionContainer(M_EDIT_ADVANCED);
- m_autoIndentAction = registerAction(AUTO_INDENT_SELECTION,
- [] (TextEditorWidget *w) { w->autoIndent(); }, true, Tr::tr("Auto-&indent Selection"),
- QKeySequence(Tr::tr("Ctrl+I")),
- G_EDIT_FORMAT, advancedEditMenu);
- m_autoFormatAction = registerAction(AUTO_FORMAT_SELECTION,
- [] (TextEditorWidget *w) { w->autoFormat(); }, true, Tr::tr("Auto-&format Selection"),
- QKeySequence(Tr::tr("Ctrl+;")),
- G_EDIT_FORMAT, advancedEditMenu);
- m_modifyingActions << registerAction(REWRAP_PARAGRAPH,
- [] (TextEditorWidget *w) { w->rewrapParagraph(); }, true, Tr::tr("&Rewrap Paragraph"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+E, R") : Tr::tr("Ctrl+E, R")),
- G_EDIT_FORMAT, advancedEditMenu);
- m_visualizeWhitespaceAction = registerBoolAction(VISUALIZE_WHITESPACE,
- [] (TextEditorWidget *widget, bool checked) {
- if (widget) {
- DisplaySettings ds = widget->displaySettings();
- ds.m_visualizeWhitespace = checked;
- widget->setDisplaySettings(ds);
- }
- },
- false, Tr::tr("&Visualize Whitespace"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+E, Meta+V") : Tr::tr("Ctrl+E, Ctrl+V")),
- G_EDIT_FORMAT, advancedEditMenu);
- m_visualizeWhitespaceAction->setCheckable(true);
- m_modifyingActions << registerAction(CLEAN_WHITESPACE,
- [] (TextEditorWidget *w) { w->cleanWhitespace(); }, true, Tr::tr("Clean Whitespace"),
- QKeySequence(),
- G_EDIT_FORMAT, advancedEditMenu);
- m_textWrappingAction = registerBoolAction(TEXT_WRAPPING,
- [] (TextEditorWidget *widget, bool checked) {
- if (widget) {
- DisplaySettings ds = widget->displaySettings();
- ds.m_textWrapping = checked;
- widget->setDisplaySettings(ds);
- }
- },
- false, Tr::tr("Enable Text &Wrapping"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+E, Meta+W") : Tr::tr("Ctrl+E, Ctrl+W")),
- G_EDIT_FORMAT, advancedEditMenu);
- m_textWrappingAction->setCheckable(true);
- m_unCommentSelectionAction = registerAction(UN_COMMENT_SELECTION,
- [] (TextEditorWidget *w) { w->unCommentSelection(); }, true, Tr::tr("Toggle Comment &Selection"),
- QKeySequence(Tr::tr("Ctrl+/")),
- G_EDIT_FORMAT, advancedEditMenu);
- m_modifyingActions << registerAction(CUT_LINE,
- [] (TextEditorWidget *w) { w->cutLine(); }, true, Tr::tr("Cut &Line"),
- QKeySequence(Tr::tr("Shift+Del")),
- G_EDIT_TEXT, advancedEditMenu);
- registerAction(COPY_LINE,
- [] (TextEditorWidget *w) { w->copyLine(); }, false, Tr::tr("Copy &Line"),
- QKeySequence(Tr::tr("Ctrl+Ins")),
- G_EDIT_TEXT, advancedEditMenu);
- m_copyHtmlAction = registerAction(COPY_WITH_HTML,
- [] (TextEditorWidget *w) { w->copyWithHtml(); }, true, Tr::tr("Copy With Highlighting"),
- QKeySequence(), G_EDIT_TEXT, advancedEditMenu);
-
- registerAction(ADD_CURSORS_TO_LINE_ENDS,
- [] (TextEditorWidget *w) { w->addCursorsToLineEnds(); }, false, Tr::tr("Create Cursors at Selected Line Ends"),
- QKeySequence(Tr::tr("Alt+Shift+I")),
- G_EDIT_TEXT, advancedEditMenu);
- registerAction(ADD_SELECT_NEXT_FIND_MATCH,
- [] (TextEditorWidget *w) { w->addSelectionNextFindMatch(); }, false, Tr::tr("Add Next Occurrence to Selection"),
- QKeySequence(Tr::tr("Ctrl+D")),
- G_EDIT_TEXT, advancedEditMenu);
- m_modifyingActions << registerAction(DUPLICATE_SELECTION,
- [] (TextEditorWidget *w) { w->duplicateSelection(); }, false, Tr::tr("&Duplicate Selection"),
- QKeySequence(),
- G_EDIT_TEXT, advancedEditMenu);
- m_modifyingActions << registerAction(DUPLICATE_SELECTION_AND_COMMENT,
- [] (TextEditorWidget *w) { w->duplicateSelectionAndComment(); }, false, Tr::tr("&Duplicate Selection and Comment"),
- QKeySequence(),
- G_EDIT_TEXT, advancedEditMenu);
- m_modifyingActions << registerAction(UPPERCASE_SELECTION,
- [] (TextEditorWidget *w) { w->uppercaseSelection(); }, true, Tr::tr("Uppercase Selection"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+Shift+U") : Tr::tr("Alt+Shift+U")),
- G_EDIT_TEXT, advancedEditMenu);
- m_modifyingActions << registerAction(LOWERCASE_SELECTION,
- [] (TextEditorWidget *w) { w->lowercaseSelection(); }, true, Tr::tr("Lowercase Selection"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+U") : Tr::tr("Alt+U")),
- G_EDIT_TEXT, advancedEditMenu);
- m_modifyingActions << registerAction(SORT_LINES,
- [] (TextEditorWidget *w) { w->sortLines(); }, false, Tr::tr("&Sort Lines"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+Shift+S") : Tr::tr("Alt+Shift+S")),
- G_EDIT_TEXT, advancedEditMenu);
- registerAction(FOLD,
- [] (TextEditorWidget *w) { w->foldCurrentBlock(); }, true, Tr::tr("Fold"),
- QKeySequence(Tr::tr("Ctrl+<")),
- G_EDIT_COLLAPSING, advancedEditMenu);
- registerAction(UNFOLD,
- [] (TextEditorWidget *w) { w->unfoldCurrentBlock(); }, true, Tr::tr("Unfold"),
- QKeySequence(Tr::tr("Ctrl+>")),
- G_EDIT_COLLAPSING, advancedEditMenu);
- m_unfoldAllAction = registerAction(UNFOLD_ALL,
- [] (TextEditorWidget *w) { w->unfoldAll(); }, true, Tr::tr("Toggle &Fold All"),
- QKeySequence(),
- G_EDIT_COLLAPSING, advancedEditMenu);
- registerAction(INCREASE_FONT_SIZE,
- [] (TextEditorWidget *w) { w->increaseFontZoom(); }, false, Tr::tr("Increase Font Size"),
- QKeySequence(Tr::tr("Ctrl++")),
- G_EDIT_FONT, advancedEditMenu);
- registerAction(DECREASE_FONT_SIZE,
- [] (TextEditorWidget *w) { w->decreaseFontZoom(); }, false, Tr::tr("Decrease Font Size"),
- QKeySequence(Tr::tr("Ctrl+-")),
- G_EDIT_FONT, advancedEditMenu);
- registerAction(RESET_FONT_SIZE,
- [] (TextEditorWidget *w) { w->zoomReset(); }, false, Tr::tr("Reset Font Size"),
- QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+0") : Tr::tr("Ctrl+0")),
- G_EDIT_FONT, advancedEditMenu);
- registerAction(GOTO_BLOCK_START,
- [] (TextEditorWidget *w) { w->gotoBlockStart(); }, true, Tr::tr("Go to Block Start"),
- QKeySequence(Tr::tr("Ctrl+[")),
- G_EDIT_BLOCKS, advancedEditMenu);
- registerAction(GOTO_BLOCK_END,
- [] (TextEditorWidget *w) { w->gotoBlockEnd(); }, true, Tr::tr("Go to Block End"),
- QKeySequence(Tr::tr("Ctrl+]")),
- G_EDIT_BLOCKS, advancedEditMenu);
- registerAction(SELECT_BLOCK_UP,
- [] (TextEditorWidget *w) { w->selectBlockUp(); }, true, Tr::tr("Select Block Up"),
- QKeySequence(Tr::tr("Ctrl+U")),
- G_EDIT_BLOCKS, advancedEditMenu);
- registerAction(SELECT_BLOCK_DOWN,
- [] (TextEditorWidget *w) { w->selectBlockDown(); }, true, Tr::tr("Select Block Down"),
- QKeySequence(Tr::tr("Ctrl+Shift+Alt+U")),
- G_EDIT_BLOCKS, advancedEditMenu);
- registerAction(SELECT_WORD_UNDER_CURSOR,
- [] (TextEditorWidget *w) { w->selectWordUnderCursor(); }, true,
- Tr::tr("Select Word Under Cursor"));
-
- // register GOTO Actions
- registerAction(GOTO_DOCUMENT_START,
- [] (TextEditorWidget *w) { w->gotoDocumentStart(); }, true, Tr::tr("Go to Document Start"));
- registerAction(GOTO_DOCUMENT_END,
- [] (TextEditorWidget *w) { w->gotoDocumentEnd(); }, true, Tr::tr("Go to Document End"));
- registerAction(GOTO_LINE_START,
- [] (TextEditorWidget *w) { w->gotoLineStart(); }, true, Tr::tr("Go to Line Start"));
- registerAction(GOTO_LINE_END,
- [] (TextEditorWidget *w) { w->gotoLineEnd(); }, true, Tr::tr("Go to Line End"));
- registerAction(GOTO_NEXT_LINE,
- [] (TextEditorWidget *w) { w->gotoNextLine(); }, true, Tr::tr("Go to Next Line"));
- registerAction(GOTO_PREVIOUS_LINE,
- [] (TextEditorWidget *w) { w->gotoPreviousLine(); }, true, Tr::tr("Go to Previous Line"));
- registerAction(GOTO_PREVIOUS_CHARACTER,
- [] (TextEditorWidget *w) { w->gotoPreviousCharacter(); }, true, Tr::tr("Go to Previous Character"));
- registerAction(GOTO_NEXT_CHARACTER,
- [] (TextEditorWidget *w) { w->gotoNextCharacter(); }, true, Tr::tr("Go to Next Character"));
- registerAction(GOTO_PREVIOUS_WORD,
- [] (TextEditorWidget *w) { w->gotoPreviousWord(); }, true, Tr::tr("Go to Previous Word"));
- registerAction(GOTO_NEXT_WORD,
- [] (TextEditorWidget *w) { w->gotoNextWord(); }, true, Tr::tr("Go to Next Word"));
- registerAction(GOTO_PREVIOUS_WORD_CAMEL_CASE,
- [] (TextEditorWidget *w) { w->gotoPreviousWordCamelCase(); }, false, Tr::tr("Go to Previous Word Camel Case"));
- registerAction(GOTO_NEXT_WORD_CAMEL_CASE,
- [] (TextEditorWidget *w) { w->gotoNextWordCamelCase(); }, false, Tr::tr("Go to Next Word Camel Case"));
-
- // register GOTO actions with selection
- registerAction(GOTO_LINE_START_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoLineStartWithSelection(); }, true, Tr::tr("Go to Line Start with Selection"));
- registerAction(GOTO_LINE_END_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoLineEndWithSelection(); }, true, Tr::tr("Go to Line End with Selection"));
- registerAction(GOTO_NEXT_LINE_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoNextLineWithSelection(); }, true, Tr::tr("Go to Next Line with Selection"));
- registerAction(GOTO_PREVIOUS_LINE_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoPreviousLineWithSelection(); }, true, Tr::tr("Go to Previous Line with Selection"));
- registerAction(GOTO_PREVIOUS_CHARACTER_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoPreviousCharacterWithSelection(); }, true, Tr::tr("Go to Previous Character with Selection"));
- registerAction(GOTO_NEXT_CHARACTER_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoNextCharacterWithSelection(); }, true, Tr::tr("Go to Next Character with Selection"));
- registerAction(GOTO_PREVIOUS_WORD_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoPreviousWordWithSelection(); }, true, Tr::tr("Go to Previous Word with Selection"));
- registerAction(GOTO_NEXT_WORD_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoNextWordWithSelection(); }, true, Tr::tr("Go to Next Word with Selection"));
- registerAction(GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoPreviousWordCamelCaseWithSelection(); }, false, Tr::tr("Go to Previous Word Camel Case with Selection"));
- registerAction(GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION,
- [] (TextEditorWidget *w) { w->gotoNextWordCamelCaseWithSelection(); }, false, Tr::tr("Go to Next Word Camel Case with Selection"));
-
- // 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 TextEditorActionHandlerPrivate::updateActions()
-{
- bool isWritable = m_currentEditorWidget && !m_currentEditorWidget->isReadOnly();
- for (QAction *a : std::as_const(m_modifyingActions))
- a->setEnabled(isWritable);
- m_unCommentSelectionAction->setEnabled((m_optionalActions & TextEditorActionHandler::UnCommentSelection) && isWritable);
- m_visualizeWhitespaceAction->setEnabled(m_currentEditorWidget);
- if (TextEditorSettings::fontSettings().relativeLineSpacing() == 100) {
- m_textWrappingAction->setEnabled(m_currentEditorWidget);
- } else {
- m_textWrappingAction->setEnabled(false);
- m_textWrappingAction->setChecked(false);
- }
- if (m_currentEditorWidget) {
- m_visualizeWhitespaceAction->setChecked(
- m_currentEditorWidget->displaySettings().m_visualizeWhitespace);
- m_textWrappingAction->setChecked(m_currentEditorWidget->displaySettings().m_textWrapping);
- }
-
- bool canRedo = false;
- bool canUndo = false;
- bool canCopy = false;
-
- if (m_currentEditor && m_currentEditor->document()
- && m_currentEditor->document()->id() == m_editorId) {
- canRedo = m_canRedoCallback ? m_canRedoCallback(m_currentEditor) : false;
- canUndo = m_canUndoCallback ? m_canUndoCallback(m_currentEditor) : false;
-
- if (m_currentEditorWidget) {
- canRedo = m_canRedoCallback ? canRedo
- : m_currentEditorWidget->document()->isRedoAvailable();
- canUndo = m_canUndoCallback ? canUndo
- : m_currentEditorWidget->document()->isUndoAvailable();
- canCopy = m_currentEditorWidget->textCursor().hasSelection();
- }
- }
-
- updateRedoAction(canRedo);
- updateUndoAction(canUndo);
- updateCopyAction(canCopy);
-
- updateOptionalActions();
-}
-
-void TextEditorActionHandlerPrivate::updateOptionalActions()
-{
- const uint optionalActions = m_currentEditorWidget ? m_currentEditorWidget->optionalActions()
- : m_optionalActions;
- m_followSymbolAction->setEnabled(
- optionalActions & TextEditorActionHandler::FollowSymbolUnderCursor);
- m_followSymbolInNextSplitAction->setEnabled(
- optionalActions & TextEditorActionHandler::FollowSymbolUnderCursor);
- m_followToTypeAction->setEnabled(
- optionalActions & TextEditorActionHandler::FollowTypeUnderCursor);
- m_followToTypeInNextSplitAction->setEnabled(
- optionalActions & TextEditorActionHandler::FollowTypeUnderCursor);
- m_findUsageAction->setEnabled(
- optionalActions & TextEditorActionHandler::FindUsage);
- m_jumpToFileAction->setEnabled(
- optionalActions & TextEditorActionHandler::JumpToFileUnderCursor);
- m_jumpToFileInNextSplitAction->setEnabled(
- optionalActions & TextEditorActionHandler::JumpToFileUnderCursor);
- m_unfoldAllAction->setEnabled(
- optionalActions & TextEditorActionHandler::UnCollapseAll);
- m_renameSymbolAction->setEnabled(
- optionalActions & TextEditorActionHandler::RenameSymbol);
- m_openCallHierarchyAction->setEnabled(
- optionalActions & TextEditorActionHandler::CallHierarchy);
-
- bool formatEnabled = (optionalActions & TextEditorActionHandler::Format)
- && m_currentEditorWidget && !m_currentEditorWidget->isReadOnly();
- m_autoIndentAction->setEnabled(formatEnabled);
- m_autoFormatAction->setEnabled(formatEnabled);
-}
-
-void TextEditorActionHandlerPrivate::updateRedoAction(bool on)
-{
- m_redoAction->setEnabled(on);
-}
-
-void TextEditorActionHandlerPrivate::updateUndoAction(bool on)
-{
- m_undoAction->setEnabled(on);
-}
-
-void TextEditorActionHandlerPrivate::updateCopyAction(bool hasCopyableText)
-{
- if (m_cutAction)
- m_cutAction->setEnabled(hasCopyableText && m_currentEditorWidget
- && !m_currentEditorWidget->isReadOnly());
- if (m_copyAction)
- m_copyAction->setEnabled(hasCopyableText);
- if (m_copyHtmlAction)
- m_copyHtmlAction->setEnabled(hasCopyableText);
-}
-
-void TextEditorActionHandlerPrivate::updateCurrentEditor(IEditor *editor)
-{
- if (m_currentEditorWidget)
- m_currentEditorWidget->disconnect(this);
- m_currentEditorWidget = nullptr;
-
- m_currentEditor = editor;
-
- if (editor && editor->document()->id() == m_editorId) {
- m_currentEditorWidget = m_findTextWidget(editor);
- if (m_currentEditorWidget) {
- connect(m_currentEditorWidget, &QPlainTextEdit::undoAvailable,
- this, &TextEditorActionHandlerPrivate::updateUndoAction);
- connect(m_currentEditorWidget, &QPlainTextEdit::redoAvailable,
- this, &TextEditorActionHandlerPrivate::updateRedoAction);
- connect(m_currentEditorWidget, &QPlainTextEdit::copyAvailable,
- this, &TextEditorActionHandlerPrivate::updateCopyAction);
- connect(m_currentEditorWidget, &TextEditorWidget::readOnlyChanged,
- this, &TextEditorActionHandlerPrivate::updateActions);
- connect(m_currentEditorWidget, &TextEditorWidget::optionalActionMaskChanged,
- this, &TextEditorActionHandlerPrivate::updateOptionalActions);
- }
- }
- updateActions();
-}
-
-} // namespace Internal
-
-TextEditorActionHandler::TextEditorActionHandler(Utils::Id editorId,
- Utils::Id contextId,
- uint optionalActions,
- const TextEditorWidgetResolver &resolver)
- : d(new Internal::TextEditorActionHandlerPrivate(editorId, contextId, optionalActions))
-{
- if (resolver)
- d->m_findTextWidget = resolver;
- else
- d->m_findTextWidget = TextEditorWidget::fromEditor;
-}
-
-uint TextEditorActionHandler::optionalActions() const
-{
- return d->m_optionalActions;
-}
-
-TextEditorActionHandler::~TextEditorActionHandler()
-{
- delete d;
-}
-
-void TextEditorActionHandler::updateCurrentEditor()
-{
- d->updateCurrentEditor(EditorManager::currentEditor());
-}
-
-void TextEditorActionHandler::updateActions()
-{
- d->updateActions();
-}
-
-void TextEditorActionHandler::setCanUndoCallback(const Predicate &callback)
-{
- d->m_canUndoCallback = callback;
-}
-
-void TextEditorActionHandler::setCanRedoCallback(const Predicate &callback)
-{
- d->m_canRedoCallback = callback;
-}
-
-void TextEditorActionHandler::setUnhandledCallback(const UnhandledCallback &callback)
-{
- d->m_unhandledCallback = callback;
-}
-
-} // namespace TextEditor
diff --git a/src/plugins/texteditor/texteditoractionhandler.h b/src/plugins/texteditor/texteditoractionhandler.h
deleted file mode 100644
index 344a4a553e1..00000000000
--- a/src/plugins/texteditor/texteditoractionhandler.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "texteditor_global.h"
-
-#include <utils/id.h>
-
-#include <QObject>
-
-#include <functional>
-
-namespace Core {
-class IEditor;
-}
-
-namespace TextEditor {
-class TextEditorWidget;
-
-namespace Internal { class TextEditorActionHandlerPrivate; }
-
-// Redirects slots from global actions to the respective editor.
-
-class TEXTEDITOR_EXPORT TextEditorActionHandler final
-{
- TextEditorActionHandler(const TextEditorActionHandler &) = delete;
- TextEditorActionHandler &operator=(const TextEditorActionHandler &) = delete;
-
-public:
- enum OptionalActionsMask {
- None = 0,
- Format = 1,
- UnCommentSelection = 2,
- UnCollapseAll = 4,
- FollowSymbolUnderCursor = 8,
- FollowTypeUnderCursor = 16,
- JumpToFileUnderCursor = 32,
- RenameSymbol = 64,
- FindUsage = 128,
- CallHierarchy = 256
- };
- using TextEditorWidgetResolver = std::function<TextEditorWidget *(Core::IEditor *)>;
-
- TextEditorActionHandler(Utils::Id editorId,
- Utils::Id contextId,
- uint optionalActions = None,
- const TextEditorWidgetResolver &resolver = {});
-
- uint optionalActions() const;
- ~TextEditorActionHandler();
-
- void updateCurrentEditor();
- void updateActions();
-
- using Predicate = std::function<bool(Core::IEditor *editor)>;
-
- void setCanUndoCallback(const Predicate &callback);
- void setCanRedoCallback(const Predicate &callback);
-
- using UnhandledCallback = std::function<void(Utils::Id commandId, Core::IEditor *editor)>;
- void setUnhandledCallback(const UnhandledCallback &callback);
-
-private:
- Internal::TextEditorActionHandlerPrivate *d;
-};
-
-} // namespace TextEditor
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index e2115261882..2597deb6bba 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -212,6 +212,8 @@ const char FIND_USAGES[] = "TextEditor.FindUsages";
// moved from CppEditor to TextEditor avoid breaking the setting by using the old key
const char RENAME_SYMBOL[] = "CppEditor.RenameSymbolUnderCursor";
const char OPEN_CALL_HIERARCHY[] = "TextEditor.OpenCallHierarchy";
+const char OPEN_TYPE_HIERARCHY[] = "TextEditor.OpenTypeHierarchy";
+const char TYPE_HIERARCHY_FACTORY_ID[] = "TextEditor.TypeHierarchy";
const char JUMP_TO_FILE_UNDER_CURSOR[] = "TextEditor.JumpToFileUnderCursor";
const char JUMP_TO_FILE_UNDER_CURSOR_IN_NEXT_SPLIT[] = "TextEditor.JumpToFileUnderCursorInNextSplit";
diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp
index 04f11bcbb0b..5db6a17e0d5 100644
--- a/src/plugins/texteditor/texteditorplugin.cpp
+++ b/src/plugins/texteditor/texteditorplugin.cpp
@@ -26,6 +26,7 @@
#include "texteditorsettings.h"
#include "texteditortr.h"
#include "textmark.h"
+#include "typehierarchy.h"
#include "typingsettings.h"
#ifdef WITH_TESTS
@@ -84,6 +85,7 @@ public:
void updateCurrentSelection(const QString &text);
void createStandardContextMenu();
+ void createEditorCommands();
};
void TextEditorPlugin::initialize()
@@ -105,6 +107,7 @@ void TextEditorPlugin::initialize()
setupTextMarkRegistry(this);
setupOutlineFactory();
+ setupTypeHierarchyFactory();
setupLineNumberFilter(); // Goto line functionality for quick open
setupPlainTextEditor();
@@ -120,58 +123,12 @@ void TextEditorPlugin::initialize()
setupMarkdownEditor();
setupJsonEditor();
- Context context(TextEditor::Constants::C_TEXTEDITOR);
-
- // Add shortcut for invoking automatic completion
- Command *command = nullptr;
- ActionBuilder(this, Constants::COMPLETE_THIS)
- .setText(Tr::tr("Trigger Completion"))
- .setContext(context)
- .bindCommand(&command)
- .setDefaultKeySequence(Tr::tr("Meta+Space"), Tr::tr("Ctrl+Space"))
- .addOnTriggered(this, [] {
- if (BaseTextEditor *editor = BaseTextEditor::currentTextEditor())
- editor->editorWidget()->invokeAssist(Completion);
- });
-
- connect(command, &Command::keySequenceChanged, [command] {
- FancyLineEdit::setCompletionShortcut(command->keySequence());
- });
- FancyLineEdit::setCompletionShortcut(command->keySequence());
-
- // Add shortcut for invoking function hint completion
- ActionBuilder(this, Constants::FUNCTION_HINT)
- .setText(Tr::tr("Display Function Hint"))
- .setContext(context)
- .setDefaultKeySequence(Tr::tr("Meta+Shift+D"), Tr::tr("Ctrl+Shift+D"))
- .addOnTriggered(this, [] {
- if (BaseTextEditor *editor = BaseTextEditor::currentTextEditor())
- editor->editorWidget()->invokeAssist(FunctionHint);
- });
-
- // Add shortcut for invoking quick fix options
- ActionBuilder(this, Constants::QUICKFIX_THIS)
- .setText(Tr::tr("Trigger Refactoring Action"))
- .setContext(context)
- .setDefaultKeySequence(Tr::tr("Alt+Return"))
- .addOnTriggered(this, [] {
- if (BaseTextEditor *editor = BaseTextEditor::currentTextEditor())
- editor->editorWidget()->invokeAssist(QuickFix);
- });
-
- ActionBuilder(this, Constants::SHOWCONTEXTMENU)
- .setText(Tr::tr("Show Context Menu"))
- .setContext(context)
- .addOnTriggered(this, [] {
- if (BaseTextEditor *editor = BaseTextEditor::currentTextEditor())
- editor->editorWidget()->showContextMenu();
- });
-
// Add text snippet provider.
SnippetProvider::registerGroup(Constants::TEXT_SNIPPET_GROUP_ID,
Tr::tr("Text", "SnippetProvider"));
createStandardContextMenu();
+ createEditorCommands();
#ifdef WITH_TESTS
addTestCreator(createCodeAssistTests);
@@ -347,6 +304,272 @@ void TextEditorPlugin::createStandardContextMenu()
add(Constants::SWITCH_UTF8BOM, Constants::G_BOM);
}
+void TextEditorPlugin::createEditorCommands()
+{
+ using namespace Core::Constants;
+ // Add shortcut for invoking automatic completion
+ Command *command = nullptr;
+ ActionBuilder(this, Constants::COMPLETE_THIS)
+ .setText(Tr::tr("Trigger Completion"))
+ .bindCommand(&command)
+ .setDefaultKeySequence(Tr::tr("Meta+Space"), Tr::tr("Ctrl+Space"));
+
+ connect(command, &Command::keySequenceChanged, [command] {
+ FancyLineEdit::setCompletionShortcut(command->keySequence());
+ });
+ FancyLineEdit::setCompletionShortcut(command->keySequence());
+
+ // Add shortcut for invoking function hint completion
+ ActionBuilder(this, Constants::FUNCTION_HINT)
+ .setText(Tr::tr("Display Function Hint"))
+ .setDefaultKeySequence(Tr::tr("Meta+Shift+D"), Tr::tr("Ctrl+Shift+D"));
+
+ // Add shortcut for invoking quick fix options
+ ActionBuilder(this, Constants::QUICKFIX_THIS)
+ .setText(Tr::tr("Trigger Refactoring Action"))
+ .setDefaultKeySequence(Tr::tr("Alt+Return"));
+
+ ActionBuilder(this, Constants::SHOWCONTEXTMENU)
+ .setText(Tr::tr("Show Context Menu"));
+
+ ActionBuilder(this, DELETE_LINE).setText(Tr::tr("Delete &Line"));
+ ActionBuilder(this, DELETE_END_OF_LINE).setText(Tr::tr("Delete Line from Cursor On"));
+ ActionBuilder(this, DELETE_END_OF_WORD).setText(Tr::tr("Delete Word from Cursor On"));
+ ActionBuilder(this, DELETE_END_OF_WORD_CAMEL_CASE)
+ .setText(Tr::tr("Delete Word Camel Case from Cursor On"));
+ ActionBuilder(this, DELETE_START_OF_LINE)
+ .setText(Tr::tr("Delete Line up to Cursor"))
+ .setDefaultKeySequence(Tr::tr("Ctrl+Backspace"), {});
+ ActionBuilder(this, DELETE_START_OF_WORD).setText(Tr::tr("Delete Word up to Cursor"));
+ ActionBuilder(this, DELETE_START_OF_WORD_CAMEL_CASE)
+ .setText(Tr::tr("Delete Word Camel Case up to Cursor"));
+ ActionBuilder(this, GOTO_BLOCK_START_WITH_SELECTION)
+ .setText(Tr::tr("Go to Block Start with Selection"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+{")));
+ ActionBuilder(this, GOTO_BLOCK_END_WITH_SELECTION)
+ .setText(Tr::tr("Go to Block End with Selection"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+}")));
+ ActionBuilder(this, MOVE_LINE_UP)
+ .setText(Tr::tr("Move Line Up"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+Up")));
+ ActionBuilder(this, MOVE_LINE_DOWN)
+ .setText(Tr::tr("Move Line Down"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+Down")));
+ ActionBuilder(this, COPY_LINE_UP)
+ .setText(Tr::tr("Copy Line Up"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Alt+Up")));
+ ActionBuilder(this, COPY_LINE_DOWN)
+ .setText(Tr::tr("Copy Line Down"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Alt+Down")));
+ ActionBuilder(this, JOIN_LINES)
+ .setText(Tr::tr("Join Lines"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+J")));
+ ActionBuilder(this, INSERT_LINE_ABOVE)
+ .setText(Tr::tr("Insert Line Above Current Line"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+Return")));
+ ActionBuilder(this, INSERT_LINE_BELOW)
+ .setText(Tr::tr("Insert Line Below Current Line"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Return")));
+ ActionBuilder(this, SWITCH_UTF8BOM).setText(Tr::tr("Toggle UTF-8 BOM"));
+ ActionBuilder(this, INDENT).setText(Tr::tr("Indent"));
+ ActionBuilder(this, UNINDENT).setText(Tr::tr("Unindent"));
+ ActionBuilder(this, FOLLOW_SYMBOL_UNDER_CURSOR)
+ .setText(Tr::tr("Follow Symbol Under Cursor"))
+ .setDefaultKeySequence(QKeySequence(Qt::Key_F2));
+ ActionBuilder(this, FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT)
+ .setText(Tr::tr("Follow Symbol Under Cursor in Next Split"))
+ .setDefaultKeySequence(Tr::tr("Meta+E, F2"), Tr::tr("Ctrl+E, F2"));
+ ActionBuilder(this, FOLLOW_SYMBOL_TO_TYPE)
+ .setText(Tr::tr("Follow Type Under Cursor"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+F2")));
+ ActionBuilder(this, FOLLOW_SYMBOL_TO_TYPE_IN_NEXT_SPLIT)
+ .setText(Tr::tr("Follow Type Under Cursor in Next Split"))
+ .setDefaultKeySequence(Tr::tr("Meta+E, Shift+F2"), Tr::tr("Ctrl+E, Ctrl+Shift+F2"));
+ ActionBuilder(this, FIND_USAGES)
+ .setText(Tr::tr("Find References to Symbol Under Cursor"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+U")));
+ ActionBuilder(this, RENAME_SYMBOL)
+ .setText(Tr::tr("Rename Symbol Under Cursor"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+R")));
+ ActionBuilder(this, JUMP_TO_FILE_UNDER_CURSOR)
+ .setText(Tr::tr("Jump to File Under Cursor"))
+ .setDefaultKeySequence(QKeySequence(Qt::Key_F2));
+ ActionBuilder(this, JUMP_TO_FILE_UNDER_CURSOR_IN_NEXT_SPLIT)
+ .setText(Tr::tr("Jump to File Under Cursor in Next Split"))
+ .setDefaultKeySequence(Tr::tr("Meta+E, F2"), Tr::tr("Ctrl+E, F2"));
+ ActionBuilder(this, OPEN_CALL_HIERARCHY).setText(Tr::tr("Open Call Hierarchy"));
+ ActionBuilder(this, OPEN_TYPE_HIERARCHY)
+ .setText(Tr::tr("Open Type Hierarchy"))
+ .setDefaultKeySequence(Tr::tr("Meta+Shift+T"), Tr::tr("Ctrl+Shift+T"));
+ ActionBuilder(this, VIEW_PAGE_UP)
+ .setText(Tr::tr("Move the View a Page Up and Keep the Cursor Position"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+PgUp")));
+ ActionBuilder(this, VIEW_PAGE_DOWN)
+ .setText(Tr::tr("Move the View a Page Down and Keep the Cursor Position"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+PgDown")));
+ ActionBuilder(this, VIEW_LINE_UP)
+ .setText(Tr::tr("Move the View a Line Up and Keep the Cursor Position"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Up")));
+ ActionBuilder(this, VIEW_LINE_DOWN)
+ .setText(Tr::tr("Move the View a Line Down and Keep the Cursor Position"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Down")));
+
+ ActionManager::actionContainer(M_EDIT);
+ ActionBuilder(this, SELECT_ENCODING)
+ .setText(Tr::tr("Select Encoding..."))
+ .addToContainer(M_EDIT, G_EDIT_OTHER);
+ ActionBuilder(this, CIRCULAR_PASTE)
+ .setText(Tr::tr("Paste from Clipboard History"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+V")))
+ .addToContainer(M_EDIT, G_EDIT_COPYPASTE);
+ ActionBuilder(this, NO_FORMAT_PASTE)
+ .setText(Tr::tr("Paste Without Formatting"))
+ .setDefaultKeySequence(Tr::tr("Ctrl+Alt+Shift+V"), QString())
+ .addToContainer(M_EDIT, G_EDIT_COPYPASTE);
+
+ ActionManager::actionContainer(M_EDIT_ADVANCED);
+ ActionBuilder(this, AUTO_INDENT_SELECTION)
+ .setText(Tr::tr("Auto-&indent Selection"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+I")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT);
+ ActionBuilder(this, AUTO_FORMAT_SELECTION)
+ .setText(Tr::tr("Auto-&format Selection"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+;")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT);
+ ActionBuilder(this, REWRAP_PARAGRAPH)
+ .setText(Tr::tr("&Rewrap Paragraph"))
+ .setDefaultKeySequence(Tr::tr("Meta+E, R"), Tr::tr("Ctrl+E, R"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT);
+ ActionBuilder(this, VISUALIZE_WHITESPACE)
+ .setText(Tr::tr("&Visualize Whitespace"))
+ .setDefaultKeySequence(Tr::tr("Meta+E, Meta+V"), Tr::tr("Ctrl+E, Ctrl+V"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT);
+ ActionBuilder(this, CLEAN_WHITESPACE)
+ .setText(Tr::tr("Clean Whitespace"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT);
+ ActionBuilder(this, TEXT_WRAPPING)
+ .setText(Tr::tr("Enable Text &Wrapping"))
+ .setDefaultKeySequence(Tr::tr("Meta+E, Meta+W"), Tr::tr("Ctrl+E, Ctrl+W"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT)
+ .setCheckable(true);
+ ActionBuilder(this, UN_COMMENT_SELECTION)
+ .setText(Tr::tr("Toggle Comment &Selection"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+/")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FORMAT);
+ ActionBuilder(this, CUT_LINE)
+ .setText(Tr::tr("Cut &Line"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Shift+Del")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, COPY_LINE)
+ .setText(Tr::tr("Copy &Line"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Ins")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, COPY_WITH_HTML)
+ .setText(Tr::tr("Copy With Highlighting"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, ADD_CURSORS_TO_LINE_ENDS)
+ .setText(Tr::tr("Create Cursors at Selected Line Ends"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Alt+Shift+I")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, ADD_SELECT_NEXT_FIND_MATCH)
+ .setText(Tr::tr("Add Next Occurrence to Selection"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+D")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, DUPLICATE_SELECTION)
+ .setText(Tr::tr("&Duplicate Selection"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, DUPLICATE_SELECTION_AND_COMMENT)
+ .setText(Tr::tr("&Duplicate Selection and Comment"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, UPPERCASE_SELECTION)
+ .setText(Tr::tr("Uppercase Selection"))
+ .setDefaultKeySequence(Tr::tr("Meta+Shift+U"), Tr::tr("Alt+Shift+U"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, LOWERCASE_SELECTION)
+ .setText(Tr::tr("Lowercase Selection"))
+ .setDefaultKeySequence(Tr::tr("Meta+U"), Tr::tr("Alt+U"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, SORT_LINES)
+ .setText(Tr::tr("Sort Lines"))
+ .setDefaultKeySequence(Tr::tr("Meta+Shift+S"), Tr::tr("Alt+Shift+S"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_TEXT);
+ ActionBuilder(this, FOLD)
+ .setText(Tr::tr("Fold"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+<")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_COLLAPSING);
+ ActionBuilder(this, UNFOLD)
+ .setText(Tr::tr("Unfold"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+>")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_COLLAPSING);
+ ActionBuilder(this, UNFOLD_ALL)
+ .setText(Tr::tr("Toggle &Fold All"))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_COLLAPSING);
+ ActionBuilder(this, INCREASE_FONT_SIZE)
+ .setText(Tr::tr("Increase Font Size"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl++")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FONT);
+ ActionBuilder(this, DECREASE_FONT_SIZE)
+ .setText(Tr::tr("Decrease Font Size"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+-")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FONT);
+ ActionBuilder(this, RESET_FONT_SIZE)
+ .setText(Tr::tr("Reset Font Size"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+0")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_FONT);
+ ActionBuilder(this, GOTO_BLOCK_START)
+ .setText(Tr::tr("Go to Block Start"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+[")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_BLOCKS);
+ ActionBuilder(this, GOTO_BLOCK_END)
+ .setText(Tr::tr("Go to Block End"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+]")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_BLOCKS);
+ ActionBuilder(this, SELECT_BLOCK_UP)
+ .setText(Tr::tr("Select Block Up"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+U")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_BLOCKS);
+ ActionBuilder(this, SELECT_BLOCK_DOWN)
+ .setText(Tr::tr("Select Block Down"))
+ .setDefaultKeySequence(QKeySequence(Tr::tr("Ctrl+Shift+Alt+U")))
+ .addToContainer(M_EDIT_ADVANCED, G_EDIT_BLOCKS);
+ ActionBuilder(this, SELECT_WORD_UNDER_CURSOR).setText(Tr::tr("Select Word Under Cursor"));
+
+ ActionBuilder(this, GOTO_DOCUMENT_START).setText(Tr::tr("Go to Document Start"));
+ ActionBuilder(this, GOTO_DOCUMENT_END).setText(Tr::tr("Go to Document End"));
+ ActionBuilder(this, GOTO_LINE_START).setText(Tr::tr("Go to Line Start"));
+ ActionBuilder(this, GOTO_LINE_END).setText(Tr::tr("Go to Line End"));
+ ActionBuilder(this, GOTO_NEXT_LINE).setText(Tr::tr("Go to Next Line"));
+ ActionBuilder(this, GOTO_PREVIOUS_LINE).setText(Tr::tr("Go to Previous Line"));
+ ActionBuilder(this, GOTO_PREVIOUS_CHARACTER).setText(Tr::tr("Go to Previous Character"));
+ ActionBuilder(this, GOTO_NEXT_CHARACTER).setText(Tr::tr("Go to Next Character"));
+ ActionBuilder(this, GOTO_PREVIOUS_WORD).setText(Tr::tr("Go to Previous Word"));
+ ActionBuilder(this, GOTO_NEXT_WORD).setText(Tr::tr("Go to Next Word"));
+ ActionBuilder(this, GOTO_PREVIOUS_WORD_CAMEL_CASE)
+ .setText(Tr::tr("Go to Previous Word (Camel Case)"));
+ ActionBuilder(this, GOTO_NEXT_WORD_CAMEL_CASE).setText(Tr::tr("Go to Next Word (Camel Case)"));
+
+ ActionBuilder(this, GOTO_LINE_START_WITH_SELECTION)
+ .setText(Tr::tr("Go to Line Start with Selection"));
+ ActionBuilder(this, GOTO_LINE_END_WITH_SELECTION)
+ .setText(Tr::tr("Go to Line End with Selection"));
+ ActionBuilder(this, GOTO_NEXT_LINE_WITH_SELECTION)
+ .setText(Tr::tr("Go to Next Line with Selection"));
+ ActionBuilder(this, GOTO_PREVIOUS_LINE_WITH_SELECTION)
+ .setText(Tr::tr("Go to Previous Line with Selection"));
+ ActionBuilder(this, GOTO_PREVIOUS_CHARACTER_WITH_SELECTION)
+ .setText(Tr::tr("Go to Previous Character with Selection"));
+ ActionBuilder(this, GOTO_NEXT_CHARACTER_WITH_SELECTION)
+ .setText(Tr::tr("Go to Next Character with Selection"));
+ ActionBuilder(this, GOTO_PREVIOUS_WORD_WITH_SELECTION)
+ .setText(Tr::tr("Go to Previous Word with Selection"));
+ ActionBuilder(this, GOTO_NEXT_WORD_WITH_SELECTION)
+ .setText(Tr::tr("Go to Next Word with Selection"));
+ ActionBuilder(this, GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION)
+ .setText(Tr::tr("Go to Previous Word (Camel Case) with Selection"));
+ ActionBuilder(this, GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION)
+ .setText(Tr::tr("Go to Next Word (Camel Case) with Selection"));
+}
+
} // namespace TextEditor::Internal
#include "texteditorplugin.moc"
diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp
index 1739cf61b9e..459d0ca27c1 100644
--- a/src/plugins/texteditor/textmark.cpp
+++ b/src/plugins/texteditor/textmark.cpp
@@ -371,7 +371,7 @@ bool TextMark::addToolTipContent(QLayout *target) const
QColor TextMark::annotationColor() const
{
if (m_color.has_value())
- return Utils::creatorTheme()->color(*m_color).toHsl();
+ return Utils::creatorColor(*m_color).toHsl();
return {};
}
diff --git a/src/plugins/texteditor/typehierarchy.cpp b/src/plugins/texteditor/typehierarchy.cpp
new file mode 100644
index 00000000000..53924a2b9d6
--- /dev/null
+++ b/src/plugins/texteditor/typehierarchy.cpp
@@ -0,0 +1,136 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "typehierarchy.h"
+
+#include "texteditorconstants.h"
+#include "texteditortr.h"
+
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/inavigationwidgetfactory.h>
+
+#include <utils/utilsicons.h>
+
+#include <QLabel>
+#include <QPalette>
+#include <QStackedWidget>
+#include <QToolButton>
+
+using namespace Utils;
+
+namespace TextEditor {
+namespace Internal {
+
+static QList<TypeHierarchyWidgetFactory *> g_widgetFactories;
+
+class TypeHierarchyFactory : public Core::INavigationWidgetFactory
+{
+public:
+ TypeHierarchyFactory()
+ {
+ setDisplayName(Tr::tr("Type Hierarchy"));
+ setPriority(649);
+ setId(Constants::TYPE_HIERARCHY_FACTORY_ID);
+ }
+
+private:
+ Core::NavigationView createWidget() override;
+};
+
+class TypeHierarchyWidgetStack : public QStackedWidget
+{
+ Q_OBJECT
+
+public:
+ TypeHierarchyWidgetStack();
+
+ void reload();
+};
+
+static TypeHierarchyFactory &typeHierarchyFactory()
+{
+ static TypeHierarchyFactory theFactory;
+ return theFactory;
+}
+
+void setupTypeHierarchyFactory()
+{
+ (void) typeHierarchyFactory();
+}
+
+TypeHierarchyWidgetStack::TypeHierarchyWidgetStack()
+{
+ QLabel *label = new QLabel(Tr::tr("No type hierarchy available"), this);
+ label->setAlignment(Qt::AlignCenter);
+
+ label->setAutoFillBackground(true);
+ label->setBackgroundRole(QPalette::Base);
+
+ addWidget(label);
+ reload();
+}
+
+void TypeHierarchyWidgetStack::reload()
+{
+ const auto editor = Core::EditorManager::currentEditor();
+ TypeHierarchyWidget *newWidget = nullptr;
+
+ if (editor) {
+ for (TypeHierarchyWidgetFactory * const widgetFactory : std::as_const(g_widgetFactories)) {
+ if ((newWidget = widgetFactory->createWidget(editor)))
+ break;
+ }
+ }
+
+ QWidget * const current = currentWidget();
+ if (current) {
+ removeWidget(current);
+ current->deleteLater();
+ }
+ if (newWidget) {
+ addWidget(newWidget);
+ setCurrentWidget(newWidget);
+ setFocusProxy(newWidget);
+ newWidget->reload();
+ }
+}
+
+Core::NavigationView TypeHierarchyFactory::createWidget()
+{
+ const auto placeholder = new TypeHierarchyWidgetStack;
+ const auto reloadButton = new QToolButton;
+ reloadButton->setIcon(Icons::RELOAD_TOOLBAR.icon());
+ reloadButton->setToolTip(Tr::tr("Reloads the type hierarchy for the symbol under the cursor."));
+ connect(reloadButton, &QToolButton::clicked, placeholder, &TypeHierarchyWidgetStack::reload);
+ return {placeholder, {reloadButton}};
+}
+
+void updateTypeHierarchy(QWidget *widget)
+{
+ if (const auto w = qobject_cast<TypeHierarchyWidgetStack *>(widget))
+ w->reload();
+}
+
+} // namespace Internal
+
+TypeHierarchyWidgetFactory::TypeHierarchyWidgetFactory()
+{
+ Internal::g_widgetFactories.append(this);
+}
+
+TypeHierarchyWidgetFactory::~TypeHierarchyWidgetFactory()
+{
+ Internal::g_widgetFactories.removeOne(this);
+}
+
+void openTypeHierarchy()
+{
+ if (const auto action = Core::ActionManager::command(Constants::OPEN_TYPE_HIERARCHY)->action())
+ action->trigger();
+}
+
+} // namespace TextEditor
+
+#include <typehierarchy.moc>
diff --git a/src/plugins/texteditor/typehierarchy.h b/src/plugins/texteditor/typehierarchy.h
new file mode 100644
index 00000000000..ee7c1fa1a7b
--- /dev/null
+++ b/src/plugins/texteditor/typehierarchy.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <texteditor/texteditor_global.h>
+
+#include <QWidget>
+
+namespace Core { class IEditor; }
+
+namespace TextEditor {
+namespace Internal {
+void setupTypeHierarchyFactory();
+void updateTypeHierarchy(QWidget *widget);
+}
+
+class TEXTEDITOR_EXPORT TypeHierarchyWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ virtual void reload() = 0;
+};
+
+class TEXTEDITOR_EXPORT TypeHierarchyWidgetFactory : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual TypeHierarchyWidget *createWidget(Core::IEditor *editor) = 0;
+
+protected:
+ TypeHierarchyWidgetFactory();
+ ~TypeHierarchyWidgetFactory() override;
+};
+
+TEXTEDITOR_EXPORT void openTypeHierarchy();
+
+} // namespace TextEditor