forked from qt-creator/qt-creator
Support UTF-8 BOM in TextEditor
TextEditor will now recognize an UTF-8 BOM. A setting to determine what to do on saving has been added as well - the options are "Always Add", "Keep Already Present" and (mostly for completeness) "Always Delete". Note: if encoding is "System", "Always Add" doesn't work, because there is no API to know what the System encoding is. Task-number: QTCREATORBUG-1857 Merge-request: 2180 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
committed by
Oswald Buddenhagen
parent
ab9f138ab4
commit
3cd32effdd
@@ -217,6 +217,7 @@ struct EditorManagerPrivate {
|
|||||||
QString m_externalEditor;
|
QString m_externalEditor;
|
||||||
|
|
||||||
IFile::ReloadSetting m_reloadSetting;
|
IFile::ReloadSetting m_reloadSetting;
|
||||||
|
IFile::Utf8BomSetting m_utf8BomSetting;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +238,8 @@ EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
|
|||||||
m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
|
m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
|
||||||
m_windowPopup(0),
|
m_windowPopup(0),
|
||||||
m_coreListener(0),
|
m_coreListener(0),
|
||||||
m_reloadSetting(IFile::AlwaysAsk)
|
m_reloadSetting(IFile::AlwaysAsk),
|
||||||
|
m_utf8BomSetting(IFile::OnlyKeep)
|
||||||
{
|
{
|
||||||
m_editorModel = new OpenEditorsModel(parent);
|
m_editorModel = new OpenEditorsModel(parent);
|
||||||
}
|
}
|
||||||
@@ -1792,6 +1794,7 @@ bool EditorManager::restoreState(const QByteArray &state)
|
|||||||
static const char * const documentStatesKey = "EditorManager/DocumentStates";
|
static const char * const documentStatesKey = "EditorManager/DocumentStates";
|
||||||
static const char * const externalEditorKey = "EditorManager/ExternalEditorCommand";
|
static const char * const externalEditorKey = "EditorManager/ExternalEditorCommand";
|
||||||
static const char * const reloadBehaviorKey = "EditorManager/ReloadBehavior";
|
static const char * const reloadBehaviorKey = "EditorManager/ReloadBehavior";
|
||||||
|
static const char * const utf8BomBehaviorKey = "EditorManager/Utf8BomBehavior";
|
||||||
|
|
||||||
void EditorManager::saveSettings()
|
void EditorManager::saveSettings()
|
||||||
{
|
{
|
||||||
@@ -1799,6 +1802,7 @@ void EditorManager::saveSettings()
|
|||||||
settings->setValue(QLatin1String(documentStatesKey), m_d->m_editorStates);
|
settings->setValue(QLatin1String(documentStatesKey), m_d->m_editorStates);
|
||||||
settings->setValue(QLatin1String(externalEditorKey), m_d->m_externalEditor);
|
settings->setValue(QLatin1String(externalEditorKey), m_d->m_externalEditor);
|
||||||
settings->setValue(QLatin1String(reloadBehaviorKey), m_d->m_reloadSetting);
|
settings->setValue(QLatin1String(reloadBehaviorKey), m_d->m_reloadSetting);
|
||||||
|
settings->setValue(QLatin1String(utf8BomBehaviorKey), m_d->m_utf8BomSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::readSettings()
|
void EditorManager::readSettings()
|
||||||
@@ -1824,6 +1828,9 @@ void EditorManager::readSettings()
|
|||||||
|
|
||||||
if (settings->contains(QLatin1String(reloadBehaviorKey)))
|
if (settings->contains(QLatin1String(reloadBehaviorKey)))
|
||||||
m_d->m_reloadSetting = (IFile::ReloadSetting)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
|
m_d->m_reloadSetting = (IFile::ReloadSetting)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
|
||||||
|
|
||||||
|
if (settings->contains(QLatin1String(utf8BomBehaviorKey)))
|
||||||
|
m_d->m_utf8BomSetting = (IFile::Utf8BomSetting)settings->value(QLatin1String(utf8BomBehaviorKey)).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1991,6 +1998,16 @@ IFile::ReloadSetting EditorManager::reloadSetting() const
|
|||||||
return m_d->m_reloadSetting;
|
return m_d->m_reloadSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorManager::setUtf8BomSetting(IFile::Utf8BomSetting behavior)
|
||||||
|
{
|
||||||
|
m_d->m_utf8BomSetting = behavior;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFile::Utf8BomSetting EditorManager::utf8BomSetting() const
|
||||||
|
{
|
||||||
|
return m_d->m_utf8BomSetting;
|
||||||
|
}
|
||||||
|
|
||||||
QTextCodec *EditorManager::defaultTextEncoding() const
|
QTextCodec *EditorManager::defaultTextEncoding() const
|
||||||
{
|
{
|
||||||
QSettings *settings = Core::ICore::instance()->settings();
|
QSettings *settings = Core::ICore::instance()->settings();
|
||||||
|
|||||||
@@ -192,6 +192,9 @@ public:
|
|||||||
void setReloadSetting(IFile::ReloadSetting behavior);
|
void setReloadSetting(IFile::ReloadSetting behavior);
|
||||||
IFile::ReloadSetting reloadSetting() const;
|
IFile::ReloadSetting reloadSetting() const;
|
||||||
|
|
||||||
|
void setUtf8BomSetting(IFile::Utf8BomSetting behavior);
|
||||||
|
IFile::Utf8BomSetting utf8BomSetting() const;
|
||||||
|
|
||||||
QTextCodec *defaultTextEncoding() const;
|
QTextCodec *defaultTextEncoding() const;
|
||||||
|
|
||||||
// Helper to display a message dialog when encountering a read-only
|
// Helper to display a message dialog when encountering a read-only
|
||||||
|
|||||||
@@ -104,6 +104,46 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="encodingLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Default file encoding: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="encodingBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||||
|
</property>
|
||||||
|
<property name="minimumContentsLength">
|
||||||
|
<number>20</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_6">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>285</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="languageLabel">
|
<widget class="QLabel" name="languageLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ public:
|
|||||||
IgnoreAll = 2
|
IgnoreAll = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Utf8BomSetting {
|
||||||
|
AlwaysAdd = 0,
|
||||||
|
OnlyKeep = 1,
|
||||||
|
AlwaysDelete = 2
|
||||||
|
};
|
||||||
|
|
||||||
enum ChangeTrigger {
|
enum ChangeTrigger {
|
||||||
TriggerInternal,
|
TriggerInternal,
|
||||||
TriggerExternal
|
TriggerExternal
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ BaseTextDocument::BaseTextDocument()
|
|||||||
m_fileIsReadOnly = false;
|
m_fileIsReadOnly = false;
|
||||||
m_isBinaryData = false;
|
m_isBinaryData = false;
|
||||||
m_codec = Core::EditorManager::instance()->defaultTextEncoding();
|
m_codec = Core::EditorManager::instance()->defaultTextEncoding();
|
||||||
|
m_fileHasUtf8Bom = false;
|
||||||
m_hasDecodingError = false;
|
m_hasDecodingError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +188,12 @@ bool BaseTextDocument::save(const QString &fileName)
|
|||||||
if (m_lineTerminatorMode == CRLFLineTerminator)
|
if (m_lineTerminatorMode == CRLFLineTerminator)
|
||||||
plainText.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
|
plainText.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
|
||||||
|
|
||||||
|
Core::IFile::Utf8BomSetting utf8bomSetting = Core::EditorManager::instance()->utf8BomSetting();
|
||||||
|
if (m_codec->name() == "UTF-8" &&
|
||||||
|
(utf8bomSetting == Core::IFile::AlwaysAdd || (utf8bomSetting == Core::IFile::OnlyKeep && m_fileHasUtf8Bom))) {
|
||||||
|
file.write("\xef\xbb\xbf", 3);
|
||||||
|
}
|
||||||
|
|
||||||
file.write(m_codec->fromUnicode(plainText));
|
file.write(m_codec->fromUnicode(plainText));
|
||||||
if (!file.flush())
|
if (!file.flush())
|
||||||
return false;
|
return false;
|
||||||
@@ -259,6 +266,7 @@ bool BaseTextDocument::open(const QString &fileName)
|
|||||||
int bytesRead = buf.size();
|
int bytesRead = buf.size();
|
||||||
|
|
||||||
QTextCodec *codec = m_codec;
|
QTextCodec *codec = m_codec;
|
||||||
|
m_fileHasUtf8Bom = false;
|
||||||
|
|
||||||
// code taken from qtextstream
|
// code taken from qtextstream
|
||||||
if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0)
|
if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0)
|
||||||
@@ -267,6 +275,9 @@ bool BaseTextDocument::open(const QString &fileName)
|
|||||||
} else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe)
|
} else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe)
|
||||||
|| (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) {
|
|| (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) {
|
||||||
codec = QTextCodec::codecForName("UTF-16");
|
codec = QTextCodec::codecForName("UTF-16");
|
||||||
|
} else if (bytesRead >= 3 && ((uchar(buf[0]) == 0xef && uchar(buf[1]) == 0xbb) && uchar(buf[2]) == 0xbf)) {
|
||||||
|
codec = QTextCodec::codecForName("UTF-8");
|
||||||
|
m_fileHasUtf8Bom = true;
|
||||||
} else if (!codec) {
|
} else if (!codec) {
|
||||||
codec = QTextCodec::codecForLocale();
|
codec = QTextCodec::codecForLocale();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ private:
|
|||||||
};
|
};
|
||||||
LineTerminatorMode m_lineTerminatorMode;
|
LineTerminatorMode m_lineTerminatorMode;
|
||||||
QTextCodec *m_codec;
|
QTextCodec *m_codec;
|
||||||
|
bool m_fileHasUtf8Bom;
|
||||||
|
|
||||||
bool m_fileIsReadOnly;
|
bool m_fileIsReadOnly;
|
||||||
bool m_isBinaryData;
|
bool m_isBinaryData;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
|
||||||
#include <QtCore/QSettings>
|
#include <QtCore/QSettings>
|
||||||
#include <QtCore/QTextCodec>
|
#include <QtCore/QTextCodec>
|
||||||
@@ -135,6 +136,8 @@ QWidget *BehaviorSettingsPage::createPage(QWidget *parent)
|
|||||||
m_d->m_page.encodingBox->setCurrentIndex(i);
|
m_d->m_page.encodingBox->setCurrentIndex(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_d->m_page.utf8BomBox->setCurrentIndex(Core::EditorManager::instance()->utf8BomSetting());
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +180,8 @@ void BehaviorSettingsPage::apply()
|
|||||||
settings->setValue(QLatin1String(Core::Constants::SETTINGS_DEFAULTTEXTENCODING),
|
settings->setValue(QLatin1String(Core::Constants::SETTINGS_DEFAULTTEXTENCODING),
|
||||||
m_codecs.at(m_d->m_page.encodingBox->currentIndex())->name());
|
m_codecs.at(m_d->m_page.encodingBox->currentIndex())->name());
|
||||||
|
|
||||||
|
Core::EditorManager::instance()->setUtf8BomSetting(
|
||||||
|
Core::IFile::Utf8BomSetting(m_d->m_page.utf8BomBox->currentIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BehaviorSettingsPage::settingsFromUI(TabSettings &tabSettings,
|
void BehaviorSettingsPage::settingsFromUI(TabSettings &tabSettings,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>576</width>
|
<width>662</width>
|
||||||
<height>538</height>
|
<height>538</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@@ -442,6 +442,13 @@ Influences the indentation of continuation lines.
|
|||||||
<string>File Encodings</string>
|
<string>File Encodings</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="encodingLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Default encoding: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
<item>
|
<item>
|
||||||
@@ -475,14 +482,63 @@ Influences the indentation of continuation lines.
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="encodingLabel">
|
<widget class="QLabel" name="utf8BomLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Default encoding: </string>
|
<string>UTF-8 BOM:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="1" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="utf8BomBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How text editors should deal with UTF-8 Byte Order Marks. The options are:</p>
|
||||||
|
<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Add If Encoding Is UTF-8:</span> always add a BOM when saving a file in UTF-8 encoding. Note that this will not work if the encoding is <span style=" font-style:italic;">System</span>, as Qt Creator does not know what it actually is.</li>
|
||||||
|
<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Keep If Already Present: </span>save the file with a BOM if it already had one when it was loaded.</li>
|
||||||
|
<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Always Delete:</span> never write an UTF-8 BOM, possibly deleting a pre-existing one.</li></ul>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note that UTF-8 BOMs are uncommon and treated incorrectly by some editors, so it usually makes little sense to add any.</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This setting does <span style=" font-weight:600;">not</span> influence the use of UTF-16 and UTF-32 BOMs.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add If Encoding Is UTF-8</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Keep If Already Present</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Always Delete</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
|||||||
Reference in New Issue
Block a user