Subversion Repositories Scribus

Rev

Rev 418 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
413 Franz 1
#include <Python.h>
2
#include <structmember.h>
3
 
4
#include "cmdvar.h"
5
#include "cmdutil.h"
6
#include "objprinter.h"
7
#include <vector>
8
 
9
#ifdef HAVE_CUPS
10
#include <cups/cups.h>
11
#endif
12
#ifdef HAVE_CMS
13
extern bool CMSuse;
14
#endif
15
// these functions are located at utils.cpp
16
extern bool loadText(QString nam, QString *Buffer);
17
extern void ReOrderText(ScribusDoc *doc, ScribusView *view);
18
// end of utils.cpp
19
 
20
typedef struct
21
{
22
    PyObject_HEAD
23
    PyObject *allPrinters; // list of strings - names of installed printers
24
    PyObject *printer;  // string - selected printer
25
    PyObject *file;  // string - name of file to print into (eg. output.ps)
26
    PyObject *cmd; // string - if "" use standard command else use this as command (eg. "kprinter", "xpp" ...)
27
    PyObject *pages;       // list of integers - pages to be printed
28
    int copies;      // numer of printed copies    
29
    PyObject *separation; // string - No; All; Cyan; Magenta; Yellow; Black
30
    int color;       // bool - do we print in color=1 or greyscale=0
31
    int useICC;       // bool - do we use ICC Profiles 0 = No 1 = Yes
32
    int pslevel;     // integer - 1, 2 or 3 level of used postscript
33
    int mph; // bool - mirror pages horizontally
34
    int mpv;   // bool - mirror pages vertically
35
    int ucr;     // bool - Under Color Removal
36
} Printer;
37
 
38
 
39
static void Printer_dealloc(Printer* self)
40
{
41
    Py_XDECREF(self->allPrinters);
42
    Py_XDECREF(self->printer);
43
    Py_XDECREF(self->file);
44
    Py_XDECREF(self->cmd);
45
    Py_XDECREF(self->pages);
46
    Py_XDECREF(self->separation);
47
    self->ob_type->tp_free((PyObject *)self);
48
}
49
 
50
static PyObject * Printer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
51
{
52
// do not create new object if there is no opened document
53
    if (!Carrier->HaveDoc) {
54
        PyErr_SetString(PyExc_SystemError, "Need to open document first");
55
        return NULL;
56
    }
57
 
58
    Printer *self;
59
    self = (Printer *)type->tp_alloc(type, 0);
60
    if (self != NULL) {
61
// set allPrinters attribute
62
        self->allPrinters = PyList_New(0);
63
        if (self->allPrinters == NULL){
64
            Py_DECREF(self);
65
            return NULL;
66
        }
67
// set printer attribute
68
        self->printer = PyString_FromString("");
69
        if (self->printer == NULL){
70
            Py_DECREF(self);
71
            return NULL;
72
        }
73
// set file attribute
74
        self->file = PyString_FromString("");
75
        if (self->file == NULL){
76
            Py_DECREF(self);
77
            return NULL;
78
        }
79
// set cmd attribute
80
        self->cmd = PyString_FromString("");
81
        if (self->cmd == NULL){
82
            Py_DECREF(self);
83
            return NULL;
84
        }
85
// set pages attribute
86
        self->pages = PyList_New(0);
87
        if (self->pages == NULL){
88
            Py_DECREF(self);
89
            return NULL;
90
        }
91
// set separation attribute
92
        self->separation = PyString_FromString("No");
93
        if (self->separation == NULL){
94
            Py_DECREF(self);
95
            return NULL;
96
        }
97
// set color attribute
98
        self->color = 1;
99
// set useICC attribute
100
        self->useICC = 0;
101
// set pslevel attribute
102
        self->pslevel = 3;
103
// set mph attribute
104
        self->mph = 0;
105
// set mpv attribute
106
        self->mpv = 0;
107
// set ucr attribute
108
        self->ucr = 1;
109
// set copies attribute
110
        self->copies = 1;
111
    }
112
    return (PyObject *) self;
113
}
114
 
115
static int Printer_init(Printer *self, PyObject *args, PyObject *kwds)
116
{
117
// pool system for installed printers
118
// most code is stolen and little adopted from druck.cpp
119
    PyObject *allPrinters = PyList_New(0);
120
    if (allPrinters){
121
        Py_DECREF(self->allPrinters);
122
        self->allPrinters = allPrinters;
123
    }
124
#ifdef HAVE_CUPS
125
    cups_dest_t *dests;
126
    int num_dests = cupsGetDests(&dests);
127
    for (int i = 0; i < num_dests; ++i) {
128
        if (dests[i].name != NULL) {
129
            PyObject *tmp = PyString_FromString(dests[i].name);
130
            if (tmp)
131
                PyList_Append(self->allPrinters, tmp);
132
        }
133
    }
134
    cupsFreeDests(num_dests, dests);
135
#else
136
    QString Pcap;
137
        // loadText is defined in utils.cpp
138
    if (loadText("/etc/printcap", &Pcap))
139
    {
140
        QTextStream ts(&Pcap, IO_ReadOnly);
141
        while(!ts.atEnd())
142
        {
143
            QStringList wt;
144
            QString tmp = ts.readLine();
145
            if (tmp.isEmpty())
146
                continue;
147
            if ((tmp[0] != '#') && (tmp[0] != ' ') && (tmp[0] != '\n') && (tmp[0] != '\t'))
148
            {
149
                tmp = tmp.stripWhiteSpace();
150
                tmp = tmp.left(tmp.length() - (tmp.right(2) == ":\\" ? 2 : 1));
151
                wt = QStringList::split("|", tmp);
152
                PyObject *tmppr = PyString_FromString(wt[0]);
153
                if (tmppr){
154
                    PyList_Append(self->allPrinters, tmppr);
155
                }
156
            }
157
        }
158
    }
159
#endif
160
    PyList_Append(self->allPrinters, PyString_FromString("File"));
161
// as defaut set to print into file
162
    PyObject *printer = NULL;
163
    printer = PyString_FromString("File");
164
    if (printer){
165
        Py_DECREF(self->printer);
166
        self->printer = printer;
167
    }
168
// set defaul name of file to print into
169
    PyObject *file = NULL;
170
    file = PyString_FromString("output.ps");
171
    if (file){
172
        Py_DECREF(self->file);
173
        self->file = file;
174
    }
175
// alternative printer commands default to ""
176
    PyObject *cmd = NULL;
177
    cmd = PyString_FromString("");
178
    if (cmd){
179
        Py_DECREF(self->cmd);
180
        self->cmd = cmd;
181
    }
182
// if document exist when created Printer instance
183
// set to print all pages
184
    PyObject *pages = NULL;
185
    int num = 0;
186
    if (Carrier->HaveDoc)
187
            // which one should I use ???
188
            // new = Carrier->view->Pages.count()
189
        num = Carrier->doc->PageC;
190
    pages = PyList_New(num);
191
    if (pages){
192
        Py_DECREF(self->pages);
193
        self->pages = pages;
194
    }
195
    for (int i = 0; i<num; i++) {
196
        PyObject *tmp=NULL;
197
        tmp = PyInt_FromLong((long)i+1L); // instead of 1 put here first page number
198
        if (tmp)
199
            PyList_SetItem(self->pages, i, tmp);
200
    }
201
// do not print separation
202
    PyObject *separation = NULL;
203
    separation = PyString_FromString("No");
204
    if (separation){
205
        Py_DECREF(self->separation);
206
        self->separation = separation;
207
    }
208
// print in color
209
    self->color = 1;
210
// do not use ICC Profile
211
    self->useICC = 0;
212
// use PostScrip level 3
213
    self->pslevel = 3;
214
// do not mirror pages
215
    self->mph = 0;
216
// do not mirror pages
217
    self->mpv = 0;
218
// apply Under Color Removal as default
219
    self->ucr = 1;
220
// number of copies
221
    self->copies = 1;
222
    return 0;
223
}
224
 
225
static PyMemberDef Printer_members[] = {
226
    {"copies", T_INT, offsetof(Printer, copies), 0, "Number of copies"},
227
    {"color", T_INT, offsetof(Printer, color), 0, "Print in color.\n\t True - color  --  Default\n\t False - greyscale"},
228
    {"useICC", T_INT, offsetof(Printer, useICC), 0, "Use ICC Profile\n\tTrue\n\tFalse  --  Default"},
229
    {"pslevel", T_INT, offsetof(Printer, pslevel), 0, "PostScript Level\n\tCan be 1 or 2 or 3    -- Default is 3."},
230
    {"mph", T_INT, offsetof(Printer, mph), 0, "Mirror Pages Horizontal\n\tTrue\n\tFalse  --  Default"},
231
    {"mpv", T_INT, offsetof(Printer, mpv), 0, "Mirror Pages Vertical\n\t True\n\tFalse  --  Default"},
232
    {"ucr", T_INT, offsetof(Printer, ucr), 0, "Apply Under Color Removal\n\tTrue  --  Default\n\tFalse"},
233
    {NULL}                      // sentinel
234
};
235
 
236
/* Here begins Getter & Setter functions */
237
 
238
static PyObject *Printer_getallPrinters(Printer *self, void *closure)
239
{
240
    Py_INCREF(self->allPrinters);
241
    return self->allPrinters;
242
}
243
 
244
static int Printer_setallPrinters(Printer *self, PyObject *value, void *closure)
245
{
246
    PyErr_SetString(PyExc_ValueError, "'allPrinters' attribute is READ-ONLY");
247
    return -1;
248
}
249
 
250
static PyObject *Printer_getprinter(Printer *self, void *closure)
251
{
252
    Py_INCREF(self->printer);
253
    return self->printer;
254
}
255
 
256
static int Printer_setprinter(Printer *self, PyObject *value, void *closure)
257
{
258
    if (value == NULL) {
259
        PyErr_SetString(PyExc_TypeError, "Cannot delete 'printer' attribute.");
260
        return -1;
261
    }
262
    if (!PyString_Check(value)) {
263
        PyErr_SetString(PyExc_TypeError, "The 'printer' attribute value must be string.");
264
        return -1;
265
    }
266
    int n = PyList_Size(self->allPrinters);
267
    bool same = 0;
268
    for (int i = 0; i<n; i++)
269
        if (PyObject_RichCompareBool(value, PyList_GetItem(self->allPrinters, i), Py_EQ) == 1)
270
            same = true;
271
    if (!same) {
272
        PyErr_SetString(PyExc_ValueError, "'printer' value can be only one of string in 'allPrinters' attribute ");
273
        return -1;
274
    }
275
    Py_DECREF(self->printer);
276
    Py_INCREF(value);
277
    self->printer = value;
278
    return 0;
279
}
280
 
281
static PyObject *Printer_getfile(Printer *self, void *closure)
282
{
283
    Py_INCREF(self->file);
284
    return self->file;
285
}
286
 
287
static int Printer_setfile(Printer *self, PyObject *value, void *closure)
288
{
289
    if (value == NULL) {
290
        PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
291
        return -1;
292
    }
293
    if (!PyString_Check(value)) {
294
        PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
295
        return -1;
296
    }
297
    Py_DECREF(self->file);
298
    Py_INCREF(value);
299
    self->file = value;
300
    return 0;
301
}
302
 
303
static PyObject *Printer_getcmd(Printer *self, void *closure)
304
{
305
    Py_INCREF(self->cmd);
306
    return self->cmd;
307
}
308
 
309
static int Printer_setcmd(Printer *self, PyObject *value, void *closure)
310
{
311
    if (value == NULL) {
312
        PyErr_SetString(PyExc_TypeError, "Cannot delete 'cmd' attribute.");
313
        return -1;
314
    }
315
    if (!PyString_Check(value)) {
316
        PyErr_SetString(PyExc_TypeError, "The 'cmd' attribute value must be string.");
317
        return -1;
318
    }
319
    Py_DECREF(self->cmd);
320
    Py_INCREF(value);
321
    self->cmd = value;
322
    return 0;
323
}
324
 
325
static PyObject *Printer_getpages(Printer *self, void *closure)
326
{
327
    Py_INCREF(self->pages);
328
    return self->pages;
329
}
330
 
331
static int Printer_setpages(Printer *self, PyObject *value, void *closure)
332
{
333
    if (value == NULL) {
334
        PyErr_SetString(PyExc_TypeError, "Cannot delete 'pages' attribute.");
335
        return -1;
336
    }
337
    if (!PyList_Check(value)) {
338
        PyErr_SetString(PyExc_TypeError, "'pages' attribute value must be list of integers.");
339
        return -1;
340
    }
341
    int len = PyList_Size(value);
342
    for (int i = 0; i<len; i++){
343
        PyObject *tmp = PyList_GetItem(value, i);
344
        if (!PyInt_Check(tmp)){
345
            PyErr_SetString(PyExc_TypeError, "'pages' attribute must be list containing only integers.");
346
            return -1;
347
        }
348
    }
349
    Py_DECREF(self->pages);
350
    Py_INCREF(value);
351
    self->pages = value;
352
    return 0;
353
}
354
 
355
static PyObject *Printer_getseparation(Printer *self, void *closure)
356
{
357
    Py_INCREF(self->separation);
358
    return self->separation;
359
}
360
 
361
static int Printer_setseparation(Printer *self, PyObject *value, void *closure)
362
{
363
    if (value == NULL) {
364
        PyErr_SetString(PyExc_TypeError, "Cannot delete 'separation' attribute.");
365
        return -1;
366
    }
367
    if (!PyString_Check(value)) {
368
        PyErr_SetString(PyExc_TypeError, "The 'separation' attribute value must be string.");
369
        return -1;
370
    }
371
    Py_DECREF(self->separation);
372
    Py_INCREF(value);
373
    self->separation = value;
374
    return 0;
375
}
376
 
377
 
378
static PyGetSetDef Printer_getseters [] = {
379
    {"allPrinters", (getter)Printer_getallPrinters, (setter)Printer_setallPrinters, "List of installed printers  --  read only", NULL},
380
    {"printer", (getter)Printer_getprinter, (setter)Printer_setprinter, "Name of printer to use.\nDefault is 'File' for printing into file", NULL},
381
    {"file", (getter)Printer_getfile, (setter)Printer_setfile, "Name of file to print into", NULL},
382
    {"cmd", (getter)Printer_getcmd, (setter)Printer_setcmd, "Alternative Printer Command", NULL},
383
    {"pages", (getter)Printer_getpages, (setter)Printer_setpages, "List of pages to be printed", NULL},
384
    {"separation", (getter)Printer_getseparation, (setter)Printer_setseparation, "Print separationl\n\t 'No'  -- Default\n\t 'All'\n\t 'Cyan'\n\t 'Magenta'\n\t 'Yellow'\n\t 'Black'\nBeware of misspelling because check is not performed", NULL},
385
    {NULL}  // sentinel
386
};
387
 
388
// Here we actually print 
389
static PyObject *Printer_print(Printer *self)
390
{
391
    if (!Carrier->HaveDoc) {
392
        PyErr_SetString(PyExc_SystemError, "Need to open documetnt first");
393
        return NULL;
394
    }
395
// copied from void ScribusApp::slotFilePrint() in file scribus.cpp
396
    QString fna, prn, cmd, scmd, cc, data, SepName;
397
    QString printcomm;
398
    int Nr, PSLevel;
399
    bool fil, sep, color, PSfile, mirrorH, mirrorV, useICC, DoGCR;
400
    PSfile = false;
401
 
402
//    ReOrderText(Carrier->doc, Carrier->view);
403
    prn = QString(PyString_AsString(self->printer));
404
    fna = QString(PyString_AsString(self->file));
405
    fil = (QString(PyString_AsString(self->printer)) == QString("File")) ? true : false;
406
    std::vector<int> pageNs;
407
    for (int i = 0; i < PyList_Size(self->pages); ++i) {
408
        pageNs.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i)));
409
    }
410
    Nr = (self->copies < 1) ? 1 : self->copies;
411
    SepName = QString(PyString_AsString(self->separation));
412
    sep =(SepName == QString("No")) ?  false : true;
413
//     if (SepName == QString("All"))
414
//         SepName = tr(SepName);
415
    color = (bool)self->color;
416
    mirrorH = (bool)self->mph;
417
    mirrorV = (bool)self->mpv;
418
    useICC = (bool)self->useICC;
419
    DoGCR = (bool)self->ucr;
420
    int psl = self->pslevel;
421
    if (psl < 1)
422
        psl = 1;
423
    if (psl > 3)
424
        psl = 3;
425
    PSLevel = psl;
426
    printcomm = QString(PyString_AsString(self->cmd));
427
    QMap<QString,QFont> ReallyUsed;
428
    ReallyUsed.clear();
429
    Carrier->GetUsedFonts(&ReallyUsed);
430
    PSLib *dd = Carrier->getPSDriver(true, Carrier->Prefs.AvailFonts, ReallyUsed, Carrier->doc->PageColors, false);
431
    if (dd != NULL)
432
    {
433
        if (!fil)
434
            fna = Carrier->PrefsPfad+"/tmp.ps";
435
        PSfile = dd->PS_set_file(fna);
436
        if (PSfile)
437
        {
438
            Carrier->view->CreatePS(dd, pageNs, sep, SepName, color, mirrorH, mirrorV, useICC, DoGCR);
439
            if (PSLevel != 3)
440
            {
441
                QString tmp;
442
                QString opts = "-dDEVICEWIDTHPOINTS=";
443
                opts += tmp.setNum(Carrier->doc->PageB);
444
                opts += " -dDEVICEHEIGHTPOINTS=";
445
                opts += tmp.setNum(Carrier->doc->PageH);
446
                if (PSLevel == 1)
447
                    system("ps2ps -dLanguageLevel=1 "+opts+" \""+fna+"\" \""+fna+".tmp\"");
448
                else
449
                    system("ps2ps "+opts+" \""+fna+"\" \""+fna+".tmp\"");
450
                system("mv \""+fna+".tmp\" \""+fna+"\"");
451
            }
452
            if (!fil)
453
            {
454
                if (printcomm != "")
455
                    cmd = printcomm + " "+fna;
456
                else
457
                {
458
                    cmd = "lpr -P" + prn;
459
                    if (Nr > 1)
460
                        cmd += " -#" + cc.setNum(Nr);
461
#ifdef HAVE_CUPS
462
// This need yet to be suported by object Printer
463
//                    cmd += printer->PrinterOpts;
464
#endif
465
                    cmd += " "+fna;
466
                }
467
                system(cmd);
468
                unlink(fna);
469
            }
470
        }
471
        else {
472
            delete dd;
473
            Carrier->closePSDriver();
474
            PyErr_SetString(PyExc_SystemError, "Printing failed");
475
            return NULL;
476
        }
477
        delete dd;
478
        Carrier->closePSDriver();
479
    }
480
    Py_INCREF(Py_None);
481
    return Py_None;
482
}
483
 
484
static PyMethodDef Printer_methods[] = {
485
    {"Print", (PyCFunction)Printer_print, METH_NOARGS, "Prints selected pages."},
486
    {NULL} // sentinel
487
};
488
 
489
PyTypeObject Printer_Type = {
490
    PyObject_HEAD_INIT(NULL)   // PyObject_VAR_HEAD 
491
    0,                         // 
492
    "Printer", // char *tp_name; /* For printing, in format "<module>.<name>" */
493
    sizeof(Printer),   // int tp_basicsize, /* For allocation */
494
    0,                       // int tp_itemsize; /* For allocation */
495
 
496
        /* Methods to implement standard operations */
497
 
498
    (destructor) Printer_dealloc, //     destructor tp_dealloc;
499
    0, //     printfunc tp_print;
500
    0, //     getattrfunc tp_getattr;
501
    0, //     setattrfunc tp_setattr;
502
    0, //     cmpfunc tp_compare;
503
    0, //     reprfunc tp_repr;
504
 
505
        /* Method suites for standard classes */
506
 
507
    0, //     PyNumberMethods *tp_as_number;
508
    0, //     PySequenceMethods *tp_as_sequence;
509
    0, //     PyMappingMethods *tp_as_mapping;
510
 
511
        /* More standard operations (here for binary compatibility) */
512
 
513
    0, //     hashfunc tp_hash;
514
    0, //     ternaryfunc tp_call;
515
    0, //     reprfunc tp_str;
516
    0, //     getattrofunc tp_getattro;
517
    0, //     setattrofunc tp_setattro;
518
 
519
        /* Functions to access object as input/output buffer */
520
    0, //     PyBufferProcs *tp_as_buffer;
521
 
522
        /* Flags to define presence of optional/expanded features */
523
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,    // long tp_flags;
524
 
525
    "Printer object",      // char *tp_doc; /* Documentation string */
526
 
527
        /* Assigned meaning in release 2.0 */
528
        /* call function for all accessible objects */
529
    0, //     traverseproc tp_traverse;
530
 
531
        /* delete references to contained objects */
532
    0, //     inquiry tp_clear;
533
 
534
        /* Assigned meaning in release 2.1 */
535
        /* rich comparisons */
536
    0, //     richcmpfunc tp_richcompare;
537
 
538
        /* weak reference enabler */
539
    0, //     long tp_weaklistoffset;
540
 
541
        /* Added in release 2.2 */
542
        /* Iterators */
543
    0, //     getiterfunc tp_iter;
544
    0, //     iternextfunc tp_iternext;
545
 
546
        /* Attribute descriptor and subclassing stuff */
547
    Printer_methods, //     struct PyMethodDef *tp_methods;
548
    Printer_members, //     struct PyMemberDef *tp_members;
549
    Printer_getseters, //     struct PyGetSetDef *tp_getset;
550
    0, //     struct _typeobject *tp_base;
551
    0, //     PyObject *tp_dict;
552
    0, //     descrgetfunc tp_descr_get;
553
    0, //     descrsetfunc tp_descr_set;
554
    0, //     long tp_dictoffset;
555
    (initproc)Printer_init, //     initproc tp_init;
556
    0, //     allocfunc tp_alloc;
557
    Printer_new, //     newfunc tp_new;
558
    0, //     freefunc tp_free; /* Low-level free-memory routine */
559
    0, //     inquiry tp_is_gc; /* For PyObject_IS_GC */
560
    0, //     PyObject *tp_bases;
561
    0, //     PyObject *tp_mro; /* method resolution order */
562
    0, //     PyObject *tp_cache;
563
    0, //     PyObject *tp_subclasses;
564
    0, //     PyObject *tp_weaklist;
565
    0, //     destructor tp_del;
566
 
567
#ifdef COUNT_ALLOCS
568
        /* these must be last and never explicitly initialized */
569
        //    int tp_allocs;
570
        //    int tp_frees;
571
        //    int tp_maxalloc;
572
        //    struct _typeobject *tp_next;
573
#endif
574
};