Text Codecs Example▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************
*/
#include
"encodingdialog.h"
#if QT_CONFIG(action)
# include <QAction>
#endif
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QVBoxLayout>
#if QT_CONFIG(clipboard)
# include <QGuiApplication>
# include <QClipboard>
#endif
#include <QTextStream>
// Helpers for formatting character sequences
// Format a special character like '\x0a'
template
&
lt;class
Int&
gt;
static
void
formatEscapedNumber(QTextStream &
amp;str, Int value, int
base,
int
width =
0
,char
prefix =
0
)
{
str &
lt;&
lt; '
\\
'
;
if
(prefix)
str &
lt;&
lt; prefix;
const
auto
oldPadChar =
str.padChar();
const
auto
oldFieldWidth =
str.fieldWidth();
const
auto
oldFieldAlignment =
str.fieldAlignment();
const
auto
oldIntegerBase =
str.integerBase();
str.setPadChar(QLatin1Char('0'
));
str.setFieldWidth(width);
str.setFieldAlignment(QTextStream::
AlignRight);
str.setIntegerBase(base);
str &
lt;&
lt; value;
str.setIntegerBase(oldIntegerBase);
str.setFieldAlignment(oldFieldAlignment);
str.setFieldWidth(oldFieldWidth);
str.setPadChar(oldPadChar);
}
template
&
lt;class
Int&
gt;
static
bool
formatSpecialCharacter(QTextStream &
amp;str, Int value)
{
bool
result =
true
;
switch
(value) {
case
'
\\
'
:
str &
lt;&
lt; "
\\\\
"
;
break
;
case
'
\"
'
:
str &
lt;&
lt; "
\\\"
"
;
break
;
case
'
\n
'
:
str &
lt;&
lt; "
\\
n"
;
break
;
default
:
result =
false
;
break
;
}
return
result;
}
// Format a sequence of characters (QChar, ushort (UTF-16), uint (UTF-32)
// or just char (Latin1, Utf-8)) with the help of traits specifying
// how to obtain the code for checking the printable-ness and how to
// stream out the plain ASCII values.
template
&
lt;EncodingDialog::
Encoding&
gt;
struct
FormattingTraits
{
}
;
template
&
lt;&
gt;
struct
FormattingTraits&
lt;EncodingDialog::
Unicode&
gt;
{
static
ushort code(QChar c) {
return
c.unicode(); }
static
char
toAscii(QChar c) {
return
c.toLatin1(); }
}
;
template
&
lt;&
gt;
struct
FormattingTraits&
lt;EncodingDialog::
Utf8&
gt;
{
static
ushort code(char
c) {
return
uchar(c); }
static
char
toAscii(char
c) {
return
c; }
}
;
template
&
lt;&
gt;
struct
FormattingTraits&
lt;EncodingDialog::
Utf16&
gt;
{
static
ushort code(ushort c) {
return
c; }
static
char
toAscii(ushort c) {
return
char
(c); }
}
;
template
&
lt;&
gt;
struct
FormattingTraits&
lt;EncodingDialog::
Utf32&
gt;
{
static
uint code(uint c) {
return
c; }
static
char
toAscii(uint c) {
return
char
(c); }
}
;
template
&
lt;&
gt;
struct
FormattingTraits&
lt;EncodingDialog::
Latin1&
gt;
{
static
uchar code(char
c) {
return
uchar(c); }
static
char
toAscii(char
c) {
return
c; }
}
;
static
bool
isHexDigit(char
c)
{
return
(c &
gt;=
'0'
&
amp;&
amp; c &
lt;=
'9'
) ||
(c &
gt;=
'a'
&
amp;&
amp; c &
lt;=
'f'
)
||
(c &
gt;=
'A'
&
amp;&
amp; c &
lt;=
'F'
);
}
template
&
lt;EncodingDialog::
Encoding encoding, class
Iterator&
gt;
static
void
formatStringSequence(QTextStream &
amp;str, Iterator i1, Iterator i2,
int
escapeIntegerBase, int
escapeWidth,
char
escapePrefix =
0
)
{
str &
lt;&
lt; '"'
;
bool
separateHexEscape =
false
;
for
(; i1 !=
i2; ++
i1) {
const
auto
code =
FormattingTraits&
lt;encoding&
gt;::
code(*
i1);
if
(code &
gt;=
0x80
) {
formatEscapedNumber(str, code, escapeIntegerBase, escapeWidth, escapePrefix);
separateHexEscape =
escapeIntegerBase ==
16
&
amp;&
amp; escapeWidth ==
0
;
}
else
{
if
(!
formatSpecialCharacter(str, code)) {
const
char
c =
FormattingTraits&
lt;encoding&
gt;::
toAscii(*
i1);
// For variable width/hex: Terminate the literal to stop digit parsing
// ("\x12" "34...").
if
(separateHexEscape &
amp;&
amp; isHexDigit(c))
str &
lt;&
lt; "
\"
\"
"
;
str &
lt;&
lt; c;
}
separateHexEscape =
false
;
}
}
str &
lt;&
lt; '"'
;
}
static
QString encodedString(const
QString &
amp;value, EncodingDialog::
Encoding e)
{
QString result;
QTextStream str(&
amp;result);
switch
(e) {
case
EncodingDialog::
Unicode:
formatStringSequence&
lt;EncodingDialog::
Unicode&
gt;(str, value.cbegin(), value.cend(),
16
, 4
, 'u'
);
break
;
case
EncodingDialog::
Utf8: {
const
QByteArray utf8 =
value.toUtf8();
str &
lt;&
lt; "u8"
;
formatStringSequence&
lt;EncodingDialog::
Utf8&
gt;(str, utf8.cbegin(), utf8.cend(),
8
, 3
);
}
break
;
case
EncodingDialog::
Utf16: {
auto
utf16 =
value.utf16();
auto
utf16End =
utf16 +
value.size();
str &
lt;&
lt; 'u'
;
formatStringSequence&
lt;EncodingDialog::
Utf16&
gt;(str, utf16, utf16End,
16
, 0
, 'x'
);
}
break
;
case
EncodingDialog::
Utf32: {
auto
utf32 =
value.toUcs4();
str &
lt;&
lt; 'U'
;
formatStringSequence&
lt;EncodingDialog::
Utf32&
gt;(str, utf32.cbegin(), utf32.cend(),
16
, 0
, 'x'
);
}
break
;
case
EncodingDialog::
Latin1: {
const
QByteArray latin1 =
value.toLatin1();
formatStringSequence&
lt;EncodingDialog::
Latin1&
gt;(str, latin1.cbegin(), latin1.cend(),
16
, 0
, 'x'
);
}
break
;
case
EncodingDialog::
EncodingCount:
break
;
}
return
result;
}
// Dialog helpers
static
const
char
*
encodingLabels[]
{
QT_TRANSLATE_NOOP("EncodingDialog"
, "Unicode:"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "UTF-8:"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "UTF-16:"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "UTF-32:"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "Latin1:"
)
}
;
static
const
char
*
encodingToolTips[]
{
QT_TRANSLATE_NOOP("EncodingDialog"
, "Unicode points for use with any encoding (C++, Python)"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "QString::fromUtf8()"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "QStringViewLiteral(), wchar_t on Windows"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "wchar_t on Unix (Ucs4)"
),
QT_TRANSLATE_NOOP("EncodingDialog"
, "QLatin1String"
)
}
;
// A read-only line edit with a tool button to copy the contents
class
DisplayLineEdit : public
QLineEdit
{
Q_OBJECT
public
:
explicit
DisplayLineEdit(const
QIcon &
amp;icon, QWidget *
parent =
nullptr
);
public
slots:
void
copyAll();
}
;
DisplayLineEdit::
DisplayLineEdit(const
QIcon &
amp;icon, QWidget *
parent) :
QLineEdit(parent)
{
setReadOnly(true
);
#if QT_CONFIG(clipboard) && QT_CONFIG(action)
auto
copyAction =
addAction(icon, QLineEdit::
TrailingPosition);
connect(copyAction, &
amp;QAction::
triggered, this
, &
amp;DisplayLineEdit::
copyAll);
#endif
}
void
DisplayLineEdit::
copyAll()
{
#if QT_CONFIG(clipboard)
QGuiApplication::
clipboard()-&
gt;setText(text());
#endif
}
static
void
addFormLayoutRow(QFormLayout *
formLayout, const
QString &
amp;text,
QWidget *
w, const
QString &
amp;toolTip)
{
auto
label =
new
QLabel(text);
label-&
gt;setToolTip(toolTip);
w-&
gt;setToolTip(toolTip);
label-&
gt;setBuddy(w);
formLayout-&
gt;addRow(label, w);
}
EncodingDialog::
EncodingDialog(QWidget *
parent) :
QDialog(parent)
{
setWindowFlags(windowFlags() &
amp; ~
Qt::
WindowContextHelpButtonHint);
setWindowTitle(tr("Encodings"
));
auto
formLayout =
new
QFormLayout;
auto
sourceLineEdit =
new
QLineEdit(this
);
sourceLineEdit-&
gt;setClearButtonEnabled(true
);
connect(sourceLineEdit, &
amp;QLineEdit::
textChanged, this
, &
amp;EncodingDialog::
textChanged);
addFormLayoutRow(formLayout, tr("&Source:"
), sourceLineEdit, tr("Enter text"
));
const
auto
copyIcon =
QIcon::
fromTheme(QLatin1String("edit-copy"
),
QIcon(QLatin1String(":/images/editcopy"
)));
for
(int
i =
0
; i &
lt; EncodingCount; ++
i) {
m_lineEdits[i] =
new
DisplayLineEdit(copyIcon, this
);
addFormLayoutRow(formLayout, tr(encodingLabels[i]),
m_lineEdits[i], tr(encodingToolTips[i]));
}
auto
mainLayout =
new
QVBoxLayout(this
);
mainLayout-&
gt;addLayout(formLayout);
auto
buttonBox =
new
QDialogButtonBox(QDialogButtonBox::
Close);
connect(buttonBox, &
amp;QDialogButtonBox::
rejected, this
, &
amp;QDialog::
reject);
mainLayout-&
gt;addWidget(buttonBox);
}
void
EncodingDialog::
textChanged(const
QString &
amp;t)
{
if
(t.isEmpty()) {
for
(auto
lineEdit : m_lineEdits)
lineEdit-&
gt;clear();
}
else
{
for
(int
i =
0
; i &
lt; EncodingCount; ++
i)
m_lineEdits[i]-&
gt;setText(encodedString(t, static_cast
&
lt;Encoding&
gt;(i)));
}
}
#include
"encodingdialog.moc"