Commit 9704844e authored by Leandro Melo's avatar Leandro Melo
Browse files

Generic highlighter: Changes in settings. Now there's a fallbacklocation.

Task-number: QTCREATORBUG-1886
parent 470a5499
Place syntax definitions files inside this directory.
Files can be downloaded at http://kate-editor.org/downloads/syntax_highlighting?kateversion=3.2
Instructions on how to write your own definitions can be found at http://kate-editor.org/article/writing_a_kate_highlighting_xml_file
......@@ -32,8 +32,7 @@ DATA_DIRS = \
gdbmacros \
qmldesigner \
qmlicons \
qml-type-descriptions \
generic-highlighter
qml-type-descriptions
!isEmpty(copydata) {
......
......@@ -79,10 +79,6 @@ QString findDefinitionsLocation()
}
#endif
if (definitionsLocation.isEmpty())
definitionsLocation = Core::ICore::instance()->resourcePath() +
QLatin1String("/generic-highlighter");
return definitionsLocation;
}
......@@ -91,8 +87,10 @@ QString findDefinitionsLocation()
namespace {
static const QLatin1String kDefinitionFilesPath("DefinitionFilesPath");
static const QLatin1String kDefinitionFilesPath("UserDefinitionFilesPath");
static const QLatin1String kFallbackDefinitionFilesPath("FallbackDefinitionFilesPath");
static const QLatin1String kAlertWhenDefinitionIsNotFound("AlertWhenDefinitionsIsNotFound");
static const QLatin1String kUseFallbackLocation("UseFallbackLocation");
static const QLatin1String kIgnoredFilesPatterns("IgnoredFilesPatterns");
static const QLatin1String kGroupPostfix("HighlighterSettings");
......@@ -108,7 +106,8 @@ QString groupSpecifier(const QString &postFix, const QString &category)
using namespace TextEditor;
using namespace Internal;
HighlighterSettings::HighlighterSettings() : m_alertWhenNoDefinition(true)
HighlighterSettings::HighlighterSettings() :
m_alertWhenNoDefinition(true), m_useFallbackLocation(true)
{}
void HighlighterSettings::toSettings(const QString &category, QSettings *s) const
......@@ -116,7 +115,9 @@ void HighlighterSettings::toSettings(const QString &category, QSettings *s) cons
const QString &group = groupSpecifier(kGroupPostfix, category);
s->beginGroup(group);
s->setValue(kDefinitionFilesPath, m_definitionFilesPath);
s->setValue(kFallbackDefinitionFilesPath, m_fallbackDefinitionFilesPath);
s->setValue(kAlertWhenDefinitionIsNotFound, m_alertWhenNoDefinition);
s->setValue(kUseFallbackLocation, m_useFallbackLocation);
s->setValue(kIgnoredFilesPatterns, ignoredFilesPatterns());
s->endGroup();
}
......@@ -125,11 +126,13 @@ void HighlighterSettings::fromSettings(const QString &category, QSettings *s)
{
const QString &group = groupSpecifier(kGroupPostfix, category);
s->beginGroup(group);
if (!s->contains(kDefinitionFilesPath))
m_definitionFilesPath = findDefinitionsLocation();
m_definitionFilesPath = s->value(kDefinitionFilesPath, QString()).toString();
if (!s->contains(kFallbackDefinitionFilesPath))
m_fallbackDefinitionFilesPath = findDefinitionsLocation();
else
m_definitionFilesPath = s->value(kDefinitionFilesPath, QString()).toString();
m_fallbackDefinitionFilesPath = s->value(kFallbackDefinitionFilesPath,QString()).toString();
m_alertWhenNoDefinition = s->value(kAlertWhenDefinitionIsNotFound, true).toBool();
m_useFallbackLocation = s->value(kUseFallbackLocation, true).toBool();
if (!s->contains(kIgnoredFilesPatterns))
assignInitialIgnoredPatterns();
else
......@@ -172,7 +175,9 @@ bool HighlighterSettings::isIgnoredFilePattern(const QString &fileName) const
bool HighlighterSettings::equals(const HighlighterSettings &highlighterSettings) const
{
return m_definitionFilesPath == highlighterSettings.m_definitionFilesPath &&
m_fallbackDefinitionFilesPath == highlighterSettings.m_fallbackDefinitionFilesPath &&
m_alertWhenNoDefinition == highlighterSettings.m_alertWhenNoDefinition &&
m_useFallbackLocation == highlighterSettings.m_useFallbackLocation &&
m_ignoredFiles == highlighterSettings.m_ignoredFiles;
}
......
......@@ -52,9 +52,15 @@ public:
void setDefinitionFilesPath(const QString &path) { m_definitionFilesPath = path; }
const QString &definitionFilesPath() const { return m_definitionFilesPath; }
void setFallbackDefinitionFilesPath(const QString &path){ m_fallbackDefinitionFilesPath = path;}
const QString &fallbackDefinitionFilesPath() const { return m_fallbackDefinitionFilesPath; }
void setAlertWhenNoDefinition(const bool alert) { m_alertWhenNoDefinition = alert; }
bool alertWhenNoDefinition() const { return m_alertWhenNoDefinition; }
void setUseFallbackLocation(const bool use) { m_useFallbackLocation = use; }
bool useFallbackLocation() const { return m_useFallbackLocation; }
void setIgnoredFilesPatterns(const QString &patterns);
QString ignoredFilesPatterns() const;
bool isIgnoredFilePattern(const QString &fileName) const;
......@@ -68,7 +74,9 @@ private:
QStringList listFromExpressions() const;
bool m_alertWhenNoDefinition;
bool m_useFallbackLocation;
QString m_definitionFilesPath;
QString m_fallbackDefinitionFilesPath;
QList<QRegExp> m_ignoredFiles;
};
......
......@@ -94,6 +94,11 @@ QWidget *HighlighterSettingsPage::createPage(QWidget *parent)
QWidget *w = new QWidget(parent);
m_d->m_page.setupUi(w);
m_d->m_page.definitionFilesPath->setExpectedKind(Utils::PathChooser::Directory);
m_d->m_page.definitionFilesPath->addButton(tr("Manage"), this,
SLOT(requestAvailableDefinitionsMetaData()));
m_d->m_page.fallbackDefinitionFilesPath->setExpectedKind(Utils::PathChooser::Directory);
m_d->m_page.fallbackDefinitionFilesPath->addButton(tr("Autodetect"), this,
SLOT(resetDefinitionsLocation()));
settingsToUI();
......@@ -101,12 +106,12 @@ QWidget *HighlighterSettingsPage::createPage(QWidget *parent)
QTextStream(&m_d->m_searchKeywords) << m_d->m_page.definitionFilesGroupBox->title()
<< m_d->m_page.locationLabel->text()
<< m_d->m_page.alertWhenNoDefinition->text()
<< m_d->m_page.useFallbackLocation->text()
<< m_d->m_page.ignoreLabel->text();
}
connect(m_d->m_page.resetButton, SIGNAL(clicked()), this, SLOT(resetDefinitionsLocation()));
connect(m_d->m_page.manageDefinitionsButton, SIGNAL(clicked()),
this, SLOT(requestAvailableDefinitionsMetaData()));
connect(m_d->m_page.useFallbackLocation, SIGNAL(clicked(bool)),
this, SLOT(useFallbackLocation(bool)));
connect(w, SIGNAL(destroyed()), this, SLOT(ignoreDownloadReply()));
return w;
......@@ -131,11 +136,17 @@ const HighlighterSettings &HighlighterSettingsPage::highlighterSettings() const
void HighlighterSettingsPage::settingsFromUI()
{
bool locationChanged = false;
if (m_d->m_settings.definitionFilesPath() != m_d->m_page.definitionFilesPath->path())
if (m_d->m_settings.definitionFilesPath() != m_d->m_page.definitionFilesPath->path() ||
m_d->m_settings.fallbackDefinitionFilesPath() !=
m_d->m_page.fallbackDefinitionFilesPath->path() ||
m_d->m_settings.useFallbackLocation() != m_d->m_page.useFallbackLocation->isChecked()) {
locationChanged = true;
}
m_d->m_settings.setDefinitionFilesPath(m_d->m_page.definitionFilesPath->path());
m_d->m_settings.setFallbackDefinitionFilesPath(m_d->m_page.fallbackDefinitionFilesPath->path());
m_d->m_settings.setAlertWhenNoDefinition(m_d->m_page.alertWhenNoDefinition->isChecked());
m_d->m_settings.setUseFallbackLocation(m_d->m_page.useFallbackLocation->isChecked());
m_d->m_settings.setIgnoredFilesPatterns(m_d->m_page.ignoreEdit->text());
if (QSettings *s = Core::ICore::instance()->settings())
m_d->m_settings.toSettings(m_d->m_settingsPrefix, s);
......@@ -147,18 +158,27 @@ void HighlighterSettingsPage::settingsFromUI()
void HighlighterSettingsPage::settingsToUI()
{
m_d->m_page.definitionFilesPath->setPath(m_d->m_settings.definitionFilesPath());
m_d->m_page.fallbackDefinitionFilesPath->setPath(m_d->m_settings.fallbackDefinitionFilesPath());
m_d->m_page.alertWhenNoDefinition->setChecked(m_d->m_settings.alertWhenNoDefinition());
m_d->m_page.useFallbackLocation->setChecked(m_d->m_settings.useFallbackLocation());
m_d->m_page.ignoreEdit->setText(m_d->m_settings.ignoredFilesPatterns());
useFallbackLocation(m_d->m_settings.useFallbackLocation());
}
void HighlighterSettingsPage::resetDefinitionsLocation()
{
m_d->m_page.definitionFilesPath->setPath(findDefinitionsLocation());
const QString &location = findDefinitionsLocation();
if (location.isEmpty())
QMessageBox::information(0, tr("Autodetect Definitions"),
tr("Existent definitions could not be found."));
else
m_d->m_page.fallbackDefinitionFilesPath->setPath(location);
}
void HighlighterSettingsPage::requestAvailableDefinitionsMetaData()
{
m_d->m_page.manageDefinitionsButton->setEnabled(false);
m_d->m_page.definitionFilesPath->buttonAtIndex(1)->setEnabled(false);
Manager::instance()->downloadAvailableDefinitionsMetaData();
connect(Manager::instance(),
......@@ -182,25 +202,36 @@ void HighlighterSettingsPage::ignoreDownloadReply()
void HighlighterSettingsPage::manageDefinitions(const QList<HighlightDefinitionMetaData> &metaData)
{
ManageDefinitionsDialog dialog(metaData, m_d->m_page.manageDefinitionsButton->window());
ManageDefinitionsDialog dialog(metaData,
m_d->m_page.definitionFilesPath->buttonAtIndex(1)->window());
dialog.exec();
m_d->m_page.manageDefinitionsButton->setEnabled(true);
m_d->m_page.definitionFilesPath->buttonAtIndex(1)->setEnabled(true);
}
void HighlighterSettingsPage::showError()
{
QMessageBox::critical(m_d->m_page.manageDefinitionsButton->window(),
QMessageBox::critical(m_d->m_page.definitionFilesPath->buttonAtIndex(1)->window(),
tr("Error connecting to server."),
tr("Not possible to retrieve data."));
m_d->m_page.manageDefinitionsButton->setEnabled(true);
m_d->m_page.definitionFilesPath->buttonAtIndex(1)->setEnabled(true);
}
void HighlighterSettingsPage::useFallbackLocation(bool checked)
{
m_d->m_page.fallbackDefinitionFilesPath->setEnabled(checked);
}
bool HighlighterSettingsPage::settingsChanged() const
{
if (m_d->m_settings.definitionFilesPath() != m_d->m_page.definitionFilesPath->path())
return true;
if (m_d->m_settings.fallbackDefinitionFilesPath() !=
m_d->m_page.fallbackDefinitionFilesPath->path())
return true;
if (m_d->m_settings.alertWhenNoDefinition() != m_d->m_page.alertWhenNoDefinition->isChecked())
return true;
if (m_d->m_settings.useFallbackLocation() != m_d->m_page.useFallbackLocation->isChecked())
return true;
if (m_d->m_settings.ignoredFilesPatterns() != m_d->m_page.ignoreEdit->text())
return true;
return false;
......
......@@ -70,6 +70,7 @@ private slots:
void manageDefinitions(const QList<Internal::HighlightDefinitionMetaData> &metaData);
void showError();
void ignoreDownloadReply();
void useFallbackLocation(bool checked);
private:
void settingsFromUI();
......
......@@ -13,13 +13,42 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="definitionsInfolabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Highlight definitions are provided by the &lt;/span&gt;&lt;a href=&quot;http://kate-editor.org/&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Kate Text Editor&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="definitionFilesGroupBox">
<property name="title">
<string>Syntax Highlight Definition Files</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
......@@ -36,72 +65,22 @@
</item>
</layout>
</item>
<item>
<widget class="QToolButton" name="resetButton">
<property name="toolTip">
<string>Reset to default</string>
</property>
<property name="text">
<string>R</string>
</property>
<property name="icon">
<iconset resource="../../coreplugin/core.qrc">
<normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="definitionsInfolabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Highlight definitions are provided by the &lt;/span&gt;&lt;a href=&quot;http://kate-editor.org/&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Kate Text Editor&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;. Qt Creator can download a list of available definitions and then install the selected ones.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="manageDefinitionsButton">
<widget class="QCheckBox" name="useFallbackLocation">
<property name="text">
<string>Manage Definitions</string>
<string>Use fallback location</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>328</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="Utils::PathChooser" name="fallbackDefinitionFilesPath" native="true"/>
</item>
</layout>
</item>
......@@ -146,7 +125,7 @@ p, li { white-space: pre-wrap; }
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>146</height>
<height>117</height>
</size>
</property>
</spacer>
......@@ -166,13 +145,9 @@ p, li { white-space: pre-wrap; }
</customwidget>
</customwidgets>
<tabstops>
<tabstop>resetButton</tabstop>
<tabstop>manageDefinitionsButton</tabstop>
<tabstop>alertWhenNoDefinition</tabstop>
<tabstop>ignoreEdit</tabstop>
</tabstops>
<resources>
<include location="../../coreplugin/core.qrc"/>
</resources>
<resources/>
<connections/>
</ui>
......@@ -146,52 +146,65 @@ void Manager::registerMimeTypes()
void Manager::gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &future)
{
QStringList definitionsPaths;
const HighlighterSettings &settings = TextEditorSettings::instance()->highlighterSettings();
QDir definitionsDir(settings.definitionFilesPath());
QStringList filter(QLatin1String("*.xml"));
definitionsDir.setNameFilters(filter);
QList<QSharedPointer<HighlightDefinitionMetaData> > allMetaData;
const QFileInfoList &filesInfo = definitionsDir.entryInfoList();
foreach (const QFileInfo &fileInfo, filesInfo) {
const QSharedPointer<HighlightDefinitionMetaData> &metaData = parseMetadata(fileInfo);
if (!metaData.isNull())
allMetaData.append(metaData);
}
definitionsPaths.append(settings.definitionFilesPath());
if (settings.useFallbackLocation())
definitionsPaths.append(settings.fallbackDefinitionFilesPath());
foreach (const QString &path, definitionsPaths) {
if (path.isEmpty())
continue;
QDir definitionsDir(path);
QStringList filter(QLatin1String("*.xml"));
definitionsDir.setNameFilters(filter);
QList<QSharedPointer<HighlightDefinitionMetaData> > allMetaData;
const QFileInfoList &filesInfo = definitionsDir.entryInfoList();
foreach (const QFileInfo &fileInfo, filesInfo) {
const QSharedPointer<HighlightDefinitionMetaData> &metaData = parseMetadata(fileInfo);
if (!metaData.isNull())
allMetaData.append(metaData);
}
// Definitions with high priority need to be added after (and then replace) definitions with
// low priority.
qSort(allMetaData.begin(), allMetaData.end(), PriorityComp());
foreach (const QSharedPointer<HighlightDefinitionMetaData> &metaData, allMetaData) {
const QString &id = metaData->id();
m_idByName.insert(metaData->name(), id);
m_definitionsMetaData.insert(id, metaData);
// A definition can specify multiple MIME types and file extensions/patterns. However, each
// thing is done with a single string. Then, there is no direct way to tell which patterns
// belong to which MIME types nor whether a MIME type is just an alias for the other.
// Currently, I associate all expressions/patterns with all MIME types from a definition.
static const QStringList textPlain(QLatin1String("text/plain"));
QList<QRegExp> patterns;
foreach (const QString &type, metaData->mimeTypes()) {
m_idByMimeType.insert(type, id);
Core::MimeType mimeType = Core::ICore::instance()->mimeDatabase()->findByType(type);
if (mimeType.isNull()) {
if (patterns.isEmpty()) {
foreach (const QString &pattern, metaData->patterns())
patterns.append(QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard));
// Definitions with high priority need to be added after (and thus replace) definitions
// with low priority.
qSort(allMetaData.begin(), allMetaData.end(), PriorityComp());
foreach (const QSharedPointer<HighlightDefinitionMetaData> &metaData, allMetaData) {
const QString &id = metaData->id();
if (m_idByName.contains(id))
// This is a fallback item, do not consider it. One with this name already exists.
continue;
m_idByName.insert(metaData->name(), id);
m_definitionsMetaData.insert(id, metaData);
// A definition can specify multiple MIME types and file extensions/patterns. However,
// each thing is done with a single string. There is no direct way to tell which
// patterns belong to which MIME types nor whether a MIME type is just an alias for the
// other. Currently, I associate all patterns with all MIME types from a definition.
static const QStringList textPlain(QLatin1String("text/plain"));
QList<QRegExp> patterns;
foreach (const QString &type, metaData->mimeTypes()) {
m_idByMimeType.insert(type, id);
Core::MimeType mimeType = Core::ICore::instance()->mimeDatabase()->findByType(type);
if (mimeType.isNull()) {
if (patterns.isEmpty()) {
foreach (const QString &pattern, metaData->patterns())
patterns.append(QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard));
}
mimeType.setType(type);
mimeType.setSubClassesOf(textPlain);
mimeType.setComment(metaData->name());
mimeType.setGlobPatterns(patterns);
future.reportResult(mimeType);
}
mimeType.setType(type);
mimeType.setSubClassesOf(textPlain);
mimeType.setComment(metaData->name());
mimeType.setGlobPatterns(patterns);
future.reportResult(mimeType);
}
}
}
......@@ -296,14 +309,16 @@ void Manager::downloadAvailableDefinitionsListFinished()
void Manager::downloadDefinitions(const QList<QUrl> &urls)
{
const QString &savePath =
TextEditorSettings::instance()->highlighterSettings().definitionFilesPath() +
QLatin1Char('/');
QString savePath = TextEditorSettings::instance()->highlighterSettings().definitionFilesPath();
if (savePath.isEmpty()) {
QMessageBox::critical(0, tr("Error"), tr("Please configure the destination directory."));
return;
}
savePath.append(QLatin1Char('/'));
QDir saveDir(savePath);
if (!saveDir.exists()) {
QMessageBox::critical(0,
tr("Error"),
QMessageBox::critical(0, tr("Error"),
tr("Please make sure the destination directory exists."));
return;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment