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# Std Lib
23
24# Local
25from base.g import *
26from prnt import cups
27from base import device
28from base.sixext import  to_unicode
29from .ui_utils import load_pixmap
30
31# Qt
32from qt import *
33
34
35
36class Widget(QWidget):
37    def __init__(self, parent=None, name=None, fl=0):
38        QWidget.__init__(self, parent, name, fl)
39        self.control = None
40
41    def setControl(self, control):
42        self.control = control
43
44
45
46class ScrollView(QScrollView):
47    def __init__(self, service=None, parent=None, name=None, fl=0):
48        QScrollView.__init__(self, parent, name, fl)
49
50        self.service = service
51        self.items = {}
52        self.enableClipper(True)
53        self.viewport().setPaletteBackgroundColor(qApp.palette().color(QPalette.Active, QColorGroup.Background))
54        self.cur_device = None
55        self.cur_printer = None
56        self.item_margin = 2
57        self.y = 0
58        self.printers = []
59        self.maximize = None
60        self.orig_height = 0
61        self.content_padding = 20
62
63        if log.is_debug():
64            self.heading_color = qApp.palette().color(QPalette.Active, QColorGroup.Base)
65            self.frame_shape = QFrame.Box
66        else:
67            self.heading_color = qApp.palette().color(QPalette.Active, QColorGroup.Background)
68            self.frame_shape = QFrame.NoFrame
69
70    def getWidget(self):
71        widget = Widget(self.viewport(),"widget")
72        widget.setPaletteBackgroundColor(qApp.palette().color(QPalette.Active, QColorGroup.Background))
73        return widget
74
75    def viewportResizeEvent(self, e):
76        QScrollView.viewportResizeEvent(self, e)
77
78        total_height = 0
79        item_margin = self.item_margin
80        width = e.size().width()
81
82        for w in self.items:
83            height  = self.items[w].size().height()
84            self.items[w].resize(width, height)
85            self.items[w].setMinimumWidth(width)
86            total_height += (height + item_margin)
87
88        if self.maximize is not None:
89            self.maximizeControl(total_height)
90
91        self.resizeContents(e.size().width(), total_height + self.content_padding)
92
93    def maximizeControl(self, total_height=0):
94        if self.maximize is not None:
95            try:
96                self.items[self.maximize]
97            except KeyError:
98                return
99
100            if total_height == 0:
101                item_margin = self.item_margin
102                for w in self.items:
103                    total_height += (self.items[w].size().height() + item_margin)
104
105            if len(self.items) == 1:
106                #total_height += item_margin
107                self.content_padding = 0
108
109            width = self.items[self.maximize].size().width()
110            old_height = self.items[self.maximize].size().height()
111
112            new_height = max((self.visibleHeight()-(total_height-old_height)),
113                self.orig_height)
114
115            delta = new_height - old_height
116
117            if delta:
118                self.items[self.maximize].resize(width, new_height)
119                self.resizeContents(width, self.contentsHeight()+delta+self.content_padding)
120                m_y = self.childY(self.items[self.maximize])
121
122                for w in self.items:
123                    w_y = self.childY(self.items[w])
124                    if w_y > m_y:
125                        self.moveChild(self.items[w], 0, w_y+delta)
126
127
128    def onDeviceChange(self, cur_device=None, updating=False):
129        if cur_device is not None:
130            log.debug("ScrollView.onDeviceChange(%s)" % cur_device.device_uri)
131        else:
132            log.debug("ScrollView.onDeviceChange(None)")
133
134        self.cur_device = cur_device
135
136        if self.cur_device is not None and self.cur_device.supported:
137            #if not updating or not self.cur_printer:
138            if not self.cur_printer:
139                try:
140                    cur_printer = self.cur_device.cups_printers[0]
141                except IndexError:
142                    log.error("Printer list empty") # Shouldn't happen!
143                    self.cur_printer = None
144                    return
145
146                #self.isFax()
147                self.printers = cups.getPrinters()
148                self.onPrinterChange(cur_printer)
149                self.cur_printer = cur_printer
150
151            #else:
152            if 1:
153                QApplication.setOverrideCursor(QApplication.waitCursor)
154                try:
155                    if 1:
156                    #try:
157                        self.fillControls()
158                    #except Exception, e:
159                    #    log.exception()
160                finally:
161                    QApplication.restoreOverrideCursor()
162
163        else:
164            log.debug("Unsupported device")
165            self.y = 0
166            self.clear()
167
168            self.addGroupHeading("error", self.__tr("ERROR: No device found or unsupported device."))
169
170    def onUpdate(self, cur_device=None):
171        log.debug("ScrollView.onUpdate()")
172        return self.onDeviceChange(cur_device, True)
173
174    def fillControls(self):
175        log.debug("fillControls(%s)" % str(self.name()))
176        self.y = 0
177        self.clear()
178
179    def onPrinterChange(self, printer_name):
180        if printer_name == self.cur_printer or printer_name is None:
181            return
182
183        self.cur_printer = to_unicode(printer_name)
184
185        if self.cur_device is not None and self.cur_device.supported:
186            #self.isFax()
187            QApplication.setOverrideCursor(QApplication.waitCursor)
188            try:
189                if 1:
190                #try:
191                    self.fillControls()
192                #except Exception, e:
193                #    log.exception()
194            finally:
195                QApplication.restoreOverrideCursor()
196
197            if self.cur_printer is not None:
198                try:
199                    self.printerComboBox.setCurrentText(self.cur_printer)
200                except AttributeError:
201                    pass
202
203        else:
204            self.y = 0
205            self.clear()
206
207    def addWidget(self, widget, key, control=None, maximize=False):
208        try:
209            self.items[key]
210        except KeyError:
211            if maximize:
212                self.maximize = key
213                widget.resize(widget.size().width(), 150)
214                self.orig_height = widget.size().height()
215
216            try:
217                widget.setControl(control)
218            except AttributeError:
219                pass
220            self.items[key] = widget
221            widget.setMinimumWidth(self.visibleWidth())
222            widget.adjustSize()
223            self.addChild(widget, 0, self.y)
224            self.y += (widget.size().height() + self.item_margin)
225            self.resizeContents(self.visibleWidth(), self.y + self.content_padding)
226            widget.show()
227        #else:
228        #    log.debug("ERROR: Duplicate control name: %s" % key)
229
230    def clear(self):
231        if len(self.items):
232            for x in self.items:
233                self.removeChild(self.items[x])
234                self.items[x].hide()
235
236            self.items.clear()
237
238    def addGroupHeading(self, group, heading, read_only=False):
239        widget = self.getWidget()
240        widget.setMinimumHeight(30)
241
242        layout = QGridLayout(widget, 0, 0, 5, 0, "layout")
243        textLabel2 = QLabel(widget, "textLabel2")
244
245        textLabel2.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,
246            QSizePolicy.Maximum, 0, 0,
247            textLabel2.sizePolicy().hasHeightForWidth()))
248
249        if log.is_debug():
250            textLabel2.setFrameShape(self.frame_shape)
251
252        elif heading:
253            textLabel2.setFrameShape(QFrame.TabWidgetPanel)
254            textLabel2.setPaletteBackgroundColor(self.heading_color)
255
256        if read_only:
257            s = self.__tr("<b>%1 (read only)</b>").arg(heading) # <nobr>
258        else:
259            s = QString("<b>%1</b>").arg(heading)
260
261        # If label is kinda long, provide a tooltip to allow reading the whole thing
262        if s.length() > 32:
263            QToolTip.add(textLabel2, s)
264
265        textLabel2.setText(s)
266        textLabel2.setAlignment(QLabel.AlignLeft | QLabel.AlignVCenter | Qt.SingleLine)
267
268        layout.addWidget(textLabel2, 0, 0)
269
270        self.addWidget(widget, "g:"+to_unicode(group))
271
272
273    def addActionButton(self, name, action_text, action_func,
274                        action_pixmap=None, disabled_action_pixmap=None,
275                        nav_text ='', nav_func=None):
276
277        widget = self.getWidget()
278
279        self.actionPushButton = None
280        self.navPushButton = None
281
282        layout36 = QHBoxLayout(widget,5,10,"layout36")
283
284        if nav_func is not None:
285            self.navPushButton = QPushButton(widget,"navPushButton")
286            navPushButton_font = QFont(self.navPushButton.font())
287            navPushButton_font.setBold(1)
288            self.navPushButton.setFont(navPushButton_font)
289            self.navPushButton.setText(nav_text)
290            layout36.addWidget(self.navPushButton)
291
292            self.connect(self.navPushButton, SIGNAL("clicked()"), nav_func)
293
294        spacer35 = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
295        layout36.addItem(spacer35)
296
297        if action_func is not None:
298            if action_pixmap is None:
299                self.actionPushButton = QPushButton(widget, "actionPushButton")
300            else:
301                self.actionPushButton = PixmapLabelButton(widget, action_pixmap,
302                    disabled_action_pixmap, 'actionPushButton')
303
304            actionPushButton_font = QFont(self.actionPushButton.font())
305            actionPushButton_font.setBold(1)
306            self.actionPushButton.setFont(actionPushButton_font)
307            layout36.addWidget(self.actionPushButton)
308
309            self.actionPushButton.setText(action_text)
310
311            self.connect(self.actionPushButton, SIGNAL("clicked()"), action_func)
312
313        self.addWidget(widget, name)
314
315        if self.actionPushButton is not None:
316            return self.actionPushButton
317
318        elif self.navPushButton is not None:
319            return self.navPushButton
320
321        else:
322            return None
323
324    def printerComboBox_activated(self, p):
325        self.cur_printer = str(p)
326
327    def addPrinterFaxList(self): # printers=True, faxes=False):
328        widget = self.getWidget()
329
330        layout = QGridLayout(widget,1,1,5,10,"layout")
331
332        self.printernameTextLabel = QLabel(widget,"printernameTextLabel")
333        layout.addWidget(self.printernameTextLabel,0,0)
334
335        self.printerComboBox = QComboBox(0,widget,"printerComboBox")
336        layout.addWidget(self.printerComboBox,0,1)
337
338        #print self.cur_device.device_type
339        if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
340            self.addGroupHeading("printer_list_heading", self.__tr("Printer"))
341            self.printernameTextLabel.setText(self.__tr("Printer Name:"))
342        else:
343            self.addGroupHeading("fax_list_heading", self.__tr("Fax"))
344            self.printernameTextLabel.setText(self.__tr("Fax Name:"))
345
346        self.printers = cups.getPrinters()
347        self.cur_printer = None
348        for p in self.printers:
349            if p.device_uri == self.cur_device.device_uri:
350
351                self.printerComboBox.insertItem(p.name)
352
353                if self.cur_printer is None:
354                    self.cur_printer = p.name
355
356        if self.cur_printer is None:
357            #log.error("No fax queue found")
358            self.y = 0
359            self.clear()
360
361            #if printers and faxes:
362            if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
363                self.addGroupHeading("error", self.__tr("ERROR: No CUPS queue found for device."))
364            else:
365                self.addGroupHeading("error", self.__tr("ERROR: No CUPS fax queue found for device."))
366
367            return False
368
369        else:
370            self.connect(self.printerComboBox, SIGNAL("activated(const QString&)"), self.printerComboBox_activated)
371
372            self.addWidget(widget, "printer_list")
373            return True
374
375
376    def addLoadPaper(self, paper_type=PAPER_TYPE_PLAIN):
377        self.addGroupHeading("load_paper", self.__tr("Load Paper"))
378
379        widget = self.getWidget()
380        layout1 = QGridLayout(widget, 1, 2, 5, 10,"layout1")
381
382        layout1.setColStretch(0, 1)
383        layout1.setColStretch(1, 10)
384
385        icon = QLabel(widget, "icon")
386        icon.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed, 0, 0,
387            icon.sizePolicy().hasHeightForWidth()))
388
389        icon.setScaledContents(1)
390        layout1.addWidget(icon, 0, 0)
391
392        textLabel = QLabel(widget, "textLabel")
393        textLabel.setAlignment(QLabel.WordBreak)
394        textLabel.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred, 0, 0,
395            textLabel.sizePolicy().hasHeightForWidth()))
396        textLabel.setFrameShape(self.frame_shape)
397        layout1.addWidget(textLabel, 0, 1)
398
399        spacer1 = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
400        layout1.addItem(spacer1, 0, 2)
401
402        if paper_type == PAPER_TYPE_PLAIN:
403            textLabel.setText(self.__tr("A page will be printed. Please load Letter/A4 <b>Plain Paper</b> into the printer."))
404        elif paper_type == PAPER_TYPE_HP_ADV_PHOTO:
405            textLabel.setText(self.__tr("A page will be printed. Please load Letter/A4 <b>HP Advanced Photo Paper - Glossy</b> into the printer."))
406
407        icon.setPixmap(load_pixmap("load_paper", 'other'))
408
409        self.addWidget(widget, "load_paper")
410
411
412    def cleanup(self):
413        pass
414
415    def __tr(self,s,c = None):
416        return qApp.translate("ScrollView",s,c)
417
418
419
420class PixmapLabelButton(QPushButton):
421    def __init__(self, parent=None, pixmap=None, disabled_pixmap=None, name='', subdir=None):
422        QPushButton.__init__(self, parent, name)
423
424        if subdir is None:
425            subdir = '16x16'
426
427        if type(pixmap) == type(''):
428            self.pixmap = load_pixmap(pixmap, subdir)
429        else:
430            self.pixmap = pixmap
431
432        if type(disabled_pixmap) == type(''):
433            self.disabled_pixmap = load_pixmap(disabled_pixmap, subdir)
434        else:
435            self.disabled_pixmap = disabled_pixmap
436
437        self.pixmap_width, self.pixmap_height = self.pixmap.width(), self.pixmap.height()
438        self.width_set = None
439
440
441    def drawButtonLabel(self, painter):
442        button_width, button_height = self.width(), self.height()
443
444        adj = 0
445        if self.isDown():
446            adj = 1
447
448        if self.isEnabled():
449            painter.setPen(Qt.black)
450        else:
451            painter.setPen(Qt.gray)
452
453        text_rect = painter.boundingRect(0, 0, 1000, 1000, Qt.AlignLeft, self.text())
454        text_width, text_height = text_rect.right() - text_rect.left(), text_rect.bottom() - text_rect.top()
455
456        button_width_center = button_width/2
457        button_height_center = button_height/2
458        combined_width_center = (self.pixmap_width + text_width + 10)/2
459
460
461        if self.isEnabled() or self.disabled_pixmap is None:
462            painter.drawPixmap(button_width_center - combined_width_center + adj,
463                button_height_center - self.pixmap_height/2 + adj, self.pixmap)
464        else:
465            painter.drawPixmap(button_width_center - combined_width_center + adj,
466                button_height_center - self.pixmap_height/2 + adj, self.disabled_pixmap)
467
468        if self.width_set is None:
469            self.setMinimumWidth(self.pixmap_width + text_width + 20)
470            self.width_set = 0
471
472        painter.drawText(button_width_center - combined_width_center +
473            self.pixmap_width + 5 + adj,
474            button_height_center - text_height/2 + adj, 1000, 1000,
475            Qt.AlignLeft, self.text())
476
477