TextEditor: add option to remember highlighter definition

Add a button to the multiple definition found info that saves the
definition of the current highlighter for the open document.

Change-Id: I04b1b7571a864d781747547a1d315ec25bb6b5a1
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
David Schulz
2019-02-07 13:40:39 +01:00
parent f6c276daf0
commit 8a0f7bcfd5
7 changed files with 145 additions and 13 deletions

View File

@@ -43,6 +43,10 @@
using namespace TextEditor; using namespace TextEditor;
static const char kDefinitionForMimeType[] = "definitionForMimeType";
static const char kDefinitionForExtension[] = "definitionForExtension";
static const char kDefinitionForFilePath[] = "definitionForFilePath";
KSyntaxHighlighting::Repository *highlightRepository() KSyntaxHighlighting::Repository *highlightRepository()
{ {
static KSyntaxHighlighting::Repository *repository = nullptr; static KSyntaxHighlighting::Repository *repository = nullptr;
@@ -107,18 +111,24 @@ Highlighter::Definition Highlighter::definitionForDocument(const TextDocument *d
if (mimeType.isValid()) if (mimeType.isValid())
definition = Highlighter::definitionForMimeType(mimeType.name()); definition = Highlighter::definitionForMimeType(mimeType.name());
if (!definition.isValid()) if (!definition.isValid())
definition = Highlighter::definitionForFileName(document->filePath().fileName()); definition = Highlighter::definitionForFilePath(document->filePath());
return definition; return definition;
} }
Highlighter::Definition Highlighter::definitionForMimeType(const QString &mimeType) Highlighter::Definition Highlighter::definitionForMimeType(const QString &mimeType)
{ {
const Definitions definitions = definitionsForMimeType(mimeType);
if (definitions.size() == 1)
return definitions.first();
return highlightRepository()->definitionForMimeType(mimeType); return highlightRepository()->definitionForMimeType(mimeType);
} }
Highlighter::Definition Highlighter::definitionForFileName(const QString &fileName) Highlighter::Definition Highlighter::definitionForFilePath(const Utils::FileName &fileName)
{ {
return highlightRepository()->definitionForFileName(fileName); const Definitions definitions = definitionsForFileName(fileName);
if (definitions.size() == 1)
return definitions.first();
return highlightRepository()->definitionForFileName(fileName.fileName());
} }
Highlighter::Definition Highlighter::definitionForName(const QString &name) Highlighter::Definition Highlighter::definitionForName(const QString &name)
@@ -133,18 +143,88 @@ Highlighter::Definitions Highlighter::definitionsForDocument(const TextDocument
if (mimeType.isValid()) if (mimeType.isValid())
definitions = Highlighter::definitionsForMimeType(mimeType.name()); definitions = Highlighter::definitionsForMimeType(mimeType.name());
if (definitions.isEmpty()) if (definitions.isEmpty())
definitions = Highlighter::definitionsForFileName(document->filePath().fileName()); definitions = Highlighter::definitionsForFileName(document->filePath());
return definitions; return definitions;
} }
static Highlighter::Definition definitionForSetting(const QString &settingsKey,
const QString &mapKey)
{
QSettings *settings = Core::ICore::settings();
settings->beginGroup(Constants::HIGHLIGHTER_SETTINGS_CATEGORY);
const QString &definitionName = settings->value(settingsKey).toMap().value(mapKey).toString();
settings->endGroup();
return Highlighter::definitionForName(definitionName);
}
Highlighter::Definitions Highlighter::definitionsForMimeType(const QString &mimeType) Highlighter::Definitions Highlighter::definitionsForMimeType(const QString &mimeType)
{ {
return highlightRepository()->definitionsForMimeType(mimeType).toList(); Definitions definitions = highlightRepository()->definitionsForMimeType(mimeType).toList();
if (definitions.size() > 1) {
const Definition &rememberedDefinition = definitionForSetting(kDefinitionForMimeType,
mimeType);
if (rememberedDefinition.isValid() && definitions.contains(rememberedDefinition))
definitions = {rememberedDefinition};
}
return definitions;
} }
Highlighter::Definitions Highlighter::definitionsForFileName(const QString &fileName) Highlighter::Definitions Highlighter::definitionsForFileName(const Utils::FileName &fileName)
{ {
return highlightRepository()->definitionsForFileName(fileName).toList(); Definitions definitions
= highlightRepository()->definitionsForFileName(fileName.fileName()).toList();
if (definitions.size() > 1) {
const QString &fileExtension = fileName.toFileInfo().completeSuffix();
const Definition &rememberedDefinition
= fileExtension.isEmpty()
? definitionForSetting(kDefinitionForFilePath,
fileName.toFileInfo().canonicalFilePath())
: definitionForSetting(kDefinitionForExtension, fileExtension);
if (rememberedDefinition.isValid() && definitions.contains(rememberedDefinition))
definitions = {rememberedDefinition};
}
return definitions;
}
void Highlighter::rememberDefintionForDocument(const Highlighter::Definition &definition,
const TextDocument *document)
{
if (!definition.isValid())
return;
const QString &mimeType = document->mimeType();
const QString &fileExtension = document->filePath().toFileInfo().completeSuffix();
const QString &path = document->filePath().toFileInfo().canonicalFilePath();
QSettings *settings = Core::ICore::settings();
settings->beginGroup(Constants::HIGHLIGHTER_SETTINGS_CATEGORY);
if (!mimeType.isEmpty()) {
const QString id(kDefinitionForMimeType);
QMap<QString, QVariant> map = settings->value(id).toMap();
map.insert(mimeType, definition.name());
settings->setValue(id, map);
} else if (!fileExtension.isEmpty()) {
const QString id(kDefinitionForExtension);
QMap<QString, QVariant> map = settings->value(id).toMap();
map.insert(fileExtension, definition.name());
settings->setValue(id, map);
} else if (!path.isEmpty()) {
const QString id(kDefinitionForFilePath);
QMap<QString, QVariant> map = settings->value(id).toMap();
map.insert(document->filePath().toFileInfo().absoluteFilePath(), definition.name());
settings->setValue(id, map);
}
settings->endGroup();
}
void Highlighter::clearDefintionForDocumentCache()
{
QSettings *settings = Core::ICore::settings();
settings->beginGroup(Constants::HIGHLIGHTER_SETTINGS_CATEGORY);
settings->remove(kDefinitionForMimeType);
settings->remove(kDefinitionForExtension);
settings->remove(kDefinitionForFilePath);
settings->endGroup();
} }
void Highlighter::addCustomHighlighterPath(const Utils::FileName &path) void Highlighter::addCustomHighlighterPath(const Utils::FileName &path)

View File

@@ -38,6 +38,8 @@ class TextDocument;
class Highlighter : public SyntaxHighlighter, public KSyntaxHighlighting::AbstractHighlighter class Highlighter : public SyntaxHighlighter, public KSyntaxHighlighting::AbstractHighlighter
{ {
Q_OBJECT
Q_INTERFACES(KSyntaxHighlighting::AbstractHighlighter)
public: public:
using Definition = KSyntaxHighlighting::Definition; using Definition = KSyntaxHighlighting::Definition;
using Definitions = QList<Definition>; using Definitions = QList<Definition>;
@@ -45,12 +47,16 @@ public:
static Definition definitionForDocument(const TextDocument *document); static Definition definitionForDocument(const TextDocument *document);
static Definition definitionForMimeType(const QString &mimeType); static Definition definitionForMimeType(const QString &mimeType);
static Definition definitionForFileName(const QString &fileName); static Definition definitionForFilePath(const Utils::FileName &fileName);
static Definition definitionForName(const QString &name); static Definition definitionForName(const QString &name);
static Definitions definitionsForDocument(const TextDocument *document); static Definitions definitionsForDocument(const TextDocument *document);
static Definitions definitionsForMimeType(const QString &mimeType); static Definitions definitionsForMimeType(const QString &mimeType);
static Definitions definitionsForFileName(const QString &fileName); static Definitions definitionsForFileName(const Utils::FileName &fileName);
static void rememberDefintionForDocument(const Definition &definition,
const TextDocument *document);
static void clearDefintionForDocumentCache();
static void addCustomHighlighterPath(const Utils::FileName &path); static void addCustomHighlighterPath(const Utils::FileName &path);
static void updateDefinitions(std::function<void()> callback = nullptr); static void updateDefinitions(std::function<void()> callback = nullptr);

View File

@@ -25,6 +25,8 @@
#include "highlightersettings.h" #include "highlightersettings.h"
#include "texteditorconstants.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/synchronousprocess.h> #include <utils/synchronousprocess.h>
@@ -97,7 +99,6 @@ namespace {
static const QLatin1String kDefinitionFilesPath("UserDefinitionFilesPath"); static const QLatin1String kDefinitionFilesPath("UserDefinitionFilesPath");
static const QLatin1String kIgnoredFilesPatterns("IgnoredFilesPatterns"); static const QLatin1String kIgnoredFilesPatterns("IgnoredFilesPatterns");
static const QLatin1String kGroupPostfix("HighlighterSettings");
QString groupSpecifier(const QString &postFix, const QString &category) QString groupSpecifier(const QString &postFix, const QString &category)
{ {
@@ -113,7 +114,7 @@ using namespace Internal;
void HighlighterSettings::toSettings(const QString &category, QSettings *s) const void HighlighterSettings::toSettings(const QString &category, QSettings *s) const
{ {
const QString &group = groupSpecifier(kGroupPostfix, category); const QString &group = groupSpecifier(Constants::HIGHLIGHTER_SETTINGS_CATEGORY, category);
s->beginGroup(group); s->beginGroup(group);
s->setValue(kDefinitionFilesPath, m_definitionFilesPath); s->setValue(kDefinitionFilesPath, m_definitionFilesPath);
s->setValue(kIgnoredFilesPatterns, ignoredFilesPatterns()); s->setValue(kIgnoredFilesPatterns, ignoredFilesPatterns());
@@ -122,7 +123,7 @@ void HighlighterSettings::toSettings(const QString &category, QSettings *s) cons
void HighlighterSettings::fromSettings(const QString &category, QSettings *s) void HighlighterSettings::fromSettings(const QString &category, QSettings *s)
{ {
const QString &group = groupSpecifier(kGroupPostfix, category); const QString &group = groupSpecifier(Constants::HIGHLIGHTER_SETTINGS_CATEGORY, category);
s->beginGroup(group); s->beginGroup(group);
m_definitionFilesPath = s->value(kDefinitionFilesPath, QString()).toString(); m_definitionFilesPath = s->value(kDefinitionFilesPath, QString()).toString();
if (!s->contains(kDefinitionFilesPath)) if (!s->contains(kDefinitionFilesPath))

View File

@@ -112,6 +112,9 @@ QWidget *HighlighterSettingsPage::widget()
label->setText(tr("Update finished")); label->setText(tr("Update finished"));
}); });
}); });
connect(m_d->m_page->resetCache, &QPushButton::clicked, []() {
Highlighter::clearDefintionForDocumentCache();
});
settingsToUI(); settingsToUI();
} }

View File

@@ -110,6 +110,30 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="resetCache">
<property name="text">
<string>Reset Remembered Definitions</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@@ -613,6 +613,7 @@ public:
void reconfigure(); void reconfigure();
void updateSyntaxInfoBar(const Highlighter::Definitions &definitions, const QString &fileName); void updateSyntaxInfoBar(const Highlighter::Definitions &definitions, const QString &fileName);
void configureGenericHighlighter(const KSyntaxHighlighting::Definition &definition); void configureGenericHighlighter(const KSyntaxHighlighting::Definition &definition);
void rememberCurrentSyntaxDefinition();
public: public:
TextEditorWidget *q; TextEditorWidget *q;
@@ -3306,6 +3307,11 @@ void TextEditorWidgetPrivate::updateSyntaxInfoBar(const Highlighter::Definitions
this->configureGenericHighlighter(Highlighter::definitionForName(definition)); this->configureGenericHighlighter(Highlighter::definitionForName(definition));
}); });
info.setCustomButtonInfo(BaseTextEditor::tr("Remember My Choice"), [multiple, this]() {
m_document->infoBar()->removeInfo(multiple);
rememberCurrentSyntaxDefinition();
});
infoBar->removeInfo(missing); infoBar->removeInfo(missing);
infoBar->addInfo(info); infoBar->addInfo(info);
} else { } else {
@@ -3333,6 +3339,16 @@ void TextEditorWidgetPrivate::configureGenericHighlighter(
m_document->setFontSettings(TextEditorSettings::fontSettings()); m_document->setFontSettings(TextEditorSettings::fontSettings());
} }
void TextEditorWidgetPrivate::rememberCurrentSyntaxDefinition()
{
auto highlighter = qobject_cast<Highlighter *>(m_document->syntaxHighlighter());
if (!highlighter)
return;
const Highlighter::Definition &definition = highlighter->definition();
if (definition.isValid())
Highlighter::rememberDefintionForDocument(definition, m_document.data());
}
bool TextEditorWidget::codeFoldingVisible() const bool TextEditorWidget::codeFoldingVisible() const
{ {
return d->m_codeFoldingVisible; return d->m_codeFoldingVisible;
@@ -8543,7 +8559,7 @@ QString TextEditorWidget::textAt(int from, int to) const
void TextEditorWidget::configureGenericHighlighter() void TextEditorWidget::configureGenericHighlighter()
{ {
const Highlighter::Definitions definitions = Highlighter::definitionsForDocument(textDocument()); Highlighter::Definitions definitions = Highlighter::definitionsForDocument(textDocument());
d->configureGenericHighlighter(definitions.isEmpty() ? Highlighter::Definition() d->configureGenericHighlighter(definitions.isEmpty() ? Highlighter::Definition()
: definitions.first()); : definitions.first());
d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName()); d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName());

View File

@@ -214,6 +214,8 @@ const char TEXT_EDITOR_DISPLAY_SETTINGS[] = "D.DisplaySettings";
const char TEXT_EDITOR_HIGHLIGHTER_SETTINGS[] = "E.HighlighterSettings"; const char TEXT_EDITOR_HIGHLIGHTER_SETTINGS[] = "E.HighlighterSettings";
const char TEXT_EDITOR_SNIPPETS_SETTINGS[] = "F.SnippetsSettings"; const char TEXT_EDITOR_SNIPPETS_SETTINGS[] = "F.SnippetsSettings";
const char HIGHLIGHTER_SETTINGS_CATEGORY[] = "HighlighterSettings";
const char SNIPPET_EDITOR_ID[] = "TextEditor.SnippetEditor"; const char SNIPPET_EDITOR_ID[] = "TextEditor.SnippetEditor";
const char TEXT_SNIPPET_GROUP_ID[] = "Text"; const char TEXT_SNIPPET_GROUP_ID[] = "Text";