1# -*- coding: utf-8 -*-
2#
3# (c) Copyright 2001-2015 HP Development Company, L.P.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18#
19# Author: Don Welch
20#
21
22# Local
23from base.g import *
24from base import utils, pml
25from copier import copier
26from base.sixext.moves import queue
27
28# Qt
29from qt import *
30from .scrollview import ScrollView, PixmapLabelButton
31from .waitform import WaitForm
32
33# Std Lib
34import os.path, os
35
36
37class ScrollCopyView(ScrollView):
38    def __init__(self, service, num_copies=None, contrast=None, quality=None,
39                reduction=None, fit_to_page=None, parent=None, form=None, name=None, fl=0):
40        ScrollView.__init__(self, service, parent, name, fl)
41
42        self.form = form
43
44        self.num_copies = num_copies
45        self.contrast = contrast
46        self.quality = quality
47        self.reduction = reduction
48        self.fit_to_page = fit_to_page
49
50        self.update_queue = queue.Queue() # UI updates from copy thread
51        self.event_queue = queue.Queue() # UI events to copy thread
52
53    def getDeviceSettings(self):
54        QApplication.setOverrideCursor(QApplication.waitCursor)
55        try:
56            # get sticky settings as defaults (if not spec'd on command line)
57            if self.num_copies is None:
58                result_code, self.num_copies = self.dev.getPML(pml.OID_COPIER_NUM_COPIES)
59
60            if self.contrast is None:
61                result_code, self.contrast = self.dev.getPML(pml.OID_COPIER_CONTRAST)
62
63            if self.reduction is None:
64                result_code, self.reduction = self.dev.getPML(pml.OID_COPIER_REDUCTION)
65
66            if self.quality is None:
67                result_code, self.quality = self.dev.getPML(pml.OID_COPIER_QUALITY)
68
69            if self.scan_src == SCAN_SRC_FLATBED and self.fit_to_page is None:
70                result_code, self.fit_to_page = self.dev.getPML(pml.OID_COPIER_FIT_TO_PAGE)
71
72                if result_code != pml.ERROR_OK:
73                    self.fit_to_page = pml.COPIER_FIT_TO_PAGE_DISABLED
74                    self.fitToPageCheckBox.setEnabled(False)
75
76            else:
77                self.fit_to_page = pml.COPIER_FIT_TO_PAGE_DISABLED
78
79            if self.scan_src != SCAN_SRC_FLATBED:
80                self.fitToPageCheckBox.setEnabled(False)
81
82            result_code, self.max_reduction = self.dev.getPML(pml.OID_COPIER_REDUCTION_MAXIMUM)
83            result_code, self.max_enlargement = self.dev.getPML(pml.OID_COPIER_ENLARGEMENT_MAXIMUM)
84
85            # contrast
86            a = self.contrast/25
87            self.contrastSpinBox.setValue(a)
88
89            if a >= 0:
90                self.contrastSpinBox.setPrefix("+")
91            else:
92                self.contrastSpinBox.setPrefix("")
93
94            self.contrastSlider.setValue(a)
95            self.contrastSlider.setTickmarks(QSlider.Below)
96            self.contrastSlider.setTickInterval(1)
97
98            self.contrastDefaultPushButton.setEnabled(a != 0)
99
100            # reduction/enlargement/fittopage
101
102            self.reductionSlider.setRange(self.max_reduction, self.max_enlargement)
103            self.reductionSlider.setTickmarks(QSlider.Below)
104            self.reductionSlider.setTickInterval(10)
105            self.reductionSlider.setValue(self.reduction)
106
107            self.reductionSpinBox.setMaxValue(self.max_enlargement)
108            self.reductionSpinBox.setMinValue(self.max_reduction)
109            self.reductionSpinBox.setValue(self.reduction)
110            self.reductionSpinBox.setSuffix("%")
111
112            if self.fit_to_page == pml.COPIER_FIT_TO_PAGE_ENABLED:
113                self.fitToPageCheckBox.setChecked(True)
114                self.reductionSpinBox.setEnabled(False)
115                self.reductionSlider.setEnabled(False)
116                self.reductionDefaultPushButton.setEnabled(True)
117            else:
118                self.fitToPageCheckBox.setChecked(False)
119                self.reductionSlider.setEnabled(True)
120                self.reductionSpinBox.setEnabled(True)
121                self.reductionDefaultPushButton.setEnabled(self.reduction != 100)
122
123            # num_copies
124            self.copiesSpinBox.setValue(self.num_copies)
125            self.copiesDefaultPushButton.setEnabled(self.num_copies != 1)
126
127            # quality
128            if self.quality == pml.COPIER_QUALITY_FAST:
129                self.qualityComboBox.setCurrentItem(0)
130                s = 'Fast'
131
132            elif self.quality == pml.COPIER_QUALITY_DRAFT:
133                self.qualityComboBox.setCurrentItem(1)
134                s = 'Draft'
135
136            elif self.quality == pml.COPIER_QUALITY_NORMAL:
137                self.qualityComboBox.setCurrentItem(2)
138                s = 'Normal'
139
140            elif self.quality == pml.COPIER_QUALITY_PRESENTATION:
141                self.qualityComboBox.setCurrentItem(3)
142                s = 'Presentation'
143
144            elif self.quality == pml.COPIER_QUALITY_BEST:
145                self.qualityComboBox.setCurrentItem(4)
146                s = 'Best'
147
148            log.debug("Default Quality: %d (%s)" % (self.quality, s))
149
150            self.qualityDefaultPushButton.setEnabled(self.quality != pml.COPIER_QUALITY_NORMAL)
151
152            log.debug("Default Num copies: %d" % self.num_copies)
153            log.debug("Default Contrast: %d" % self.contrast)
154            log.debug("Default Reduction: %d" % self.reduction)
155            log.debug("Maximum Reduction: %d" % self.max_reduction)
156            log.debug("Maximum Enlargement: %d" % self.max_enlargement)
157
158            if self.fit_to_page == pml.COPIER_FIT_TO_PAGE_ENABLED:
159                s = 'Enabled'  # 2
160            else:
161                s = 'Disabled' # 1
162
163            log.debug("Default Fit to page: %s (%s)" % (self.fit_to_page, s))
164            log.debug("Scan src (models.dat: scan-src): %d" % self.scan_src)
165
166        finally:
167            self.dev.closePML()
168            QApplication.restoreOverrideCursor()
169
170
171    def fillControls(self):
172        ScrollView.fillControls(self)
173
174        self.addGroupHeading("copies", self.__tr("Number of Copies"))
175        self.addCopies()
176
177        self.addGroupHeading("reduction", self.__tr("Enlargement, Reduction and Fit to Page"))
178        self.addEnlargementReduction()
179
180        self.addGroupHeading("contrast", self.__tr("Copy Contrast"))
181        self.addContrast()
182
183        self.addGroupHeading("quality", self.__tr("Copy Quality"))
184        self.addQuality()
185
186        self.addGroupHeading("space1", "")
187
188        self.copyButton = self.addActionButton("bottom_nav", self.__tr("Make Copies(s)"),
189                                self.copyButton_clicked, 'print.png', 'print.png',
190                                self.__tr("Close"), self.funcButton_clicked)
191
192
193
194    def onUpdate(self, cur_device=None):
195        log.debug("ScrollPrintView.onUpdate()")
196
197    def onDeviceChange(self, cur_device=None):
198        ScrollView.onDeviceChange(self, cur_device)
199
200        self.dev = copier.PMLCopyDevice(device_uri=self.cur_device.device_uri,
201                                        printer_name=self.cur_printer)
202
203        self.scan_src = self.dev.mq.get('scan-src', SCAN_SRC_FLATBED)
204        self.copy_type = self.dev.mq.get('copy-type', COPY_TYPE_DEVICE)
205
206        if self.scan_src == SCAN_SRC_SCROLLFED:
207            self.fitToPageCheckBox.setEnabled(False)
208            self.fit_to_page = pml.COPIER_FIT_TO_PAGE_DISABLED
209
210        self.getDeviceSettings()
211
212
213    def addCopies(self):
214        widget = self.getWidget()
215
216        layout12 = QHBoxLayout(widget,5,10,"layout12")
217
218        self.textLabel5 = QLabel(widget,"textLabel5")
219        layout12.addWidget(self.textLabel5)
220        spacer20 = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
221        layout12.addItem(spacer20)
222
223        self.copiesSpinBox = QSpinBox(widget,"copiesSpinBox")
224        layout12.addWidget(self.copiesSpinBox)
225
226        self.copiesDefaultPushButton = QPushButton(widget,"copiesDefaultPushButton")
227        layout12.addWidget(self.copiesDefaultPushButton)
228
229        self.textLabel5.setText(self.__tr("Number of copies:"))
230        self.copiesDefaultPushButton.setText(self.__tr("Default"))
231
232        self.copiesSpinBox.setMaxValue(99)
233        self.copiesSpinBox.setMinValue(1)
234        self.copiesSpinBox.setValue(1)
235
236        self.copiesDefaultPushButton.setEnabled(False)
237
238        self.connect(self.copiesDefaultPushButton, SIGNAL("clicked()"), self.copiesDefaultPushButton_clicked)
239        self.connect(self.copiesSpinBox, SIGNAL("valueChanged(int)"), self.copiesSpinBox_valueChanged)
240
241        self.addWidget(widget, "copies")
242
243    def copiesDefaultPushButton_clicked(self):
244        self.copiesSpinBox.setValue(1)
245        self.copiesDefaultPushButton.setEnabled(False)
246
247    def copiesSpinBox_valueChanged(self, i):
248        self.copiesDefaultPushButton.setEnabled(i != 1)
249        self.num_copies = i
250
251    def addQuality(self):
252        widget = self.getWidget()
253        layout34 = QHBoxLayout(widget,5,10,"layout34")
254
255        self.textLabel5_4 = QLabel(widget,"textLabel5_4")
256        self.textLabel5_4.setText(self.__tr("Quality:"))
257        layout34.addWidget(self.textLabel5_4)
258
259        spacer20_4 = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
260        layout34.addItem(spacer20_4)
261
262        self.qualityComboBox = QComboBox(0,widget,"qualityComboBox")
263        layout34.addWidget(self.qualityComboBox)
264
265        self.qualityDefaultPushButton = QPushButton(widget,"qualityDefaultPushButton")
266        layout34.addWidget(self.qualityDefaultPushButton)
267
268        self.qualityComboBox.clear()
269        self.qualityComboBox.insertItem(self.__tr("Fast")) # 0
270        self.qualityComboBox.insertItem(self.__tr("Draft")) # 1
271        self.qualityComboBox.insertItem(self.__tr("Normal")) # 2
272        self.qualityComboBox.insertItem(self.__tr("Presentation")) # 3
273        self.qualityComboBox.insertItem(self.__tr("Best")) # 4
274        self.qualityComboBox.setCurrentItem(2) # Normal
275
276        self.qualityDefaultPushButton.setText(self.__tr("Default"))
277        self.qualityDefaultPushButton.setEnabled(False)
278
279        self.connect(self.qualityComboBox, SIGNAL("activated(int)"), self.qualityComboBox_activated)
280        self.connect(self.qualityDefaultPushButton, SIGNAL("clicked()"), self.qualityDefaultPushButton_clicked)
281
282        self.addWidget(widget, "quality")
283
284    def qualityDefaultPushButton_clicked(self):
285        self.qualityDefaultPushButton.setEnabled(False)
286        self.qualityComboBox.setCurrentItem(2) # Normal
287        self.quality = pml.COPIER_QUALITY_NORMAL
288
289    def qualityComboBox_activated(self, i):
290        self.qualityDefaultPushButton.setEnabled(i != 2) # Normal
291
292        if i == 0:
293            self.quality = pml.COPIER_QUALITY_FAST
294        elif i == 1:
295            self.quality = pml.COPIER_QUALITY_DRAFT
296        elif i == 2:
297            self.quality = pml.COPIER_QUALITY_NORMAL
298        elif i == 3:
299            self.quality = pml.COPIER_QUALITY_PRESENTATION
300        elif i == 4:
301            self.quality = pml.COPIER_QUALITY_BEST
302
303
304    def addEnlargementReduction(self):
305        widget = self.getWidget()
306        layout43 = QGridLayout(widget,1,1,5,10,"layout43")
307
308        self.reductionSlider = QSlider(widget,"reductionSlider")
309        self.reductionSlider.setOrientation(QSlider.Horizontal)
310
311        layout43.addWidget(self.reductionSlider,0,2)
312
313        self.reductionSpinBox = QSpinBox(widget, "reductionSpinBox")
314        self.reductionSpinBox.setMaxValue(100)
315        self.reductionSpinBox.setMinValue(0)
316        self.reductionSpinBox.setValue(100)
317        self.reductionSpinBox.setSuffix("%")
318        layout43.addWidget(self.reductionSpinBox,0,3)
319
320        spacer42 = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
321        layout43.addItem(spacer42,0,1)
322
323        self.fitToPageCheckBox = QCheckBox(widget,"fitToPageCheckBox")
324        layout43.addWidget(self.fitToPageCheckBox,1,2)
325
326        self.reductionDefaultPushButton = QPushButton(widget,"reductionDefaultPushButton")
327        layout43.addWidget(self.reductionDefaultPushButton,0,4)
328
329        self.textLabel1 = QLabel(widget,"textLabel1")
330        layout43.addWidget(self.textLabel1,0,0)
331
332        self.textLabel1.setText(self.__tr("Enlargement or reduction (percent):"))
333        self.fitToPageCheckBox.setText(self.__tr("Fit to Page"))
334        self.reductionDefaultPushButton.setText(self.__tr("Default"))
335
336        self.reductionSlider.setRange(25, 400)
337
338        self.connect(self.reductionSlider,SIGNAL("valueChanged(int)"),self.reductionSlider_valueChanged)
339        self.connect(self.fitToPageCheckBox,SIGNAL("clicked()"),self.fitToPageCheckBox_clicked)
340        self.connect(self.reductionDefaultPushButton, SIGNAL("clicked()"), self.reductionDefaultPushButton_clicked)
341        self.connect(self.reductionSpinBox, SIGNAL("valueChanged(int)"), self.reductionSpinBox_valueChanged)
342
343        self.addWidget(widget, "reduction")
344
345    def reductionSlider_valueChanged(self,a0):
346        self.reduction = a0
347        self.reductionSpinBox.setValue(a0)
348        self.reductionDefaultPushButton.setEnabled(a0 != 100)
349
350    def reductionSpinBox_valueChanged(self, a0):
351        self.reduction = a0
352        self.reductionSlider.setValue(a0)
353        self.reductionDefaultPushButton.setEnabled(a0 != 100)
354
355    def fitToPageCheckBox_clicked(self):
356        if self.fitToPageCheckBox.isChecked():
357            self.fit_to_page = pml.COPIER_FIT_TO_PAGE_ENABLED
358            self.reductionSpinBox.setEnabled(False)
359            self.reductionSlider.setEnabled(False)
360            self.reductionDefaultPushButton.setEnabled(True)
361        else:
362            self.fit_to_page = pml.COPIER_FIT_TO_PAGE_DISABLED
363            self.reductionSlider.setEnabled(True)
364            self.reductionSpinBox.setEnabled(True)
365            self.reductionDefaultPushButton.setEnabled(self.reductionSlider.value() != 100)
366
367    def reductionDefaultPushButton_clicked(self):
368        self.reduction = 100
369        self.reductionSlider.setValue(100)
370        self.reductionSlider.setEnabled(True)
371        self.reductionSpinBox.setValue(100)
372        self.reductionSpinBox.setEnabled(True)
373        self.fitToPageCheckBox.setChecked(False)
374        self.fit_to_page = False
375
376    def addContrast(self):
377        widget = self.getWidget()
378
379        layout41 = QGridLayout(widget,1,1,5,10,"layout41")
380
381        self.textLabel1_2 = QLabel(widget,"textLabel1_2")
382
383        layout41.addWidget(self.textLabel1_2,0,0)
384
385        self.contrastDefaultPushButton = QPushButton(widget,"contrastDefaultPushButton")
386
387        layout41.addWidget(self.contrastDefaultPushButton,0,4)
388        spacer41 = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
389        layout41.addItem(spacer41,0,1)
390
391        self.contrastSlider = QSlider(widget,"contrastSlider")
392        self.contrastSlider.setMinValue(-5)
393        self.contrastSlider.setMaxValue(5)
394        self.contrastSlider.setPageStep(1)
395        self.contrastSlider.setOrientation(QSlider.Horizontal)
396
397        layout41.addWidget(self.contrastSlider,0,2)
398
399        self.contrastSpinBox = QSpinBox(widget, "contrastSpinBox")
400        self.contrastSpinBox.setMinValue(-5)
401        self.contrastSpinBox.setMaxValue(5)
402
403        layout41.addWidget(self.contrastSpinBox,0,3)
404
405        self.textLabel1_2.setText(self.__tr("Contrast (-5 lighter to +5 darker):"))
406        self.contrastDefaultPushButton.setText(self.__tr("Default"))
407
408        self.connect(self.contrastSlider,SIGNAL("valueChanged(int)"),self.contrastSlider_valueChanged)
409        self.connect(self.contrastSpinBox, SIGNAL("valueChanged(int)"), self.contrastSpinBox_valueChanged)
410        self.connect(self.contrastDefaultPushButton, SIGNAL("clicked()"), self.contrastDefaultPushButton_clicked)
411
412        self.addWidget(widget, "contrast")
413
414
415    def contrastSlider_valueChanged(self, a0):
416        self.contrastSpinBox.setValue(a0)
417        self.contrast = a0 * 25
418        self.contrastDefaultPushButton.setEnabled(a0 != 0)
419
420    def contrastSpinBox_valueChanged(self, a0):
421        if a0 >= 0:
422            self.contrastSpinBox.setPrefix("+")
423        else:
424            self.contrastSpinBox.setPrefix("")
425
426        self.contrastSlider.setValue(a0)
427        self.contrast = a0 * 25
428        self.contrastDefaultPushButton.setEnabled(a0 != 0)
429
430    def contrastDefaultPushButton_clicked(self):
431        self.contrastSpinBox.setValue(0)
432        self.contrastSpinBox.setPrefix("+")
433        self.contrastSlider.setValue(0)
434        self.contrast = 0
435
436
437    def copy_canceled(self):
438        self.event_queue.put(copier.COPY_CANCELED)
439        self.dev.sendEvent(EVENT_COPY_JOB_CANCELED)
440
441    def copy_timer_timeout(self):
442        while self.update_queue.qsize():
443            try:
444                status = self.update_queue.get(0)
445            except queue.Empty:
446                break
447
448            if status == copier.STATUS_IDLE:
449                self.copy_timer.stop()
450
451                #self.pb.hide()
452                #self.form.statusBar().removeWidget(self.pb)
453
454            elif status in (copier.STATUS_SETTING_UP, copier.STATUS_WARMING_UP):
455                #self.pb.setProgress(self.pb.progress()+1)
456                pass
457
458            elif status == copier.STATUS_ACTIVE:
459                #self.pb.setProgress(self.pb.progress()+1)
460                pass
461
462            elif status in (copier.STATUS_ERROR, copier.STATUS_DONE):
463                self.copy_timer.stop()
464                #self.pb.hide()
465                #self.form.statusBar().removeWidget(self.pb)
466
467                # Close the dialog box.
468                #
469                if self.waitdlg is not None:
470                    self.waitdlg.hide()
471                    self.waitdlg.close()
472                    self.waitdlg = None
473
474                if status == copier.STATUS_ERROR:
475                    self.form.FailureUI(self.__tr("<b>Copier error.</b><p>"))
476                    self.dev.sendEvent(EVENT_COPY_JOB_FAIL)
477
478                elif status == copier.STATUS_DONE:
479                    pass
480                    self.dev.sendEvent(EVENT_END_COPY_JOB)
481
482                self.cur_device.close()
483                self.copyButton.setEnabled(True)
484
485                self.form.close()
486
487
488    def copyButton_clicked(self):
489        self.copyButton.setEnabled(False)
490        try:
491            try:
492                self.dev.open()
493            except Error:
494                self.form.FailureUI(self.__tr("<b>Cannot copy: Device is busy or not available.</b><p>Please check device and try again. [1]"))
495                return
496
497            self.dev.sendEvent(EVENT_START_COPY_JOB, self.cur_printer, 0, '')
498            #self.pb = QProgressBar()
499            #self.pb.setTotalSteps(2)
500            #self.form.statusBar().addWidget(self.pb)
501            #self.pb.show()
502
503            log.debug("Num copies: %d" % self.num_copies)
504            log.debug("Contrast: %d" % self.contrast)
505            log.debug("Reduction: %d" % self.reduction)
506
507            s = 'Normal'
508            if self.quality == pml.COPIER_QUALITY_FAST:
509                s = 'Fast'
510            elif self.quality == pml.COPIER_QUALITY_DRAFT:
511                s = 'Draft'
512            elif self.quality == pml.COPIER_QUALITY_NORMAL:
513                s = 'Normal'
514            elif self.quality == pml.COPIER_QUALITY_PRESENTATION:
515                s = 'Presentation'
516            elif self.quality == pml.COPIER_QUALITY_BEST:
517                s = 'Best'
518
519            log.debug("Quality: %d (%s)" % (self.quality, s))
520
521            if self.fit_to_page == pml.COPIER_FIT_TO_PAGE_ENABLED:
522                s = 'Enabled'  # 2
523            else:
524                s = 'Disabled' # 1
525
526            log.debug("Fit to page: %s (%s)" % (self.fit_to_page, s))
527            log.debug("Scan src: %d" % self.scan_src)
528
529            # Open the dialog box.
530            #
531            self.waitdlg = WaitForm(0, self.__tr("Copying..."), self.copy_canceled, self, modal=1)
532            self.waitdlg.show()
533
534            self.copy_timer = QTimer(self, "CopyTimer")
535            self.connect(self.copy_timer, SIGNAL('timeout()'), self.copy_timer_timeout)
536            self.copy_timer.start(1000) # 1 sec UI updates
537
538            self.dev.copy(self.num_copies, self.contrast, self.reduction,
539                          self.quality, self.fit_to_page, self.scan_src,
540                          self.update_queue, self.event_queue)
541
542        finally:
543            #self.cur_device.close()
544            #self.copyButton.setEnabled(True)
545            pass
546
547    def funcButton_clicked(self):
548        self.dev.close()
549        self.form.close()
550
551    def __tr(self,s,c = None):
552        return qApp.translate("ScrollCopy",s,c)
553