summaryrefslogtreecommitdiffstats
path: root/examples/widgets/tools/codecs/previewform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/widgets/tools/codecs/previewform.cpp')
-rw-r--r--examples/widgets/tools/codecs/previewform.cpp176
1 files changed, 153 insertions, 23 deletions
diff --git a/examples/widgets/tools/codecs/previewform.cpp b/examples/widgets/tools/codecs/previewform.cpp
index 82203175ca..e5ca13f011 100644
--- a/examples/widgets/tools/codecs/previewform.cpp
+++ b/examples/widgets/tools/codecs/previewform.cpp
@@ -52,47 +52,159 @@
#include "previewform.h"
+// Helpers for creating hex dumps
+static void indent(QTextStream &str, int indent)
+{
+ for (int i = 0; i < indent; ++i)
+ str << ' ';
+}
+
+static void formatHex(QTextStream &str, const QByteArray &data)
+{
+ const int fieldWidth = str.fieldWidth();
+ const QTextStream::FieldAlignment alignment = str.fieldAlignment();
+ const int base = str.integerBase();
+ const QChar padChar = str.padChar();
+ str.setIntegerBase(16);
+ str.setPadChar(QLatin1Char('0'));
+ str.setFieldAlignment(QTextStream::AlignRight);
+
+ const unsigned char *p = reinterpret_cast<const unsigned char *>(data.constBegin());
+ for (const unsigned char *end = p + data.size(); p < end; ++p) {
+ str << ' ';
+ str.setFieldWidth(2);
+ str << unsigned(*p);
+ str.setFieldWidth(fieldWidth);
+ }
+ str.setFieldAlignment(alignment);
+ str.setPadChar(padChar);
+ str.setIntegerBase(base);
+}
+
+static void formatPrintableCharacters(QTextStream &str, const QByteArray &data)
+{
+ for (int i = 0, size = data.size(); i < size; ++i) {
+ const char c = data.at(i);
+ switch (c) {
+ case '\0':
+ str << "\\0";
+ break;
+ case '\t':
+ str << "\\t";
+ break;
+ case '\r':
+ str << "\\r";
+ break;
+ case '\n':
+ str << "\\n";
+ break;
+ default:
+ if (c >= 32 && uchar(c) < 127)
+ str << ' ' << c;
+ else
+ str << "..";
+ break;
+ }
+ }
+}
+
+static QString formatHexDump(const QByteArray &data)
+{
+ enum { lineWidth = 16 };
+ QString result;
+ QTextStream str(&result);
+ str.setIntegerBase(16);
+ str.setPadChar(QLatin1Char('0'));
+ const int fieldWidth = str.fieldWidth();
+ const QTextStream::FieldAlignment alignment = str.fieldAlignment();
+ for (int a = 0, size = data.size(); a < size; a += lineWidth) {
+ str.setFieldAlignment(QTextStream::AlignRight);
+ str.setFieldWidth(8);
+ str << a;
+ str.setFieldWidth(fieldWidth);
+ str.setFieldAlignment(alignment);
+
+ const int end = qMin(a + lineWidth, size);
+ const QByteArray line = data.mid(a, end - a);
+
+ formatHex(str, line);
+ indent(str, 3 * (lineWidth - line.size()));
+
+ str << ' ';
+ formatPrintableCharacters(str, line);
+ indent(str, 2 * (lineWidth - line.size()));
+ str << '\n';
+ }
+ return result;
+}
+
PreviewForm::PreviewForm(QWidget *parent)
: QDialog(parent)
{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
encodingComboBox = new QComboBox;
- encodingLabel = new QLabel(tr("&Encoding:"));
+ QLabel *encodingLabel = new QLabel(tr("&Encoding:"));
encodingLabel->setBuddy(encodingComboBox);
- textEdit = new QTextEdit;
- textEdit->setLineWrapMode(QTextEdit::NoWrap);
+ textEdit = new QPlainTextEdit;
+ textEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
textEdit->setReadOnly(true);
+ hexDumpEdit = new QPlainTextEdit;
+ hexDumpEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
+ hexDumpEdit->setReadOnly(true);
+ hexDumpEdit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
- buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
- | QDialogButtonBox::Cancel);
+ QDialogButtonBox *buttonBox =
+ new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ okButton = buttonBox->button(QDialogButtonBox::Ok);
- connect(encodingComboBox, SIGNAL(activated(int)),
- this, SLOT(updateTextEdit()));
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
- connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ typedef void(QComboBox::*ComboBoxIntSignal)(int);
+ connect(encodingComboBox, static_cast<ComboBoxIntSignal>(&QComboBox::activated),
+ this, &PreviewForm::updateTextEdit);
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
- QGridLayout *mainLayout = new QGridLayout;
+ QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(encodingLabel, 0, 0);
mainLayout->addWidget(encodingComboBox, 0, 1);
- mainLayout->addWidget(textEdit, 1, 0, 1, 2);
- mainLayout->addWidget(buttonBox, 2, 0, 1, 2);
- setLayout(mainLayout);
+ tabWidget = new QTabWidget;
+ tabWidget->addTab(textEdit, tr("Preview"));
+ tabWidget->addTab(hexDumpEdit, tr("Hex Dump"));
+ mainLayout->addWidget(tabWidget, 1, 0, 1, 2);
+ statusLabel = new QLabel;
+ mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
+ mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
- setWindowTitle(tr("Choose Encoding"));
- resize(400, 300);
+ const QRect screenGeometry = QApplication::desktop()->screenGeometry(this);
+ resize(screenGeometry.width() * 2 / 5, screenGeometry.height() / 2);
}
void PreviewForm::setCodecList(const QList<QTextCodec *> &list)
{
encodingComboBox->clear();
- foreach (QTextCodec *codec, list)
- encodingComboBox->addItem(codec->name(), codec->mibEnum());
+ foreach (const QTextCodec *codec, list) {
+ encodingComboBox->addItem(QLatin1String(codec->name()),
+ QVariant(codec->mibEnum()));
+ }
+}
+
+void PreviewForm::reset()
+{
+ decodedStr.clear();
+ textEdit->clear();
+ hexDumpEdit->clear();
+ statusLabel->clear();
+ statusLabel->setStyleSheet(QString());
+ okButton->setEnabled(false);
+ tabWidget->setCurrentIndex(0);
}
void PreviewForm::setEncodedData(const QByteArray &data)
{
+ reset();
encodedData = data;
+ hexDumpEdit->setPlainText(formatHexDump(data));
updateTextEdit();
}
@@ -100,12 +212,30 @@ void PreviewForm::updateTextEdit()
{
int mib = encodingComboBox->itemData(
encodingComboBox->currentIndex()).toInt();
- QTextCodec *codec = QTextCodec::codecForMib(mib);
+ const QTextCodec *codec = QTextCodec::codecForMib(mib);
+ const QString name = QLatin1String(codec->name());
- QTextStream in(&encodedData);
- in.setAutoDetectUnicode(false);
- in.setCodec(codec);
- decodedStr = in.readAll();
+ QTextCodec::ConverterState state;
+ decodedStr = codec->toUnicode(encodedData.constData(), encodedData.size(), &state);
- textEdit->setPlainText(decodedStr);
+ bool success = true;
+ if (state.remainingChars) {
+ success = false;
+ const QString message =
+ tr("%1: conversion error at character %2")
+ .arg(name).arg(encodedData.size() - state.remainingChars + 1);
+ statusLabel->setText(message);
+ statusLabel->setStyleSheet(QStringLiteral("background-color: \"red\";"));
+ } else if (state.invalidChars) {
+ statusLabel->setText(tr("%1: %n invalid characters", 0, state.invalidChars).arg(name));
+ statusLabel->setStyleSheet(QStringLiteral("background-color: \"yellow\";"));
+ } else {
+ statusLabel->setText(tr("%1: %n bytes converted", 0, encodedData.size()).arg(name));
+ statusLabel->setStyleSheet(QString());
+ }
+ if (success)
+ textEdit->setPlainText(decodedStr);
+ else
+ textEdit->clear();
+ okButton->setEnabled(success);
}