Search code examples
c++linuxqtprintingzebra-printers

Qt: Print raw text


I need to output a ZPL script to a Zebra printer in a Qt application. The printer is on a smb share network configured as raw printer in the client computer.

Everything goes fine if I call cupsPrintFile( "printer_name", "./tmp_print_file.zpl", "", 0, NULL ) from a C++ test program.

If I use QTextDocument::print() using the same text in "./tmp_print_file.zpl" as document, nothing gets printed. I sniffed the network and found that the data being sent to the printer server is not raw data, but, a postscript!

Is there any way to get the data sent to the printer with no modification at all?

  • Let me be clear that I don't want to render a text, but just send the label script, that is ready to print, directly to the printer, that understands the ZPL protocol.

Thanks for all.


EDIT:

As @Martin said, I tried:

printer.setOutputFormat( QPrinter::NativeFormat );
QTextDocument   *doc = new QTextDocument( QString( label ), this );
doc->print( &printer );

but it didn't work.


Solution

  • Before I start, must thank Dave. His suggestion to bypass the temporary file while printing with CUPs works fine.

    Now, my conclusion: There is no easy way to print raw data using Qt only. Maybe creating custom QPainter or going down to the bits of QPrinter could give a solution, but it would take me too much time.

    The final solution is simply use CUPs API inside my Qt application. Unfortunatelly, it is not portable.

    Here is a snippet:

    #include    <cups/cups.h>
    
    //...
    
    int print_label( const char *text, const char *printer_name, const char *job_name )
    {
        int jobId = 0;
    
        jobId = cupsCreateJob( CUPS_HTTP_DEFAULT, printer_name, job_name, 0, NULL );
    
        if ( jobId > 0 )
        {
            qDebug( ) << "Printing job #" << jobId << " (\"" << job_name << "\").";
    
            const char* format = CUPS_FORMAT_TEXT;  // CUPS_FORMAT_POSTSCRIPT;
    
            cupsStartDocument( CUPS_HTTP_DEFAULT, printer_name, jobId, text, format, true );
            cupsWriteRequestData( CUPS_HTTP_DEFAULT, text, strlen( text ) );
    
            cupsFinishDocument( CUPS_HTTP_DEFAULT, printer_name );
        }
    
        return jobId;
    }
    
    //...
    
    // Now, inside any Qt function (may be a slot):
    
    QPrinter printer;
    
    QPrintDialog *dialog = new QPrintDialog( &printer, this );
    dialog->setWindowTitle( tr( "Zebra label" ) );
    if ( dialog->exec( ) != QDialog::Accepted )
        return;
    
        // This is the sample label. Can be anything.
    const char  label[] =
        "^XA~TA000~JSN^LT0^MNW^MTD^PON^PMN^LH0,0^JMA^PR4,4^MD0^JUS^LRN^CI0^XZ\n"
        "^XA\n"
        "^MMT\n"
        "^LL0600\n"
        "^PW900\n"
        "^LS0\n"
        "^BY2,3,54^FT24,109^BCN,,Y,N\n"
        "^FD>;43210000>773>0000^FS\n"
        "^PQ1,0,1,Y^XZ\n";
    
        // Informative only.
    ui->txtLabelScript->setPlainText( label );
    
        // Call the printing function.
    if ( print_label( label, printer.printerName( ).toAscii( ), "Zebra_Label" ) == 0 )
        qDebug( ) << "CUPS Error: " << ippErrorString( cupsLastError( ) );
    

    And it's done.

    Don't forget to link libcups (-lcups).

    I still hope any buddy to add another solution prooving that Qt-only is possible. Meanwhile, it is enough.

    Thanks everybody.