+ kbarcode - The Barcode Solution for KDE +

+ +

kbarcode has right now support following barcodes. Please check + the requirements and limitations:

+ + +

EAN 8:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
kbarcode Settingean
valid character setnumbers (0....9)
lenght7 + 1 Checkum Digit = 8
Checksum
+
• when the number is 7 digits long, kbarcode will create a checksum + (the 8. digits)
• +
• when the number is 8 digits long, kbarcode will check the checksum + and deny printing if wrong
• +
Size

fixed, but scalable
+ Standard: 26.73mm x 21.64mm

Remark

possible scaling:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Size Factor width + [mm] height + [mm] SC0 0.818 21.87 17.70 SC1 0.90 24.06 19.48 SC2 1.00 26.73 21.64 SC3 1.10 29.40 23.80 SC4 1.20 32.08 25.97 SC5 1.35 36.09 29.21 SC6 1.50 40.10 32.46 SC7 1.65 44.10 35.71 SC8 1.85 49.45 40.03 SC9 2.00 53.46 43.28

+ + +

+ TOP +

+ + +

EAN 13:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
kbarcode Settingean
valid character setnumbers (0.....9)
lenght12 + 1 checksum digitt = 13
Checksum
+
• when the number is 12 digits long, kbarcode will create a checksum + (the 13. digits)
• +
• when the number is 13 digits long, kbarcode will check the checksum + and deny printing if wrong
• +
Size

fixed, but scalable
+ Standard: 37.29 x 26.26mm

Remark

possible scaling:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Size Factor width + [mm] height + [mm] SC0 0.818 30.50 21.48 SC1 0.90 33.56 23.63 SC2 1.00 37.29 26.26 SC3 1.10 41.02 28.89 SC4 1.20 44.75 31.51 SC5 1.35 50.34 35.45 SC6 1.50 55.94 39.39 SC7 1.65 61.35 43.33 SC8 1.85 68.99 48.58 SC9 2.00 74.58 52.52

+ + +

+ TOP +

+ + + +

UPC-A

+ + + + + + + + + + + + + + + + + + + + + + + + + +
kbarcode SettingUPC
valid character setnumbers (0....9)
lenght11 + 1 checksum digit = 12
Checksum
+
• when the number is 11 digits long, kbarcode will create a checksum + (the 12. digits)
• +
• when the number is 12 digits long, kbarcode will check the checksum + and deny printing if wrong
• +
Size

fixed, but scalable
+ Standard: 37.29 x 26.26mm

Remark

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Size Factor width + [mm] height + [mm] SC0 0.818 30.50 21.48 SC1 0.90 33.56 23.63 SC2 1.00 37.29 26.26 SC3 1.10 41.02 28.89 SC4 1.20 44.75 31.51 SC5 1.35 50.34 35.45 SC6 1.50 55.94 39.39 SC7 1.65 61.35 43.33 SC8 1.85 68.99 48.58 SC9 2.00 74.58 52.52
+

+ +

+ TOP +

+ + +

UPC-E

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting upc valid character set numbers (0....9) lenght Systemcode 0 + 6 + 1 Checkum Digit = 8 Checksum + when the number is 7 digits long, kbarcode will create a checksum + (the 8. digits) + when the number is 8 digits long, kbarcode will check the checksum + and deny printing if wrong + Size Remark +
+ + + +

+ TOP +

+ + + +

ISBN

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting ISBN valid character set lenght Checksum Size Remark ISBN numbers are encoded as EAN-13 symbols, with an optional add-5 + trailer. The ISBN frontend of the library accepts real ISBN + numbers and deals with any hyphen and, if present, the ISBN checksum character + before encoding data. Valid representations for ISBN strings are for example: + "1-56592-292-1", "3-89721-122-X" and "3-89721-122-X + 06900".
+ + +

+ TOP +

+ + + +

code 128-B

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting code 128-B valid character set lenght Checksum Size Remark This encoding can represent all of the printing ASCII characters, from + the space (32) to DEL (127). The checksum digit is mandatory i + n this encoding.
+ + +

+ TOP +

+ + +

code 128-C

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting code 128-C valid character set lenght Checksum Size Remark + The "C" variation of Code-128 uses Code-128 symbols to represent + two digits at a time (Code-128 is made up of 104 symbols whose + interpretation is controlled by the start symbol being used). Code 128-C + is thus the most compact way to represent any even number of digits. The + encoder refuses to deal with an odd number of digits because the caller + is expected to provide proper padding to an even number of digits. (Since + Code-128 includes control symbols to switch charset, it is theoretically + possible to represent the odd digit as a Code 128-A or 128-B symbol, but + this tool doesn't currently implement this option).
+ + +

+ TOP +

+ + +

code 128 raw

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting code 128 raw valid character set lenght Checksum Size Remark Code-128 output represented symbol-by-symbol in the input string. + To override part of the problems outlined below in specifying + code128 symbols, this pseudo-encoding allows the used to specify a list + of code128 symbols separated by spaces. Each symbol is represented by + a number in the range 0-105. The list should include the leading character.The + checksum and the stop character are automatically added by the library. + Most likely this pseudo-encoding will be used with BARCODE_NO_ASCII and + some external program to supply the printed text.
+ + +

+ TOP +

+ + +

code 39

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting code 39 valid character set lenght Checksum Size Remark The code-39 standard can encode uppercase letters, digits, the blank + space, plus, minus, dot, star, dollar, slash, percent. Any + string that is only composed of such characters is accepted by the code-39 + encoder. To avoid loosing information, the encoder refuses to encode mixed-case + strings (a lowercase string is nonetheless accepted as a shortcut, but is + encoded as uppercase).
+ + +

+ TOP +

+ + +

interleaved 2 of 5

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting interleaved 2 of 5 valid character set lenght Checksum Size Remark + This encoding can only represent an even number of digits (odd digits + are represented by bars, and even digits by the interleaving + spaces). The name stresses the fact that two of the five items (bars or + spaces) allocated to each symbol are wide, while the rest are narrow. + The checksum digit is optional (can be disabled via BARCODE_NO_CHECKSUM). + Since the number of digits, including the checksum, must be even, a leading + zero is inserted in the string being encoded if needed (this is specifically + stated in the specs I have access to).
+ + +

+ TOP +

+ + +

code 128

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting code 128 valid character set lenght Checksum Size Remark Automatic selection between alphabet A, B and C of the Code-128 standard. + This encoding can represent all ASCII symbols, from 0 + (NUL) to 127 (DEL), as well as four special symbols, named F1, F2, F3, + F4. The set of symbols available in this encoding is not easily represented + as input to the barcode library, so the following convention is used. + In the input string, which is a C-language null- terminated string, the + NUL char is represented by the value 128 (0x80, 0200) and the F1-F4 characters + are represented by the values 193-196 (0xc1-0xc4, 0301-0304). The values + have been chosen to ease their representation as escape sequences. + Since the shell doesn't seem to interpret escape sequences on the command + line, the "-b" option cannot be easily used to designate the + strings to be encoded. As a workaround you can resort to the command echo, + either within back-ticks or used separately to create a file that is then + fed to the standard-input of barcode - assuming your echo command processes + escape sequences. The newline character is especially though to encode + (but not impossible unless you use a csh variant. + These problems only apply to the command-line tool; the use of library + functions doesn't give any problem. In needed, you can use the "code + 128 raw" pseudo-encoding to represent code128 symbols by their numerical + value. This encoding is used late in the auto- selection mechanism because + (almost) any input string can be represented using code128. +
+ + +

+ TOP +

+ + +

Codabar

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting Codabar valid character set lenght Checksum Size Remark + Codabar can encode the ten digits and a few special symbols (minus, plus, + dollar, colon, bar, dot). The characters "A", "B", + "C" and + "D" are used to represent four different start/stop characters. + The input string to the barcode library can include the start and stop + characters or not include them (in which case "A" is used as + start and "B" as stop). Start and stop characters in the input + string can be either all lowercase or all uppercase and are always printed + as uppercase.
+ + +

+ TOP +

+ + +

Plessey

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting Plessey valid character set lenght Checksum Size Remark Plessey barcodes can encode all the hexadecimal digits. Alphabetic + digits in the input string must either be all lowercase or all + uppercase. The output text is always uppercase.
+ + +

+ TOP +

+ + +

MSI

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting MSI valid character set lenght Checksum Size Remark + MSI can only encode the decimal digits. While the standard specifies either + one or two check digits, the current implementation in + this library only generates one check digit.
+ +

+ TOP +

+ + +

code 93

+ + + + + + + + + + + + + + + + + + + + + + + + + +
 kbarcode Setting code 93 valid character set lenght Checksum Size Remark The code-93 standard can natively encode 48 different characters, including + uppercase letters, digits, the blank space, plus, minus, + dot, star, dollar, slash, percent, as well as five special characters: + a start/stop delimiter and four "shift characters" used for + extended encoding. Using this "extended encoding" method, any + standard 7-bit ASCII character can be encoded, but it takes up two symbol + lengths in barcode if the character is not natively supported (one of + the 48). The encoder here fully implements the code 93 encoding standard. + Any characters natively supported (A-Z, 0-9, ".+-/\$&%") + will be encoded as such - for any other characters (such as lower case + letters, brackets, parentheses, etc.), the encoder will revert to extended + encoding. As a note, the option to exclude the checksum will eliminate + the two modulo-47 checksums (called C and K) from the barcode, but this + probably will make it unreadable by 99% of all scanning systems. These + checksums are specified to be used at the firmware level, and their absence + will be interpreted as an invalid barcode.
+ + +

+ TOP +

The first step " + "is to select the KBarcode label file you want to print.
" + "Serial start is a free form start value containing at least one " + "number. This number is increased for every printed label on the " + "print out.
") + query.lastError().text() + "
```+          * void create() {
+          *     DrawingRect* r = new DrawingRect( 0 ); // Drawing rect is a subclass of QCanvasItem
+          *     r->setCircle( m_circle );   // Do something with r
+          *     item = r;   // save r into item, so that NewItemCommand knows about it
+          * }
+          * ```

# Welcome to KBarcode

") + + i18n( description ) + "
" ); + Layout8->addWidget( TextLabel2_2 ); + + pageLayout->addLayout( Layout8 ); + + KURLLabel1 = new KURLLabel( page, "KURLLabel1" ); + KURLLabel1->setText( "http://www.kbarcode.net" ); + KURLLabel1->setURL("http://www.kbarcode.net"); + pageLayout->addWidget( KURLLabel1 ); + addPage( page, i18n( "Welcome" ) ); +} + +void ConfWizard::setupPage0() +{ + QWidget* page_0 = new QWidget( this, "page_0" ); + QVBoxLayout* pageLayout = new QVBoxLayout( page_0, 11, 6, "pageLayout"); + + QTextBrowser* b = new QTextBrowser( page_0, "b" ); + b->setText( DSMainWindow::systemCheck() ); + + pageLayout->addWidget( b ); + + addPage( page_0, i18n("System Check") ); +} + +void ConfWizard::setupPage2() +{ + page_2 = new QWidget( this, "page_2" ); + pageLayout_2 = new QVBoxLayout( page_2, 11, 6, "pageLayout_2"); + + checkDatabase = new QCheckBox( page_2 ); + checkDatabase->setText( i18n("&Use database with KBarcode") ); + checkDatabase->setChecked( true ); + + sqlwidget = new SqlWidget( true, page_2, "sqlwidget" ); + connect( sqlwidget, SIGNAL( databaseWorking( bool ) ), this, SLOT( testSettings( bool ) ) ); + + QSpacerItem* spacer_5 = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); + pageLayout_2->addWidget( checkDatabase ); + pageLayout_2->addWidget( sqlwidget ); + pageLayout_2->addItem( spacer_5 ); + + addPage( page_2, i18n( "Database" ) ); +} + +void ConfWizard::setupPage3() +{ + page_3 = new QWidget( this, "page_3" ); + pageLayout_3 = new QVBoxLayout( page_3, 11, 6, "pageLayout_3"); + + TextLabel1_2 = new QLabel( page_3, "TextLabel1_2" ); + TextLabel1_2->setText( i18n( "KBarcode can create the required SQL tables for you.
KBarcode will add also some Label Definitions to the tables.
") + sqlwidget->database(), + db->lastError().databaseText() + "
" ); + + if( db->open() ) { + KApplication::setOverrideCursor( Qt::WaitCursor ); + SqlTables::getInstance()->importData( + locate("appdata", "labeldefinitions.sql"), db ); + buttonExample->setEnabled( true ); + KApplication::restoreOverrideCursor(); + } + + db->close(); +} + +void ConfWizard::example() +{ + QSqlDatabase* db = QSqlDatabase::addDatabase( sqlwidget->driver() ); + db->setDatabaseName( sqlwidget->database() ); + db->setUserName( sqlwidget->username() ); + db->setPassword( sqlwidget->password() ); + db->setHostName( sqlwidget->hostname() ); + + if( !db->open() ) + KMessageBox::error( this, i18n("Connection failed:
") + sqlwidget->database(), + db->lastError().databaseText() + "

", + QString::null, QString::null, KMessageBox::AllowLink ); +} + +void DSMainWindow::showCheck() +{ + QTextBrowser* b = new QTextBrowser( 0, "b" ); + b->setText( DSMainWindow::systemCheck() ); + b->resize( 320, 240 ); + b->show(); +} + +void DSMainWindow::startInfo() +{ + QString info = locate("appdata", "barcodes.html"); + if( !info.isEmpty() ) + kapp->invokeBrowser( info ); +} + +bool DSMainWindow::newTables() +{ + return SqlTables::getInstance()->newTables(); +} + +void DSMainWindow::donations() +{ + // orig =https://www.paypal.com/xclick/business=domseichter%40web.de&item_name=Support+KBarcode+Development&item_number=0&image_url=http%3A//www.kbarcode.net/themes/DeepBlue/images/logo.gif&no_shipping=1&return=http%3A//www.kbarcode.net&cancel_return=http%3A//www.kbarcode.net&cn=Suggestions%2C+Comments%3F&tax=0¤cy_code=EUR + QString url = "https://www.paypal.com/xclick/business=domseichter@web.de&item_name=Support+KBarcode+Development&item_number=0&image_url=www.kbarcode.net/themes/DeepBlue/images/logo.gif&no_shipping=1&return=www.kbarcode.net&cancel_return=www.kbarcode.net&cn=Suggestions,+Comments,&tax=0¤cy_code=EUR"; + + KMessageBox::information( this, i18n( + "It is possible to support the further development of KBarcode through donations. " + "PayPal will be used for processing the donation.

" ) + + "" + + i18n("Donate Now") + "
", QString::null, QString::null, KMessageBox::AllowLink ); +} + +QString DSMainWindow::systemCheck() +{ + bool gnubarcode = !Barkode::haveGNUBarcode(); + bool pdf = !Barkode::havePDFBarcode(); + bool tbarcode = !Barkode::haveTBarcode(); + bool tbarcode2 = !Barkode::haveTBarcode2(); + bool pure = !Barkode::havePurePostscriptBarcode(); + + QString text; + + text.append( i18n("

### Barcode Support

") ); + text.append( "

GNU Barcode: "); + text.append( gnubarcode ? i18n("No
") : i18n("Found
") ); + text.append( "PDF417 Encode: "); + text.append( pdf ? i18n("No
") : i18n("Found
") ); + text.append( "TBarcode: "); + text.append( tbarcode ? i18n("No
") : i18n("Found
") ); + text.append( "TBarcode2: "); + text.append( tbarcode2 ? i18n("No
") : i18n("Found
") ); + text.append( "Pure Postscript Barcode Writer: "); + text.append( pure ? i18n("No
") : i18n("Found
") ); + + if( gnubarcode && tbarcode && pdf ) + text.append( i18n("

To get barcode support you have to either install GNU Barcode, TBarcode or PDF417 Enc.

") ); + + text.append( i18n("

### Database Support

") ); + + QStringList list = QSqlDatabase::drivers(); + + if( list.count() ) { + text.append( "
" ); + QStringList::Iterator it = list.begin(); + while( it != list.end() ) { + text.append( i18n("
• Driver found: ") + *it + "
• " ); + ++it; + } + text.append( "
" ); + } else + text.append( i18n("

No database drivers found. SQL database support is disabled.

A little bit formated " + "richtext which should be printed to a QPrinter with QSimpleRichText.

" + "

Printing should work in ScreenResolution as well as in HighResolution, but as you can see it will only work in ScreenResolution.

" + ""; + +Another example + +

Text test label

+

Resolution formated 108dpi. This text & text should now overlap with the first line. 4 < 6a

+

A longer paragraph with some text, so that I can test wether wordwrap is working. Another "line" to test line spacing without a bigger font (like the one found in the next sentence) messing up the spacing. Some text "in" a bigger courier font. Also this paragraph should be justified as blockquote. I hope it works and KBarcodes text redering will be better than the one found in Qt.

+ + +*/ + +DSRichText::DSRichText( const QString & t ) + : text( t ) +{ + if( text.find("") == -1 ) + text = "

" + + t + "

"; + + //qDebug( text ); + + start = end = pos = 0; + x = y = 0; + sx = sy = 1.0; + m_base = QFont(); + + QString tmp = parse( text, "", 0 ); + if( !tmp.isNull() ) { + pos += tmp.length(); + tmp = tmp.left( tmp.length() - 1 ); + tmp = tmp.mid( 5, tmp.length() - 5 ); + m_base = parseStyle( parse( tmp, "style=\"", "\"", pos ), &m_color ); + } + + pos = text.find( "text = QString::null; + f->line = false; + f->alignment = alignment; + f->font = m_base; + f->color = m_color; +} + +void DSRichText::initLine( QValueList* l ) +{ + formated_line li; + li.width = 0; + li.ascent = 0; + li.leading = 0; + li.lineSpacing = 0; + li.line = false; + l->append( li ); +} + +void DSRichText::updateSpacing( QValueList* l, QFontMetrics* fm ) +{ + l->last().lineSpacing = (l->last().lineSpacing < fm->lineSpacing()) ? fm->lineSpacing() : l->last().lineSpacing; + l->last().ascent = (l->last().ascent < fm->ascent()) ? fm->ascent() : l->last().ascent; + l->last().leading = (l->last().leading < fm->leading()) ? fm->leading() : l->last().leading; +} + +void DSRichText::fillLines() +{ + for( unsigned int z = 0; z < word_p.count(); z++ ) { + WordList words = word_p[z]; + LineList lines; + initLine( &lines ); + for( unsigned int i = 0; i < words.count(); i++ ) { + formated_word word = words[i]; + lines.last().line = lines.last().line | word.line; + + QFontMetrics fm( word.font ); + updateSpacing( &lines, &fm ); + + int tw = fm.width( word.text ); + // word does not fit in the current line, create a new one + if( lines.last().width + tw >= w ) + initLine( &lines ); + + // TODO: check here for words longer than one line + lines.last().formats.append( word ); + lines.last().width += tw; + } + line_p.append( lines ); + } +} + +void DSRichText::draw( QPainter* p ) +{ + /* don't try to draw if there is no space to draw */ + if( !w || !h ) + return; + + fillLines(); + + painter = p; + painter->save(); + painter->setClipRect( xpos, ypos, int(w*sx), int(h*sy), QPainter::CoordPainter ); + + for( unsigned int z = 0; z < line_p.count(); z++ ) { + LineList lines = line_p[z]; + if( lines.count() && z ) + y += int( lines[0].lineSpacing * 0.5); + + for( unsigned int i = 0; i < lines.count(); i++ ) { + formated_line l = lines[i]; + + if( l.formats.count() && l.formats[0].alignment == Qt::AlignJustify && i != lines.count() - 1 ) { + // last line in a paragraph is not justified (in blocksatz mode)! + drawJustified( &l ); + } else { + for( unsigned int z = 0; z < l.formats.count(); z++ ) { + formated_word f = l.formats[z]; + + painter->setFont( f.font ); + painter->setPen( QPen( f.color ) ); + + int a = f.alignment; + if( a == Qt::AlignRight ) { + a = Qt::AlignLeft; + if( !x ) + x = w - l.width; + } else if( a == Qt::AlignHCenter ) { + a = Qt::AlignLeft; + if( !x ) + x = ( w - l.width ) / 2; + } + + int ya = yDeviation( &l ); + painter->drawText( xpos + int(x*sx), ypos + int((y+ya)*sy), int(l.width*sx), int(l.lineSpacing * sy), a, f.text ); + x += painter->fontMetrics().width( f.text ); + } + } + + x = 0; + y += l.lineSpacing; + } + } + + painter->restore(); +} + +void DSRichText::drawJustified( formated_line* line ) +{ + int all = 0; + for( unsigned int z = 0; z < line->formats.count(); z++ ) { + line->formats[z].text = line->formats[z].text.stripWhiteSpace(); + QFontMetrics fm( line->formats[z].font ); + all += fm.width( line->formats[z].text ); + } + + int x = 0; + int space = (w - all) / (line->formats.count() - 1); + for( unsigned int z = 0; z < line->formats.count(); z++ ) { + painter->setFont( line->formats[z].font ); + painter->setPen( QPen( line->formats[z].color ) ); + + int ya = yDeviation( line ); + int tw = painter->fontMetrics().width(line->formats[z].text); + painter->drawText( int(x*sx), int((y+ya)*sy), int(tw*sx), int(line->lineSpacing * sy), Qt::AlignAuto, line->formats[z].text ); + x += tw; + x += space; + } + +} + +bool DSRichText::parseParagraph() +{ + int alignment = 0; + formated_word f; + QString d = parse( text, "", pos ); + //qDebug("D=" + d ); + //qDebug("POS=%i", pos ); + + pos += d.length(); + if( d.isNull() ) + return false; + + d = parseParagraphTag( d, &alignment ); + + WordList words; + QString data; + initFormat( &f, alignment ); + + if( d.isEmpty() ) { + // found empty paragraph + words.append( f ); + word_p.append( words ); + return true; + } + + for( unsigned int i = 0; i < d.length(); ) { + if( d[i] == '<' || i == (d.length() - 1) ) { + if( i == (d.length() - 1) ) + data.append( d[i] ); + + parseWords( data, &f, &words ); + initFormat( &f, alignment ); + data = QString::null; + + // bail out now, otherwise there is + // and endless loop for e.g.

a

+ if( i == (d.length() - 1) ) + break; + + if( d[i] == '<' ) { + QString span = d.mid( i, d.find( ">", i ) - i + 1 ); + i += span.length(); + + if( span.startsWith( "setNamedColor( s.right( s.length() - 6 ) ); + } else if( s.startsWith("text-decoration:") ) { + if( s.endsWith( "underline" ) ) + f.setUnderline( true ); +/*#if QT_VERSION >= 0x030200 + else if( s.endsWith( "overline" ) ) + f.setOverline( true ); +#endif */ + else if( s.endsWith( "line-through" ) ) + f.setStrikeOut( true ); + } else if( s.startsWith( "font-style:") ) { + if( s.endsWith( "italic" ) || s.endsWith( "oblique" ) ) + f.setItalic( true ); + } else if( s.startsWith( "font-weight:" ) ) { + bool ok = false; + int n = s.right( s.length() - 12 ).toInt( &ok ); + if( s.endsWith( "bold" ) ) + f.setBold( true ); + else if( ok ) + f.setWeight( n / 8 ); // convert CSS values to Qt values + } + } + + return f; +} + +QString DSRichText::parse( const QString & t, const QString & find, const QString & find2, int start ) +{ + int s = t.find( find, start ); + if( s == -1 || s < start ) + return QString::null; + + int pend = t.find( find2, s + find.length() ); + if( pend == -1 || pend < (signed int)(s + find.length()) ) + return QString::null; + + QString text = t.mid( s, pend - s + find2.length() ); + return text; +} + +void DSRichText::setX( int x ) +{ + xpos = x; +} + +void DSRichText::setY( int y ) +{ + ypos = y; +} + +void DSRichText::setWidth( int width ) +{ + w = width; +} + +void DSRichText::setHeight( int height ) +{ + h = height; +} + +int DSRichText::parseAlignment( const QString & align ) +{ + QString a = QString( align ); + if( a.endsWith("\"") ) + a = a.left( a.length() - 1 ); + + if( a.startsWith("align=\"") ) + a = a.mid( 7, a.length() - 7 ); + + if( a == "left" ) + return Qt::AlignLeft; + else if( a == "center" ) + return Qt::AlignHCenter; + else if( a == "right" ) + return Qt::AlignRight; + else if( a == "justify" ) + return Qt::AlignJustify; + + return 0; +} + +void DSRichText::parseWords( const QString & t, formated_word* w, WordList* words ) +{ + unsigned int p = 0; + for( unsigned int i = 0; i < t.length(); i++ ) { + if( (t[i].isSpace() && p != i) || i == t.length() - 1 ) { + formated_word word = *w; + + word.text = replaceEscapeSequences( t.mid( p, i + 1 - p ) ); + + p = i + 1; + words->append( word ); + } + } +} + +inline int DSRichText::yDeviation( const formated_line* line ) +{ + // leading = 1 (almost ever) + // linespacing = leading + height + // height = ascent + descent + 1 + if( line->lineSpacing != painter->fontMetrics().lineSpacing() ) { + return line->ascent + line->leading - painter->fontMetrics().ascent() - painter->fontMetrics().leading(); + } else { + return 0; + } +} + +QString DSRichText::replaceEscapeSequences( const QString & t ) +{ + QString tmp = QString( t ); + tmp = tmp.replace( DSREPLACE( "<" ), "<" ); + tmp = tmp.replace( DSREPLACE( ">" ), ">" ); + tmp = tmp.replace( DSREPLACE( "&" ), "&" ); + tmp = tmp.replace( DSREPLACE( """ ), "\"" ); + return tmp; +} + +QString DSRichText::parseParagraphTag( const QString &t, int* alignment ) +{ + QString d = QString( t ); + if( d.startsWith("

") ) { + d = d.mid( 3, d.length() - 3 ); + } else if( d.startsWith("

" ) ) { + int x = d.find(">" ) + 1; + d = d.mid( x, d.length() - x ); + } + } + + if( d.endsWith("

") ) + d = d.left( d.length() - 4 ); // strlen("

"); + + return d; +} + +#endif // QT_TEXT_BUG + + diff --git a/kbarcode/dsrichtext.h b/kbarcode/dsrichtext.h new file mode 100644 index 0000000..5da22b1 --- /dev/null +++ b/kbarcode/dsrichtext.h @@ -0,0 +1,193 @@ +/*************************************************************************** + dsrichtext.h - description + ------------------- + begin : Fre Okt 17 2003 + copyright : (C) 2003 by Dominik Seichter + email : domseichter@web.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef DSRICHTEXT_H +#define DSRICHTEXT_H + +#define QT_TEXT_BUG +/*#undef QT_TEXT_BUG*/ +#ifdef QT_TEXT_BUG + +#include +#include +#include +#include + +class DSRichText; + +/** This class represents one word, + * formated with a font, a color and an + * alignment. + */ +struct formated_word { + QString text; + QFont font; + QColor color; + int alignment; + bool line; +}; + +typedef QValueList WordList; + +/** This structure represents a single line. + * Every line contains a list of formated_words. + * Wordwrapping has been applied before the line + * was created. + * lineSpacing, ascent and leading come from the + * biggest font in the line. + */ +struct formated_line { + int width; + int lineSpacing; + int ascent; + int leading; + bool line; + + WordList formats; +}; +typedef QValueList LineList; + +class QColor; +class QPainter; + +/** A richtext rendering class, which draws a piece + * of HTML formated richtext on any QPainter. + * This class works with all printer resolutions compared + * to the buggy QSimpleRichText + * + * rendering the richtext happens in 3 steps: + *
+ *
• the HTML data is parsed into text_format structures. Each + * of these text_format structures may represend multiple lines, but + * also single words. This depends on how long a formated text is. + * this step happens in the constructor and in parseParagraph()
• + *
• the text_format structures are parsed into line structures. + * In this step the wordwrapping is calculated. Each line structure + * has again text_format structures. This is necessary because a line + * of text may of course contain different formattings. A line struct is always + * a single line of drawn text, not more and not less. + * happens in draw() and fillLines()
• + *
• the line structure is drawn line by line using QPainter. + * happens in draw()
• + *
+ * + * Printing to the screen is easy and the usage does not differ from + * QSimpleRichText. Drawing on QPrinter is a little bit more complicated. + * The most important thing is that you may not use QPainter::scale(). + * A small example on how to print on a QPrinter: + *
```+  *  QPrinter printer( QPrinter::HighResolution );
+  *  QPainter painter( &printer );
+  *  QPaintDeviceMetrics metrics( &printer );
+  *  double scalex = (double)metrics.logicalDpiX() / (double)QPaintDevice::x11AppDpiX();
+  *  double scaley = (double)metrics.logicalDpiY() / (double)QPaintDevice::x11AppDpiY();
+  *
+  *  DSRichText dsr( "<html><p>Hallo World</p></html>" );
+  *  dsr.setWidth( 200 ); // in screenresolution coordinates
+  *  dsr.setHeight( 80 );  // in screenresolution coordinates
+  *  painter.translate( 10 * scalex, 10 * scaley ); // draw at 10, 10 instead of 0, 0
+  *  dsr.scale( scalex, scaley );
+  *  dsr.draw( &painter );
+  * ```
+ * + *@author Dominik Seichter + */ +class DSRichText { + public: + /** construct a DSRichText object. @p t is formated text as produces by QTextEdit. + */ + DSRichText( const QString & t ); + ~DSRichText(); + + void setX( int x ); + void setY( int y ); + + /** draw the formated text on the QPainter* @p p + */ + void draw( QPainter* p ); + /** set the width of the clipping rectangle + */ + void setWidth( int width ); + /** set the height of the clipping rectangle + */ + void setHeight( int height ); + /** scale everything. This is necessary to print on devices + * with another resolution than the screen. QPainter::scale() won't work. + */ + void setScale( double x, double y ) { + sx = x; sy = y; + }; + + private: + /** parse a single pare of

elements + */ + bool parseParagraph(); + /** remove

and

from the QString @p t and return it. + * This function is also responsible for getting the + * correct alignment of the paragraph. + */ + QString parseParagraphTag( const QString & t, int* alignment ); + /** parse the align attribute of a

tag and return the corresponding Qt alignment value. + */ + int parseAlignment( const QString & align ); + /** parse the css style attribute of a tag and return a matching QFont for these + * style. The font color is saved in the QColor* @p color. + */ + QFont parseStyle( const QString & s, QColor* color ); + QString parse( const QString & t, const QString & find, const QString & end, int start ); + void parseWords( const QString & t, formated_word* w, WordList* words ); + void initFormat( formated_word* f, int alignment ); + void initLine( QValueList* l ); + void updateSpacing( QValueList* l, QFontMetrics* fm ); + /** draw the line @p line justified as blockquote + */ + void drawJustified( formated_line* line ); + /** calculate the y-deviation needed, because of different font sizes in this line + */ + inline int yDeviation( const formated_line* line ); + /** replace HTML escape sequences such as < to their real character meaning (i.e. < ) + */ + QString replaceEscapeSequences( const QString & t ); + + /** fill the line structures with data + */ + void fillLines(); + + int pos; // current position in text + int start; // start of a tag + int end; // end of a tag + int x; // x position + int y; // y position + int w; // width of the text element + int h; // height of the text element + int xpos; // x position at the beginning + int ypos; // y position at the beginning + + double sx; + double sy; + + QString text; + QFont m_base; + QColor m_color; + QPainter* painter; + + QValueList line_p; + QValueList word_p; +}; + +#endif // QT_TEXT_BUG +#endif diff --git a/kbarcode/dstextedit.cpp b/kbarcode/dstextedit.cpp new file mode 100644 index 0000000..e059e96 --- /dev/null +++ b/kbarcode/dstextedit.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + dstextedit.cpp - description + ------------------- + begin : Sam Jun 04 2005 + copyright : (C) 2005 by Dominik Seichter + email : domseichter@web.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "dstextedit.h" +#include "dstextedit.moc" +#include + +DSTextEdit::DSTextEdit( QWidget* parent, const char* name ) + : TextEditBase( parent, name ) +{ + connect( this, SIGNAL( textChanged() ), this, SLOT( fixParagraphs() ) ); +} + +void DSTextEdit::fixParagraphs() +{ + struct { + QFont font; + QColor color; + int alignment; + } tFormattings; + + QString t; + int pos = 0; + int count = 0; + int i; + int para, index; // needed to save the cursor position + int paraFrom, indexFrom, paraTo, indexTo; // needed to save the selection + QValueList chars; + QRegExp reg("]*>"); + + for( i = 0; i < paragraphs(); i++ ) + chars.append( paragraphLength( i ) ); + + // disconnect us first as we change the text here + disconnect( this, SIGNAL( textChanged() ), this, SLOT( fixParagraphs() ) ); + + getCursorPosition( ¶, &index ); + getSelection( ¶From, &indexFrom, ¶To, &indexTo ); + + if( !para && !index ) + setCursorPosition( 0, index+1 ); + + t = this->text(); + tFormattings.font = this->currentFont(); + tFormattings.color = this->color(); + tFormattings.alignment = this->alignment(); + + while( pos != -1 ) + { + pos = reg.search( t, pos ); + if( pos != -1 ) + { + if( count && count == para ) + { + for( i = 0; i < count; i++ ) + index += chars[i]; + ++index; // count the new
that is inserted later + } + + ++count; + + if( count > 1 ) //&& pos != -1 ) + t = t.remove( pos, reg.matchedLength() ); + else + pos += reg.matchedLength(); + } + } + + pos = t.length(); + count = 0; + + while( pos != -1 ) + { + pos = t.findRev( "

", pos ); + if( pos != -1 ) + { + ++count; + + if( count > 1 ) //&& pos != -1 ) + t = t.replace( pos, 4, "