1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7
8
9 #include "../formatidlist.h"
10 #include "barcodegenerator.h"
11 #include "commonstrings.h"
12 #include "iconmanager.h"
13 #include "loadsaveplugin.h"
14 #include "scpaths.h"
15 #include "scribuscore.h"
16 #include "ui/colorsandfills.h"
17 #include "undomanager.h"
18
19 #include <QDebug>
20 #include <QTextStream>
21 #include <QStandardItemModel>
22 #include <QTimer>
23 #include <QThread>
24
BarcodeType(const QString & cmd,const QString & exa,const QString & exaop)25 BarcodeType::BarcodeType(const QString &cmd, const QString &exa, const QString &exaop)
26 {
27 command = cmd;
28 exampleContents = exa;
29 exampleOptions = exaop;
30 }
31
BarcodeGenerator(QWidget * parent,const char * name)32 BarcodeGenerator::BarcodeGenerator(QWidget* parent, const char* name)
33 : QDialog(parent),
34 paintBarcodeTimer(nullptr)
35 {
36 ui.setupUi(this);
37 setObjectName(name);
38 setModal(true);
39
40 ui.bcodeBox->layout()->setAlignment(Qt::AlignTop);
41 ui.colorBox->layout()->setAlignment(Qt::AlignTop);
42
43 connect(&thread, SIGNAL(renderedImage(QString)),this, SLOT(updatePreview(QString)));
44
45 /*
46 * We extract the barcode information from the BWIPP metadata which looks like this:
47 *
48 * % --BEGIN ENCODER gs1-128--
49 * % --REQUIRES preamble raiseerror renlinear code128--
50 * % --DESC: GS1-128
51 * % --EXAM: (01)95012345678903(3103)000123
52 * % --EXOP: includetext
53 * % --RNDR: renlinear
54 *
55 */
56
57 QFile f(ScPaths::instance().shareDir() + QString("/plugins/barcode.ps"));
58 if(!f.open(QIODevice::ReadOnly))
59 {
60 qDebug()<<"Barcodegenerator unable to open "<<f.fileName();
61 return;
62 }
63 QTextStream ts(&f);
64 QString bwipp = ts.readAll();
65 f.close();
66
67 QRegExp rx(
68 "[\\r\\n]+% --BEGIN (RESOURCE|RENDERER|ENCODER) ([\\w-]+)--[\\r\\n]+"
69 "(.*[\\r\\n]+)?"
70 "(%%BeginResource.*[\\r\\n]+)"
71 "% --END \\1 \\2--[\\r\\n]+");
72 rx.setMinimal(true);
73 int pos = 0;
74 while ( (pos = rx.indexIn(bwipp, pos)) != -1 )
75 {
76 int len = rx.matchedLength();
77 QString restype = rx.cap(1);
78 QString resname = rx.cap(2);
79 QString reshead = rx.cap(3);
80 QString resbody = rx.cap(4);
81
82 resbodys[resname] = resbody;
83
84 if (restype=="ENCODER")
85 {
86 QRegExp rxhead(
87 "% --REQUIRES (.*)--[\\r\\n]+"
88 "% --DESC:(.*)[\\r\\n]+"
89 "% --EXAM:(.*)[\\r\\n]+"
90 "% --EXOP:(.*)[\\r\\n]+"
91 "% --RNDR:(.*)[\\r\\n]+"
92 );
93 if (rxhead.indexIn(reshead) >= 0)
94 {
95 resreqs[resname] = rxhead.cap(1).trimmed();
96 resdescs[resname] = rxhead.cap(2).trimmed();
97 resexams[resname] = rxhead.cap(3).trimmed();
98 resexops[resname] = rxhead.cap(4).trimmed();
99 resrndrs[resname] = rxhead.cap(5).trimmed();
100 encoderlist.append(resname);
101 }
102 }
103 pos += len;
104 }
105
106 foreach (const QString& enc, encoderlist)
107 map[resdescs[enc]] = BarcodeType(enc, resexams[enc], resexops[enc]);
108
109 /*
110 * Ultimately all of this static data about the capabilities of each barcode
111 * encoder will be replaced by data read from the barcode.ps metadata, when
112 * such data exists...
113 *
114 */
115
116 // Content for the version and ecc combos
117 resvers["qrcode"] = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40";
118 resecls["qrcode"] = "L,Q,M,H";
119 resvers["gs1qrcode"] = resvers["qrcode"];
120 resecls["gs1qrcode"] = resecls["qrcode"];
121 resvers["hibcqrcode"] = resvers["qrcode"];
122 resecls["hibcqrcode"] = resecls["qrcode"];
123 resvers["microqrcode"] = "M1,M2,M3,M4";
124 resecls["microqrcode"] = "L,Q,M,H";
125 resvers["datamatrix"] = "10x10,12x12,14x14,16x16,18x18,20x20,22x22,24x24,26x26,32x32,36x36,40x40,44x44,48x48,52x52,64x64,72x72,80x80,88x88,96x96,104x104,120x120,132x132,144x144,8x18,8x32,12x26,12x36,16x36,16x48";
126 resecls["datamatrix"] = "";
127 resvers["gs1datamatrix"] = resvers["datamatrix"];
128 resecls["gs1datamatrix"] = resvers["datamatrix"];
129 resvers["hibcdatamatrix"] = resvers["datamatrix"];
130 resecls["hibcdatamatrix"] = resecls["datamatrix"];
131 resvers["azteccode"] = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32";
132 resvlbl["azteccode"] = "Layers";
133 resecls["azteccode"] = "5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95";
134 resvers["azteccodecompact"] = "1,2,3,4";
135 resvlbl["azteccodecompact"] = resvlbl["azteccode"];
136 resecls["azteccodecompact"] = resecls["azteccode"];
137 resvers["pdf417"] = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30";
138 resvlbl["pdf417"] = "Columns";
139 resecls["pdf417"] = "1,2,3,4,5";
140 resvers["pdf417compact"] = resvers["pdf417"];
141 resvlbl["pdf417compact"] = resvlbl["pdf417"];
142 resecls["pdf417compact"] = resecls["pdf417"];
143 resvers["hibcpdf417"] = resvers["pdf417"];
144 resvlbl["hibcpdf417"] = resvlbl["pdf417"];
145 resecls["hibcpdf417"] = resecls["pdf417"];
146 resvers["micropdf417"] = "1x11,1x14,1x17,1x20,1x24,1x28,2x8,2x11,2x14,2x17,2x20,2x23,2x26,3x6,3x8,3x10,3x12,3x15,3x20,3x26,3x32,3x38,3x44,4x4,4x6,4x8,4x10,4x12,4x15,4x20,4x26,4x32,4x38,4x44";
147 resecls["micropdf417"] = "";
148 resvers["hibcmicropdf417"] = resvers["micropdf417"];
149 resecls["hibcmicropdf417"] = resecls["micropdf417"];
150 resvers["hanxin"] = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84";
151 resecls["hanxin"] = "L1,L2,L3,L4";
152 resecls["ultracode"] = "EC0,EC1,EC2,EC3,EC4,EC5";
153
154
155 // Which options checkboxes are enabled for each encoder
156 QStringList includetextAvail = encoderlist;
157 foreach (const QString& enc, includetextAvail)
158 resincludetextAvail[enc] = true;
159
160 QStringList guardwhitespaceAvail;
161 guardwhitespaceAvail << "ean13" << "ean8" << "isbn" << "ismn" << "issn" << "ean13composite" << "ean8composite";
162 foreach (const QString& enc, guardwhitespaceAvail)
163 resguardwhitespaceAvail[enc] = true;
164
165 QStringList includecheckAvail;
166 includecheckAvail << "bc412" << "channelcode" << "code11" << "code2of5" << "coop2of5" << "datalogic2of5"
167 << "iata2of5" << "industrial2of5" << "matrix2of5" << "code39" << "code39ext"
168 << "code93" << "code93ext" << "interleaved2of5" << "msi" << "rationalizedCodabar";
169 foreach (const QString& enc, includecheckAvail)
170 resincludecheckAvail[enc] = true;
171
172 QStringList includecheckintextAvail;
173 includecheckintextAvail << "bc412" << "code11" << "code2of5" << "coop2of5" << "datalogic2of5" << "iata2of5"
174 << "industrial2of5" << "matrix2of5" << "code39" << "code39ext" << "interleaved2of5"
175 << "japanpost" << "msi" << "planet" << "plessey" << "postnet" << "rationalizedCodabar" << "royalmail";
176 foreach (const QString& enc, includecheckintextAvail)
177 resincludecheckintextAvail[enc] = true;
178
179 QStringList parseAvail;
180 parseAvail << "azteccode" << "azteccodecompact" << "codablockf" << "hibccodablockf" << "code128" << "hibccode128" << "code16k" << "code39ext" << "code49"
181 << "code93ext" << "codeone" << "datamatrix" << "hibcdatamatrix" << "maxicode" << "micropdf417" << "hibcmicropdf417" << "pdf417" << "hibcpdf417"
182 << "pdf417compact" << "posicode" << "qrcode" << "hibcqrcode" << "microqrcode" << "telepen" << "hanxin" << "dotcode" << "ultracode";
183 foreach (const QString& enc, parseAvail)
184 resparseAvail[enc] = true;
185
186 QStringList parsefncAvail;
187 parsefncAvail << "codablockf" << "code128" << "code16k" << "code49" << "code93" << "codeone"
188 << "datamatrix" << "posicode" << "qrcode" << "microqrcode" << "dotcode" << "ultracode";
189 foreach (const QString& enc, parsefncAvail)
190 resparsefncAvail[enc] = true;
191
192 // Building up the bcFamilyCombo grouping the formats for readablity
193 ui.bcFamilyCombo->addItem(tr("Select a barcode family")); // to prevent 1st gs call
194 ui.bcFamilyCombo->insertSeparator(999);
195
196 // Building up the bcCombo grouping the formats for readablity
197 ui.bcCombo->addItem(tr("Select a barcode format")); // to prevent 1st gs call
198 ui.bcCombo->insertSeparator(999);
199
200 QString familyName;
201 QStringList bcNames;
202 bcNames << "EAN-13" << "EAN-8" << "UPC-A" << "UPC-E" << "ISBN" << "ISMN" << "ISSN";
203 familyName = tr("Point of Sale");
204 familyList.append(familyName);
205 familyItems.insert(familyName, bcNames);
206
207 bcNames.clear();
208 bcNames << "GS1-14" << "GS1 Data Matrix" << "GS1 QR Code" << "GS1-128" << "ITF-14" << "SSCC-18";
209 familyName = tr("Supply Chain");
210 familyList.append(familyName);
211 familyItems.insert(familyName, bcNames);
212
213 bcNames.clear();
214 bcNames << "QR Code" << "Micro QR Code" << "Data Matrix" << "Aztec Code" << "Compact Aztec Code"
215 << "Aztec Runes" << "PDF417" << "Compact PDF417" << "MicroPDF417" << "Han Xin Code"
216 << "DotCode" << "Ultracode";
217 familyName = tr("Two-dimensional symbols");
218 familyList.append(familyName);
219 familyItems.insert(familyName, bcNames);
220
221 bcNames.clear();
222 bcNames << "Code 128" << "Code 39" << "Code 39 Extended" << "Code 93" << "Code 93 Extended"
223 << "Interleaved 2 of 5 (ITF)";
224 familyName = tr("One-dimensional symbols");
225 familyList.append(familyName);
226 familyItems.insert(familyName, bcNames);
227
228 bcNames.clear();
229 bcNames << "GS1 DataBar Omnidirectional" << "GS1 DataBar Stacked Omnidirectional"
230 << "GS1 DataBar Expanded" << "GS1 DataBar Expanded Stacked" << "GS1 DataBar Truncated"
231 << "GS1 DataBar Stacked" << "GS1 DataBar Limited" << "GS1 North American Coupon";
232 familyName = tr("GS1 DataBar family");
233 familyList.append(familyName);
234 familyItems.insert(familyName, bcNames);
235
236 bcNames.clear();
237 bcNames << "AusPost 4 State Customer Code" << "Deutsche Post Identcode" << "Deutsche Post Leitcode"
238 << "Japan Post 4 State Customer Code" << "Royal Dutch TPG Post KIX"
239 << "Royal Mail 4 State Customer Code" << "USPS Intelligent Mail" << "USPS PLANET" << "USPS POSTNET";
240 familyName = tr("Postal symbols");
241 familyList.append(familyName);
242 familyItems.insert(familyName, bcNames);
243
244 bcNames.clear();
245 bcNames << "Italian Pharmacode" << "Pharmaceutical Binary Code" << "Two-track Pharmacode"
246 << "Pharmazentralnummer (PZN)" << "HIBC Codablock F" << "HIBC Code 128" << "HIBC Code 39"
247 << "HIBC Data Matrix" << "HIBC MicroPDF417" << "HIBC PDF417" << "HIBC QR Code";
248 familyName = tr("Pharmaceutical symbols");
249 familyList.append(familyName);
250 familyItems.insert(familyName, bcNames);
251
252 bcNames.clear();
253 bcNames << "Code 11" << "Codabar" << "Code 25" << "COOP 2 of 5" << "Datalogic 2 of 5" << "IATA 2 of 5"
254 << "Industrial 2 of 5" << "Matrix 2 of 5" << "MSI Modified Plessey" << "Plessey UK"
255 << "PosiCode" << "Telepen" << "Telepen Numeric"<< "Code 16K" << "Codablock F" << "Code 49"
256 << "Code One";
257 familyName = tr("Less-used symbols");
258 familyList.append(familyName);
259 familyItems.insert(familyName, bcNames);
260
261 bcNames.clear();
262 bcNames << "EAN-13 Composite" << "EAN-8 Composite" << "UPC-A Composite" << "UPC-E Composite"
263 << "GS1 DataBar Omnidirectional Composite" << "GS1 DataBar Stacked Omnidirectional Composite"
264 << "GS1 DataBar Expanded Composite" << "GS1 DataBar Expanded Stacked Composite"
265 << "GS1 DataBar Truncated Composite" << "GS1 DataBar Stacked Composite"
266 << "GS1 DataBar Limited Composite" << "GS1-128 Composite";
267 familyName = tr("GS1 Composite symbols");
268 familyList.append(familyName);
269 familyItems.insert(familyName, bcNames);
270
271 ui.bcFamilyCombo->addItems(familyList);
272
273 /*
274 * End of the hard-coded data
275 *
276 */
277
278 guiColor = ui.codeEdit->palette().color(QPalette::Window);
279
280 ui.okButton->setText(CommonStrings::tr_OK);
281 ui.cancelButton->setText(CommonStrings::tr_Cancel);
282 ui.resetButton->setIcon(IconManager::instance().loadIcon("u_undo16.png"));
283
284 if (ScCore->primaryMainWindow()->doc->PageColors.contains("Black"))
285 {
286 lnColor = ScCore->primaryMainWindow()->doc->PageColors["Black"];
287 txtColor = ScCore->primaryMainWindow()->doc->PageColors["Black"];
288 ui.linesLabel->setToolTip("Black");
289 ui.txtLabel->setToolTip("Black");
290 }
291 else
292 {
293 ui.linesLabel->setToolTip("n.a.");
294 ui.txtLabel->setToolTip("n.a.");
295 }
296 if (ScCore->primaryMainWindow()->doc->PageColors.contains("White"))
297 {
298 bgColor = ScCore->primaryMainWindow()->doc->PageColors["White"];
299 ui.bgLabel->setToolTip("White");
300 }
301 else
302 ui.bgLabel->setToolTip("n.a.");
303
304 paintColorSample(ui.linesLabel, lnColor);
305 paintColorSample(ui.txtLabel, txtColor);
306 paintColorSample(ui.bgLabel, bgColor);
307
308 paintBarcodeTimer=new QTimer(this);
309 paintBarcodeTimer->setSingleShot(true);
310 connect(paintBarcodeTimer, SIGNAL(timeout()), this, SLOT(paintBarcode()));
311
312 connect(ui.bcFamilyCombo, SIGNAL(activated(QString)), this, SLOT(bcFamilyComboChanged()));
313 connect(ui.bcCombo, SIGNAL(activated(QString)), this, SLOT(bcComboChanged()));
314 connect(ui.bgColorButton, SIGNAL(clicked()), this, SLOT(bgColorButton_pressed()));
315 connect(ui.lnColorButton, SIGNAL(clicked()), this, SLOT(lnColorButton_pressed()));
316 connect(ui.txtColorButton, SIGNAL(clicked()), this, SLOT(txtColorButton_pressed()));
317 connect(ui.okButton, SIGNAL(clicked()), this, SLOT(okButton_pressed()));
318 connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelButton_pressed()));
319 connect(ui.codeEdit, SIGNAL(textChanged(QString)), this, SLOT(codeEdit_textChanged(QString)));
320 connect(ui.resetButton, SIGNAL(clicked()), this, SLOT(resetButton_clicked()));
321 bcComboChanged();
322
323 }
324
~BarcodeGenerator()325 BarcodeGenerator::~BarcodeGenerator()
326 {
327 if (!paintBarcodeTimer)
328 return;
329 delete paintBarcodeTimer;
330 paintBarcodeTimer = nullptr;
331 }
332
updateOptions()333 void BarcodeGenerator::updateOptions()
334 {
335 QString enc=map[ui.bcCombo->currentText()].command;
336
337 ui.formatLabel->setText(resvlbl.contains(enc) ? resvlbl[enc] + ":" : "Version:");
338 ui.formatCombo->blockSignals(true);
339 ui.formatCombo->clear();
340 ui.formatCombo->addItem("Auto");
341 if (resvers.contains(enc))
342 {
343 ui.formatCombo->insertSeparator(999);
344 ui.formatCombo->addItems(resvers[enc].split(","));
345 ui.formatLabel->setEnabled(true);
346 ui.formatCombo->setEnabled(true);
347 }
348 else
349 {
350 ui.formatLabel->setEnabled(false);
351 ui.formatCombo->setEnabled(false);
352 }
353 ui.formatCombo->blockSignals(false);
354
355 ui.eccCombo->blockSignals(true);
356 ui.eccCombo->clear();
357 ui.eccCombo->addItem("Auto");
358 if (resecls.contains(enc))
359 {
360 ui.eccCombo->insertSeparator(999);
361 ui.eccCombo->addItems(resecls[enc].split(","));
362 ui.eccLabel->setEnabled(true);
363 ui.eccCombo->setEnabled(true);
364 }
365 else
366 {
367 ui.eccLabel->setEnabled(false);
368 ui.eccCombo->setEnabled(false);
369 }
370 ui.eccCombo->blockSignals(false);
371
372 }
373
374
bcFamilyComboChanged()375 void BarcodeGenerator::bcFamilyComboChanged()
376 {
377 ui.bcCombo->blockSignals(true);
378 ui.bcCombo->clear();
379 ui.bcCombo->addItem(tr("Select a barcode format")); // to prevent 1st gs call
380 ui.bcCombo->insertSeparator(999);
381 ui.bcCombo->addItems(familyItems[ui.bcFamilyCombo->currentText()]);
382 ui.bcCombo->blockSignals(false);
383 bcComboChanged();
384 }
385
bcComboChanged(int i)386 void BarcodeGenerator::bcComboChanged(int i)
387 {
388 bcComboChanged();
389 }
390
bcComboChanged()391 void BarcodeGenerator::bcComboChanged()
392 {
393 updateOptions();
394
395 if (ui.bcCombo->currentIndex() == 0)
396 {
397 ui.okButton->setEnabled(false);
398 ui.sampleLabel->setText(tr("Select Type"));
399 ui.codeEdit->clear();
400 ui.codeEdit->setEnabled(false);
401 ui.optionsEdit->clear();
402 ui.optionsEdit->setEnabled(false);
403 ui.includetextCheck->setEnabled(false);
404 ui.guardwhitespaceCheck->setEnabled(false);
405 ui.includecheckCheck->setEnabled(false);
406 ui.includecheckintextCheck->setEnabled(false);
407 ui.parseCheck->setEnabled(false);
408 ui.parsefncCheck->setEnabled(false);
409 ui.formatLabel->setEnabled(false);
410 ui.formatCombo->setEnabled(false);
411 ui.eccLabel->setEnabled(false);
412 ui.eccCombo->setEnabled(false);
413 ui.bgColorButton->setEnabled(false);
414 ui.lnColorButton->setEnabled(false);
415 ui.txtColorButton->setEnabled(false);
416 return;
417 }
418
419 ui.codeEdit->setEnabled(true);
420 ui.optionsEdit->setEnabled(true);
421 ui.bgColorButton->setEnabled(true);
422 ui.lnColorButton->setEnabled(true);
423 ui.txtColorButton->setEnabled(true);
424 ui.okButton->setEnabled(true);
425
426 QString s = ui.bcCombo->currentText();
427 ui.codeEdit->blockSignals(true);
428 ui.codeEdit->setText(map[s].exampleContents);
429 ui.codeEdit->blockSignals(false);
430 ui.optionsEdit->blockSignals(true);
431 ui.optionsEdit->setText(map[s].exampleOptions);
432 ui.optionsEdit->blockSignals(false);
433
434 QString enc = map[s].command;
435 ui.includetextCheck->setEnabled(resincludetextAvail[enc]);
436 ui.guardwhitespaceCheck->setEnabled(resguardwhitespaceAvail[enc]);
437 ui.includecheckCheck->setEnabled(resincludecheckAvail[enc]);
438 ui.includecheckintextCheck->setEnabled(resincludetextAvail[enc] && resincludecheckintextAvail[enc]);
439 ui.parseCheck->setEnabled(resparseAvail[enc]);
440 ui.parsefncCheck->setEnabled(resparsefncAvail[enc]);
441
442 updateUIFromOptionsText();
443
444 enqueuePaintBarcode(0);
445 }
446
enqueuePaintBarcode(int delay)447 void BarcodeGenerator::enqueuePaintBarcode(int delay)
448 {
449 ui.okButton->setEnabled(false);
450 // paintBarcode();
451 paintBarcodeTimer->start(delay);
452 }
453
updateOptionsTextFromUI()454 void BarcodeGenerator::updateOptionsTextFromUI()
455 {
456 QString opts = ui.optionsEdit->text();
457
458 if (ui.includetextCheck->isChecked())
459 {
460 if (!opts.contains(QRegExp("\\bincludetext\\b")))
461 opts.append(" includetext");
462 }
463 else
464 {
465 opts.replace(QRegExp("\\bincludetext\\b")," ");
466 }
467
468 if (ui.guardwhitespaceCheck->isChecked())
469 {
470 if (!opts.contains(QRegExp("\\bguardwhitespace\\b")))
471 opts.append(" guardwhitespace");
472 }
473 else
474 {
475 opts.replace(QRegExp("\\bguardwhitespace\\b")," ");
476 }
477
478 if (ui.includecheckCheck->isChecked())
479 {
480 if (!opts.contains(QRegExp("\\bincludecheck\\b")))
481 opts.append(" includecheck");
482 }
483 else
484 {
485 opts.replace(QRegExp("\\bincludecheck\\b")," ");
486 }
487
488 if (ui.includecheckintextCheck->isChecked())
489 {
490 if (!opts.contains(QRegExp("\\bincludecheckintext\\b")))
491 opts.append(" includecheckintext");
492 }
493 else
494 {
495 opts.replace(QRegExp("\\bincludecheckintext\\b")," ");
496 }
497
498 if (ui.parseCheck->isChecked())
499 {
500 if (!opts.contains(QRegExp("\\bparse\\b")))
501 opts.append(" parse");
502 }
503 else
504 {
505 opts.replace(QRegExp("\\bparse\\b")," ");
506 }
507
508 if (ui.parsefncCheck->isChecked())
509 {
510 if (!opts.contains(QRegExp("\\bparsefnc\\b")))
511 opts.append(" parsefnc");
512 }
513 else
514 {
515 opts.replace(QRegExp("\\bparsefnc\\b")," ");
516 }
517
518 QString enc = map[ui.bcCombo->currentText()].command;
519 QString vlbl = resvlbl.contains(enc) ? resvlbl[enc].toLower() : "version";
520
521 if (ui.formatCombo->currentIndex() != 0)
522 {
523 QString t = ui.formatCombo->currentText();
524 if (!opts.contains(QRegExp("\\b" + QRegExp::escape(vlbl) + "=.*\\b")))
525 opts.append(" " + vlbl + "=" + t);
526 else
527 opts.replace(QRegExp("\\b" + QRegExp::escape(vlbl) + "=\\S*\\b"), vlbl + "=" + t);
528 }
529 else
530 {
531 opts.replace(QRegExp("\\b" + QRegExp::escape(vlbl) + "=\\S*\\b"), " ");
532 }
533
534 if (ui.eccCombo->currentIndex() != 0)
535 {
536 QString t = ui.eccCombo->currentText();
537 if (!opts.contains(QRegExp("\\beclevel=.*\\b")))
538 opts.append(" eclevel=" + t);
539 else
540 opts.replace(QRegExp("\\beclevel=\\S*\\b"), "eclevel=" + t);
541 }
542 else
543 {
544 opts.replace(QRegExp("\\beclevel=\\S*\\b")," ");
545 }
546
547 ui.optionsEdit->blockSignals(true);
548 ui.optionsEdit->setText(opts.simplified());
549 ui.optionsEdit->blockSignals(false);
550
551 }
552
updateUIFromOptionsText()553 void BarcodeGenerator::updateUIFromOptionsText()
554 {
555 ui.includetextCheck->blockSignals(true);
556 ui.includetextCheck->setChecked(ui.optionsEdit->text().contains(QRegExp("\\bincludetext\\b")));
557 ui.includetextCheck->blockSignals(false);
558
559 ui.guardwhitespaceCheck->blockSignals(true);
560 ui.guardwhitespaceCheck->setChecked(ui.optionsEdit->text().contains(QRegExp("\\bguardwhitespace\\b")));
561 ui.guardwhitespaceCheck->blockSignals(false);
562
563 ui.includecheckCheck->blockSignals(true);
564 ui.includecheckCheck->setChecked(ui.optionsEdit->text().contains(QRegExp("\\bincludecheck\\b")));
565 ui.includecheckCheck->blockSignals(false);
566
567 ui.includecheckintextCheck->blockSignals(true);
568 ui.includecheckintextCheck->setChecked(ui.optionsEdit->text().contains(QRegExp("\\bincludecheckintext\\b")));
569 ui.includecheckintextCheck->blockSignals(false);
570
571 ui.parseCheck->blockSignals(true);
572 ui.parseCheck->setChecked(ui.optionsEdit->text().contains(QRegExp("\\bparse\\b")));
573 ui.parseCheck->blockSignals(false);
574
575 ui.parsefncCheck->blockSignals(true);
576 ui.parsefncCheck->setChecked(ui.optionsEdit->text().contains(QRegExp("\\bparsefnc\\b")));
577 ui.parsefncCheck->blockSignals(false);
578
579 QString enc = map[ui.bcCombo->currentText()].command;
580 QString vlbl = resvlbl.contains(enc) ? resvlbl[enc].toLower() : "version";
581
582 QRegExp rxf("\\b" + QRegExp::escape(vlbl) + "=(\\S*)\\b");
583 ui.formatCombo->blockSignals(true);
584 if (ui.optionsEdit->text().contains(rxf))
585 {
586 int idx = ui.formatCombo->findText(rxf.cap(1));
587 if (idx == -1)
588 idx = 0;
589 ui.formatCombo->setCurrentIndex(idx);
590 }
591 else
592 {
593 ui.formatCombo->setCurrentIndex(0);
594 }
595 ui.formatCombo->blockSignals(false);
596
597 QRegExp rxe("\\beclevel=(\\S*)\\b");
598 ui.eccCombo->blockSignals(true);
599 if (ui.optionsEdit->text().contains(rxe))
600 {
601 int idx=ui.eccCombo->findText(rxe.cap(1));
602 if (idx == -1)
603 idx = 0;
604 ui.eccCombo->setCurrentIndex(idx);
605 }
606 else
607 {
608 ui.eccCombo->setCurrentIndex(0);
609 }
610 ui.eccCombo->blockSignals(false);
611 }
612
updatePreview(const QString & errorMsg)613 void BarcodeGenerator::updatePreview(const QString& errorMsg)
614 {
615 QString pngFile = QDir::toNativeSeparators(ScPaths::tempFileDir() + "bcode.png");
616 if (errorMsg.isEmpty())
617 {
618 ui.sampleLabel->setPixmap(QPixmap(pngFile));
619 ui.okButton->setEnabled(true);
620 }
621 else
622 {
623 ui.sampleLabel->setText("<qt>" + errorMsg + "</qt>");
624 }
625 }
626
on_includetextCheck_stateChanged(int)627 void BarcodeGenerator::on_includetextCheck_stateChanged(int)
628 {
629 updateOptionsTextFromUI();
630 enqueuePaintBarcode(0);
631 }
632
on_guardwhitespaceCheck_stateChanged(int)633 void BarcodeGenerator::on_guardwhitespaceCheck_stateChanged(int)
634 {
635 updateOptionsTextFromUI();
636 enqueuePaintBarcode(0);
637 }
638
on_includecheckCheck_stateChanged(int)639 void BarcodeGenerator::on_includecheckCheck_stateChanged(int)
640 {
641 updateOptionsTextFromUI();
642 enqueuePaintBarcode(0);
643 }
644
on_includecheckintextCheck_stateChanged(int)645 void BarcodeGenerator::on_includecheckintextCheck_stateChanged(int)
646 {
647 updateOptionsTextFromUI();
648 enqueuePaintBarcode(0);
649 }
650
on_parseCheck_stateChanged(int)651 void BarcodeGenerator::on_parseCheck_stateChanged(int)
652 {
653 updateOptionsTextFromUI();
654 enqueuePaintBarcode(0);
655 }
656
on_parsefncCheck_stateChanged(int)657 void BarcodeGenerator::on_parsefncCheck_stateChanged(int)
658 {
659 updateOptionsTextFromUI();
660 enqueuePaintBarcode(0);
661 }
662
on_formatCombo_currentIndexChanged(int)663 void BarcodeGenerator::on_formatCombo_currentIndexChanged(int)
664 {
665 updateOptionsTextFromUI();
666 enqueuePaintBarcode(0);
667 }
668
on_eccCombo_currentIndexChanged(int)669 void BarcodeGenerator::on_eccCombo_currentIndexChanged(int)
670 {
671 updateOptionsTextFromUI();
672 enqueuePaintBarcode(0);
673 }
674
paintColorSample(QLabel * l,const ScColor & c)675 void BarcodeGenerator::paintColorSample(QLabel *l, const ScColor & c)
676 {
677 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
678 QPixmap currentPixmap = l->pixmap(Qt::ReturnByValue);
679 #else
680 QPixmap currentPixmap = l->pixmap() ? *(l->pixmap()) : QPixmap();
681 #endif
682
683 double pixelRatio = l->devicePixelRatioF();
684 QSize pixmapSize(currentPixmap.width(), currentPixmap.height());
685 if (currentPixmap.isNull())
686 {
687 QRect rect = l->frameRect();
688 pixmapSize = QSize(rect.width() * pixelRatio, rect.height() * pixelRatio);
689 }
690 QPixmap pm(pixmapSize.width(), pixmapSize.height());
691 pm.fill(c.getRawRGBColor()); // brute force sc2qt color convert for preview
692 l->setPixmap(pm);
693 }
694
bgColorButton_pressed()695 void BarcodeGenerator::bgColorButton_pressed()
696 {
697 ColorsAndFillsDialog d(this, &ScCore->primaryMainWindow()->doc->docGradients, ScCore->primaryMainWindow()->doc->PageColors, "", &ScCore->primaryMainWindow()->doc->docPatterns, ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow());
698 if (!d.exec())
699 return;
700
701 QString selectedColorName = d.selectedColorName();
702 if (selectedColorName == CommonStrings::None)
703 return;
704
705 bgColor = d.selectedColor();
706 ui.bgLabel->setToolTip(d.selectedColorName());
707 paintColorSample(ui.bgLabel, bgColor);
708 enqueuePaintBarcode(0);
709 }
710
lnColorButton_pressed()711 void BarcodeGenerator::lnColorButton_pressed()
712 {
713 ColorsAndFillsDialog d(this, &ScCore->primaryMainWindow()->doc->docGradients, ScCore->primaryMainWindow()->doc->PageColors, "", &ScCore->primaryMainWindow()->doc->docPatterns, ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow());
714 if (!d.exec())
715 return;
716
717 QString selectedColorName = d.selectedColorName();
718 if (selectedColorName == CommonStrings::None)
719 return;
720
721 lnColor = d.selectedColor();
722 ui.linesLabel->setToolTip(d.selectedColorName());
723 paintColorSample(ui.linesLabel, lnColor);
724 enqueuePaintBarcode(0);
725 }
726
txtColorButton_pressed()727 void BarcodeGenerator::txtColorButton_pressed()
728 {
729 ColorsAndFillsDialog d(this, &ScCore->primaryMainWindow()->doc->docGradients, ScCore->primaryMainWindow()->doc->PageColors, "", &ScCore->primaryMainWindow()->doc->docPatterns, ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow());
730 if (!d.exec())
731 return;
732
733 QString selectedColorName = d.selectedColorName();
734 if (selectedColorName == CommonStrings::None)
735 return;
736
737 txtColor = d.selectedColor();
738 ui.txtLabel->setToolTip(d.selectedColorName());
739 paintColorSample(ui.txtLabel, txtColor);
740 enqueuePaintBarcode(0);
741 }
742
okButton_pressed()743 void BarcodeGenerator::okButton_pressed()
744 {
745 QString psFile = QDir::toNativeSeparators(ScPaths::tempFileDir() + "bcode.ps");
746
747 // no need to call paintBarcode(pngFile, 300); because
748 // it's created by previous run...
749 hide();
750 const FileFormat * fmt = LoadSavePlugin::getFormatByExt("ps");
751
752 UndoTransaction tran;
753 if (UndoManager::undoEnabled())
754 {
755 tran = UndoManager::instance()->beginTransaction(
756 ScCore->primaryMainWindow()->doc->currentPage()->getUName(),
757 Um::IImageFrame,
758 Um::ImportBarcode,
759 ui.bcCombo->currentText() + " (" + ui.codeEdit->text() + ")",
760 Um::IEPS);
761 }
762
763 if (fmt)
764 {
765 fmt->loadFile(psFile, LoadSavePlugin::lfUseCurrentPage|LoadSavePlugin::lfInteractive|LoadSavePlugin::lfNoDialogs);
766 if (tran)
767 tran.commit();
768 }
769 accept();
770 }
771
cancelButton_pressed()772 void BarcodeGenerator::cancelButton_pressed()
773 {
774 reject();
775 }
776
codeEdit_textChanged(const QString & s)777 void BarcodeGenerator::codeEdit_textChanged(const QString& s)
778 {
779 enqueuePaintBarcode(0);
780 }
781
on_optionsEdit_textChanged(const QString & s)782 void BarcodeGenerator::on_optionsEdit_textChanged(const QString &s )
783 {
784 updateUIFromOptionsText();
785 enqueuePaintBarcode(0);
786 }
787
paintBarcode()788 void BarcodeGenerator::paintBarcode()
789 {
790 QString coloropts("barcolor=%1 showbackground backgroundcolor=%2 textcolor=%3");
791 coloropts = coloropts.arg(lnColor.name().replace('#', ""), bgColor.name().replace('#', ""), txtColor.name().replace('#', ""));
792
793 QString opts=ui.optionsEdit->text() + " " + coloropts;
794
795 // Assemble PS from encoder and requirement bodies
796 QString psCommand = "%!PS-Adobe-2.0 EPSF-2.0\n";
797 QString req;
798 QString enc = map[ui.bcCombo->currentText()].command;
799 foreach (req, resreqs[enc].split(" "))
800 psCommand.append(resbodys[req]);
801 psCommand.append(resbodys[enc]);
802 psCommand.append(
803 "errordict begin\n"
804 "/handleerror {\n"
805 "$error begin\n"
806 "errorname dup length string cvs 0 6 getinterval (bwipp.) eq {\n"
807 "(%stderr) (w) file\n"
808 "dup (\nBWIPP ERROR: ) writestring\n"
809 "dup errorname dup length string cvs writestring\n"
810 "dup ( ) writestring\n"
811 "dup errorinfo dup length string cvs writestring\n"
812 "dup (\n) writestring\n"
813 "dup flushfile end quit\n"
814 "} if\n"
815 "end //handleerror exec\n"
816 "} bind def\n"
817 "end\n"
818 );
819 QString comm("20 10 moveto <%1> <%2> /%3 /uk.co.terryburton.bwipp findresource exec\n");
820 QString bcdata(ui.codeEdit->text().toLatin1().toHex());
821 QString bcopts(opts.toLatin1().toHex());
822 comm = comm.arg(bcdata, bcopts, map[ui.bcCombo->currentText()].command);
823 psCommand.append(comm);
824 psCommand.append("showpage\n");
825
826 thread.render(psCommand);
827 }
828
829
resetButton_clicked()830 void BarcodeGenerator::resetButton_clicked()
831 {
832 bcComboChanged();
833 }
834