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