diff --git a/ChangeLog b/ChangeLog index 899ff09e..fe819123 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,6 +43,7 @@ Changes - CODE16K/CODE49: add min rows option - GUI: add CLI equivalent dialog (#163) - Add ZBarcode_BarcodeName() +- GUI: data dialog: convert Line Feeds if escaping on input, escape on output Bugs ---- diff --git a/backend_qt/tests/test_qzint.cpp b/backend_qt/tests/test_qzint.cpp index d6b94b8b..9d58c993 100644 --- a/backend_qt/tests/test_qzint.cpp +++ b/backend_qt/tests/test_qzint.cpp @@ -556,6 +556,18 @@ private slots: " --height=11.7 --heightperrow --noquietzones --rows=4 --separator=2 --small" << "" << ""; + QTest::newRow("BARCODE_CODE49") << true << 0.0f << "" + << BARCODE_CODE49 << UNICODE_MODE // symbology-inputMode + << "12345678901234567890" << "" // text-primary + << 30.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor + << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting + << true << false << false << false << true << 0 // showText-rotateAngle + << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << "zint -b 24 --compliantheight -d '12345678901234567890'" + << "zint.exe -b 24 --compliantheight -d \"12345678901234567890\"" + << "" << ""; + QTest::newRow("BARCODE_CODABLOCKF") << true << 0.0f << "" << BARCODE_CODABLOCKF << (DATA_MODE | ESCAPE_MODE) // symbology-inputMode << "T\\n\\xA0t\\\"" << "" // text-primary @@ -682,6 +694,18 @@ private slots: " --rows=10 --scale=10 --secure=3 --structapp=1,2" << "" << ""; + QTest::newRow("BARCODE_ITF14") << true << 0.0f << "" + << BARCODE_ITF14 << UNICODE_MODE // symbology-inputMode + << "9212320967145" << "" // text-primary + << 30.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor + << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting + << true << false << false << false << true << 0 // showText-rotateAngle + << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << "zint -b 89 --compliantheight -d '9212320967145'" + << "zint.exe -b 89 --compliantheight -d \"9212320967145\"" + << "" << ""; + QTest::newRow("BARCODE_MAXICODE") << true << 0.0f << "" << BARCODE_MAXICODE << (UNICODE_MODE | ESCAPE_MODE) // symbology-inputMode << "152382802840001" diff --git a/docs/manual.txt b/docs/manual.txt index 95150f5a..88f1f4bb 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1707,7 +1707,7 @@ border width of 5. This behaviour can be overridden by using the --bind option (or adding BARCODE_BIND to symbol->output_options). Similarly the border width can be overridden using --border= (or by setting symbol->border_width). If a symbol with no border is required this can be achieved by explicitly setting -the border type to bind (or box) and setting the border width to 0. +the border type to box (or bind) and setting the border width to 0. 6.1.2.7 Deutsche Post Leitcode ------------------------------ diff --git a/frontend_qt/cliwindow.cpp b/frontend_qt/cliwindow.cpp index 40658c81..ac8064f3 100644 --- a/frontend_qt/cliwindow.cpp +++ b/frontend_qt/cliwindow.cpp @@ -25,7 +25,6 @@ #include "cliwindow.h" #include "barcodeitem.h" -#include "mainwindow.h" // Shorthand #define QSL QStringLiteral diff --git a/frontend_qt/datawindow.cpp b/frontend_qt/datawindow.cpp index a6908d53..91bfb3fd 100644 --- a/frontend_qt/datawindow.cpp +++ b/frontend_qt/datawindow.cpp @@ -24,13 +24,16 @@ #include #include #include +#include #include "datawindow.h" // Shorthand #define QSL QStringLiteral -DataWindow::DataWindow(const QString &input) : Valid(false) +static const int tempMessageTimeout = 2000; + +DataWindow::DataWindow(const QString &input, bool isEscaped) : Valid(false), Escaped(false) { setupUi(this); QSettings settings; @@ -48,7 +51,26 @@ DataWindow::DataWindow(const QString &input) : Valid(false) btnDataClear->setIcon(clearIcon); btnOK->setIcon(okIcon); - txtDataInput->setPlainText(input); + if (isEscaped && input.contains(QSL("\\n"))) { + // Substitute escaped Line Feeds with actual Line Feeds + QString out; + out.reserve(input.length()); + int lastPosn = 0; + QRegularExpression escRE(QSL("\\\\(?:[0EabtnvfreGR\\\\]|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})")); + QRegularExpressionMatchIterator matchI = escRE.globalMatch(input); + while (matchI.hasNext()) { + QRegularExpressionMatch match = matchI.next(); + if (match.captured(0) == QSL("\\n")) { + out += input.mid(lastPosn, match.capturedStart(0) - lastPosn) + '\n'; + lastPosn = match.capturedEnd(0); + } + } + out += input.mid(lastPosn); + txtDataInput->setPlainText(out); + statusBarData->showMessage(tr("Converted LFs"), tempMessageTimeout); + } else { + txtDataInput->setPlainText(input); + } txtDataInput->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); connect(btnCancel, SIGNAL( clicked( bool )), SLOT(close())); @@ -75,6 +97,11 @@ void DataWindow::okay() { Valid = true; DataOutput = txtDataInput->toPlainText(); + if (DataOutput.contains('\n')) { + // Escape Line Feeds + DataOutput.replace('\n', QSL("\\n")); + Escaped = true; + } close(); } @@ -88,9 +115,7 @@ void DataWindow::from_file() QString filename; QFile file; QByteArray outstream; - QString escape_string; - - open_dialog.setWindowTitle("Open File"); + open_dialog.setWindowTitle("Import File"); open_dialog.setDirectory(settings.value("studio/default_dir", QDir::toNativeSeparators(QDir::homePath())).toString()); @@ -110,22 +135,27 @@ void DataWindow::from_file() /* Allow some non-printing (control) characters to be read from file by converting them to escape sequences */ - escape_string.clear(); - escape_string.append(QString(outstream)); + QString escape_string(outstream); // Converts to UTF-8 (NOTE: QString can't handle embedded NULs) - escape_string.replace((QChar)'\\', (QString)"\\\\", Qt::CaseInsensitive); - escape_string.replace((QChar)0x04, (QString)"\\E", Qt::CaseInsensitive); /* End of Transmission */ - escape_string.replace((QChar)'\a', (QString)"\\a", Qt::CaseInsensitive); /* Bell */ - escape_string.replace((QChar)'\b', (QString)"\\b", Qt::CaseInsensitive); /* Backspace */ - escape_string.replace((QChar)'\t', (QString)"\\t", Qt::CaseInsensitive); /* Horizontal tab */ - escape_string.replace((QChar)'\v', (QString)"\\v", Qt::CaseInsensitive); /* Vertical tab */ - escape_string.replace((QChar)'\f', (QString)"\\f", Qt::CaseInsensitive); /* Form feed */ - escape_string.replace((QChar)'\r', (QString)"\\r", Qt::CaseInsensitive); /* Carriage return */ - escape_string.replace((QChar)0x1b, (QString)"\\e", Qt::CaseInsensitive); /* Escape */ - escape_string.replace((QChar)0x1d, (QString)"\\G", Qt::CaseInsensitive); /* Group Separator */ - escape_string.replace((QChar)0x1e, (QString)"\\R", Qt::CaseInsensitive); /* Record Separator */ + QRegularExpression escRE(QSL("[\\x04\\x07\\x08\\x09\\x0B\\x0C\\x0D\\x1B\\x1D\\x1E\\x5C]")); + if (escape_string.contains(escRE)) { + escape_string.replace((QChar)'\\', QSL("\\\\")); + escape_string.replace((QChar)0x04, QSL("\\E")); /* End of Transmission */ + escape_string.replace((QChar)'\a', QSL("\\a")); /* Bell (0x07) */ + escape_string.replace((QChar)'\b', QSL("\\b")); /* Backspace (0x08) */ + escape_string.replace((QChar)'\t', QSL("\\t")); /* Horizontal tab (0x09) */ + // Leaving Line Feed (0x0A) + escape_string.replace((QChar)'\v', QSL("\\v")); /* Vertical tab (0x0B) */ + escape_string.replace((QChar)'\f', QSL("\\f")); /* Form feed (0x0C) */ + escape_string.replace((QChar)'\r', QSL("\\r")); /* Carriage return (0x0D) */ + escape_string.replace((QChar)0x1b, QSL("\\e")); /* Escape */ + escape_string.replace((QChar)0x1d, QSL("\\G")); /* Group Separator */ + escape_string.replace((QChar)0x1e, QSL("\\R")); /* Record Separator */ + Escaped = true; + statusBarData->showMessage(tr("Escaped data"), tempMessageTimeout); + } - txtDataInput->setPlainText(QString(escape_string)); + txtDataInput->setPlainText(escape_string); file.close(); settings.setValue("studio/default_dir", filename.mid(0, filename.lastIndexOf(QDir::separator()))); diff --git a/frontend_qt/datawindow.h b/frontend_qt/datawindow.h index 369e927e..c1803e04 100644 --- a/frontend_qt/datawindow.h +++ b/frontend_qt/datawindow.h @@ -28,10 +28,11 @@ class DataWindow : public QDialog, private Ui::DataDialog Q_OBJECT public: - DataWindow(const QString &input); + DataWindow(const QString &input, bool isEscaped); ~DataWindow(); bool Valid; + bool Escaped; QString DataOutput; private slots: diff --git a/frontend_qt/extData.ui b/frontend_qt/extData.ui index 8d180432..aabbf351 100644 --- a/frontend_qt/extData.ui +++ b/frontend_qt/extData.ui @@ -6,7 +6,7 @@ 0 0 - 429 + 500 333 @@ -27,8 +27,7 @@ &Data - Input data. Line Feeds (0xA0) will -be converted to spaces + Input data txtDataInput @@ -56,7 +55,7 @@ be converted to spaces &From File... - Get input data from a file. Certain characters <br/>will be converted to escape sequences + Import input data from a file. Certain characters <br/>will be converted to escape sequences <table cellspacing="3"> <tr><td>End of Transmission (0x04)</td><td>&nbsp;\E</td></tr> <tr><td>Bell (0x07)</td><td>&nbsp;\a</td></tr> @@ -70,7 +69,7 @@ be converted to spaces <tr><td>Record Separator (0x1E)</td><td>&nbsp;\R</td></tr> <tr><td>Backslash (0x5C)</td><td>&nbsp;\\</td></tr> </table> -Note that Line Feed (0x0A) is not included +Note that Line Feeds (0x0A) are not included,<br/> but any present will be escaped on update @@ -85,9 +84,9 @@ Note that Line Feed (0x0A) is not included - - - Qt::Horizontal + + + false @@ -95,7 +94,7 @@ Note that Line Feed (0x0A) is not included 20 - + @@ -103,7 +102,8 @@ Note that Line Feed (0x0A) is not included &OK - Close window and update input data + Close window and update input data +Line Feeds (0xA0) will be escaped as "\n" diff --git a/frontend_qt/extSequence.ui b/frontend_qt/extSequence.ui index 36593930..a2679c65 100644 --- a/frontend_qt/extSequence.ui +++ b/frontend_qt/extSequence.ui @@ -24,205 +24,174 @@ - - - - 0 - 0 - - - - Create Sequence - - - - - - - - - - Start sequence at this value - - - &Start Value: - - - spnSeqStartVal - - - - - - - End sequence at this value - - - End &Value: - - - spnSeqEndVal - - - - - - - Go from start to end in steps of this amount - - - Increment &By: - - - spnSeqIncVal - - - - - - - Format sequence using special characters<table cellspacing="3"> -<tr><td>#</td><td>Number or space</td></tr> -<tr><td>$</td><td>Number or '0'</td></tr> -<tr><td>*</td><td>Number or '*'</td></tr> -<tr><td>Other</td><td>Insert literally</td></tr> -</table> - - - &Format: - - - linSeqFormat - - - - - - - Create a data sequence - - - Sequence: - - - - - - - Get a data sequence from a file - - - Sequence File: - - - - - - - false - - - Save the symbols to files - - - Generate Bar Codes: - - - - + + + + + + 0 + 0 + + + + Create Sequence + + + Generate a sequence + + + + + + Start sequence at this value + + + &Start Value: + + + spnSeqStartVal + + - - - - - - Start sequence at this value - - - true - - - 999999999 - - - - - - - End sequence at this value - - - 999999999 - - - - - - - Go from start to end in steps of this amount - - - 1 - - - 999999999 - - - - - - - Format sequence using special characters<table cellspacing="3"> + + + + Start sequence at this value + + + true + + + 999999999 + + + + + + + End sequence at this value + + + End &Value: + + + spnSeqEndVal + + + + + + + End sequence at this value + + + 999999999 + + + + + + + Go from start to end in steps of this amount + + + Increment &By: + + + spnSeqIncVal + + + + + + + Go from start to end in steps of this amount + + + 1 + + + 999999999 + + + + + + + Format sequence using special characters<table cellspacing="3"> <tr><td>#</td><td>Number or space</td></tr> <tr><td>$</td><td>Number or '0'</td></tr> <tr><td>*</td><td>Number or '*'</td></tr> <tr><td>Other</td><td>Insert literally</td></tr> </table> + + + F&ormat: + + + linSeqFormat + + + + + + + Format sequence using special characters<table cellspacing="3"> +<tr><td>#</td><td>Number or space</td></tr> +<tr><td>$</td><td>Number or '0'</td></tr> +<tr><td>*</td><td>Number or '*'</td></tr> +<tr><td>Other</td><td>Insert literally</td></tr> +</table> + + + $$$$$$ + + + + + + + + + Qt::Horizontal - - $$$$$$ + + + 40 + 20 + - + - Create a data sequence + Generate a data sequence Crea&te - - - - Get a data sequence from a file - - - &Import... - - - - - - - false - - - Save the symbols to files - - - &Export... - - - - - - + + + + + + Qt::Vertical + + + + 40 + 20 + + + + + @@ -256,6 +225,26 @@ + + + + Import a data sequence from a file + + + &From File... + + + + + + + Clear the sequence data + + + C&lear + + + @@ -270,12 +259,15 @@ - + + + false + - Clear the sequence data + Save the symbols to files - C&lear + &Export... diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index 4b5f82ac..2849e2ed 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -478,13 +478,18 @@ void MainWindow::help() void MainWindow::open_data_dialog() { - DataWindow dlg(txtData->text()); + DataWindow dlg(txtData->text(), chkEscape->isChecked()); (void) dlg.exec(); if (dlg.Valid) { const bool updated = txtData->text() != dlg.DataOutput; txtData->setText(dlg.DataOutput); if (updated) { - statusBar->showMessage(tr("Updated data"), tempMessageTimeout); + if (dlg.Escaped && !chkEscape->isChecked()) { + chkEscape->setChecked(true); + statusBar->showMessage(tr("Set \"Parse Escapes\", updated data"), tempMessageTimeout); + } else { + statusBar->showMessage(tr("Updated data"), tempMessageTimeout); + } } } } diff --git a/frontend_qt/sequencewindow.cpp b/frontend_qt/sequencewindow.cpp index f5dac8d3..564aabfc 100644 --- a/frontend_qt/sequencewindow.cpp +++ b/frontend_qt/sequencewindow.cpp @@ -56,7 +56,7 @@ SequenceWindow::SequenceWindow(BarcodeItem *bc) : m_bc(bc) connect(btnSeqClear, SIGNAL( clicked( bool )), SLOT(clear_preview())); connect(btnSeqCreate, SIGNAL( clicked( bool )), SLOT(create_sequence())); connect(txtSeqPreview, SIGNAL( textChanged()), SLOT(check_generate())); - connect(btnSeqImport, SIGNAL( clicked( bool )), SLOT(import())); + connect(btnSeqFromFile, SIGNAL( clicked( bool )), SLOT(from_file())); connect(btnSeqExport, SIGNAL( clicked( bool )), SLOT(generate_sequence())); } @@ -166,14 +166,12 @@ void SequenceWindow::check_generate() preview_copy = txtSeqPreview->toPlainText(); if (preview_copy.isEmpty()) { btnSeqExport->setEnabled(false); - lblSeqExport->setEnabled(false); } else { btnSeqExport->setEnabled(true); - lblSeqExport->setEnabled(true); } } -void SequenceWindow::import() +void SequenceWindow::from_file() { QSettings settings; #if QT_VERSION < 0x60000 diff --git a/frontend_qt/sequencewindow.h b/frontend_qt/sequencewindow.h index 4d28ddc1..042f7a6d 100644 --- a/frontend_qt/sequencewindow.h +++ b/frontend_qt/sequencewindow.h @@ -39,7 +39,7 @@ private slots: void clear_preview(); void create_sequence(); void check_generate(); - void import(); + void from_file(); void generate_sequence(); protected: