~ubuntu-branches/ubuntu/lucid/kdeadmin/lucid-proposed

« back to all changes in this revision

Viewing changes to debian/patches/kubuntu_02_system_config_printer_trunk.diff

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2009-08-01 23:38:57 UTC
  • mfrom: (1.2.30 upstream)
  • Revision ID: james.westby@ubuntu.com-20090801233857-iadqweam8cr8hnd0
Tags: 4:4.3.0-0ubuntu1
* New upstream release
* Remove depends on hal-cups-utils, which no longer exists

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/CMakeLists.txt kdeadmin-4.2.2/system-config-printer-kde/CMakeLists.txt
2
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/CMakeLists.txt        2009-01-01 16:27:18.000000000 +0000
3
 
+++ kdeadmin-4.2.2/system-config-printer-kde/CMakeLists.txt     2009-04-09 22:56:36.000000000 +0100
4
 
@@ -1,15 +1,13 @@
5
 
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}  ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules )
6
 
+find_package( KDE4 REQUIRED )
7
 
 
8
 
-MACRO(PYKDE4_ADD_EXECUTABLE _pyname _exename)
9
 
-    INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -DTARGET=${DATA_INSTALL_DIR}/system-config-printer-kde/${_pyname} -DLINK_NAME=${BIN_INSTALL_DIR}/${_exename} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/create_exe_symlink.cmake)" )
10
 
-ENDMACRO(PYKDE4_ADD_EXECUTABLE)
11
 
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}  ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules )
12
 
 
13
 
 macro_optional_find_package(PythonLibrary)
14
 
 macro_optional_find_package(SIP)
15
 
 
16
 
 macro_optional_find_package(PyQt4)
17
 
 IF(NOT PYQT4_FOUND)
18
 
-    macro_log_feature(PYQT4_FOUND "PyQt4" "PyQt4 was not found.  It is needed by system-config-printer-kde to run. (Use -DINSTALL_SYSTEM_CONFIG_PRINTER=TRUE to install anyway)" "http://www.riverbankcomputing.co.uk/software/pyqt/" FALSE)
19
 
+    macro_log_feature(PYQT4_FOUND "PyQt4" "PyQt4 was not found.  It is needed by system-config-printer-kde to run. (Use -DINSTALL_SYSTEM_CONFIG_PRINTER=TRUE to install anyway)" "http://www.riverbankcomputing.co.uk/pyqt/" FALSE)
20
 
 ENDIF(NOT PYQT4_FOUND)
21
 
 
22
 
 macro_optional_find_package(PyKDE)
23
 
@@ -35,10 +33,13 @@
24
 
     install( FILES
25
 
         new-printer.ui
26
 
         system-config-printer.ui
27
 
-        system-config-printer-kde.py
28
 
+        kcm-scpk.py
29
 
+        options.py
30
 
+        optionwidgets.py
31
 
+        ipp-browse-dialog.ui
32
 
+        smb-browse-dialog.ui
33
 
         DESTINATION ${DATA_INSTALL_DIR}/system-config-printer-kde )
34
 
-    PYKDE4_ADD_EXECUTABLE(system-config-printer-kde.py system-config-printer-kde)
35
 
-    install(FILES system-config-printer-kde.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
36
 
+    install(FILES kcm-scpk.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
37
 
 ENDIF(INSTALL_SYSTEM_CONFIG_PRINTER)
38
 
 
39
 
 macro_display_feature_log()
40
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/COMMENTS kdeadmin-4.2.2/system-config-printer-kde/COMMENTS
41
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/COMMENTS      1970-01-01 01:00:00.000000000 +0100
42
 
+++ kdeadmin-4.2.2/system-config-printer-kde/COMMENTS   2009-04-09 22:56:08.000000000 +0100
43
 
@@ -0,0 +1,13 @@
44
 
+01:37 <seele> the menu/list on the left looks like a tree, will it eventually become a list like the other modules? icon and all?
45
 
+01:38 <seele> under configured printers, options and job options tabs, widgets dont have correct alignment
46
 
+01:38 <seele> job options is pretty scary looking too, we'll probably need to work on that
47
 
+01:38 <seele> i assume advanced is wip
48
 
+01:39 <seele> under policies tab, do you think the uesr and group permissions make sense? i know we discussed it a while ago as a way of doing it (or
49
 
+              someone else if not you)
50
 
+01:39 <seele> also.. remove should be disabled until you select a list item
51
 
+01:41 <seele> under settings, it takes a number of seconds for the change driver wizard to load after clicking the button. will this be improved eventually?
52
 
+01:41 <seele> also, is the change driver wizard within scope of what we can improve? (not going to comment on it now, but it could be tweaked)
53
 
+01:43 <seele> the remove printer button gets lost with the other printer buttons on that page. i'll have to think about what to do with that section, i dont
54
 
+              know where else remove printer could go
55
 
+01:45 <seele> the other parts of the UI, i'm not sure how much is up for debate. for example, the new printer wizard. also, i dont know much about print
56
 
+              server configuration and if those options are sufficient and presented in the best way
57
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/ipp-browse-dialog.ui kdeadmin-4.2.2/system-config-printer-kde/ipp-browse-dialog.ui
58
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/ipp-browse-dialog.ui  1970-01-01 01:00:00.000000000 +0100
59
 
+++ kdeadmin-4.2.2/system-config-printer-kde/ipp-browse-dialog.ui       2009-04-09 22:56:08.000000000 +0100
60
 
@@ -0,0 +1,124 @@
61
 
+<ui version="4.0" >
62
 
+ <class>IPPBrowseDialog</class>
63
 
+ <widget class="QDialog" name="IPPBrowseDialog" >
64
 
+  <property name="windowModality" >
65
 
+   <enum>Qt::NonModal</enum>
66
 
+  </property>
67
 
+  <property name="geometry" >
68
 
+   <rect>
69
 
+    <x>0</x>
70
 
+    <y>0</y>
71
 
+    <width>400</width>
72
 
+    <height>300</height>
73
 
+   </rect>
74
 
+  </property>
75
 
+  <property name="font" >
76
 
+   <font>
77
 
+    <weight>50</weight>
78
 
+    <bold>false</bold>
79
 
+   </font>
80
 
+  </property>
81
 
+  <property name="focusPolicy" >
82
 
+   <enum>Qt::StrongFocus</enum>
83
 
+  </property>
84
 
+  <property name="windowTitle" >
85
 
+   <string>IPP Browser</string>
86
 
+  </property>
87
 
+  <property name="modal" >
88
 
+   <bool>true</bool>
89
 
+  </property>
90
 
+  <widget class="QWidget" name="layoutWidget" >
91
 
+   <property name="geometry" >
92
 
+    <rect>
93
 
+     <x>21</x>
94
 
+     <y>250</y>
95
 
+     <width>361</width>
96
 
+     <height>41</height>
97
 
+    </rect>
98
 
+   </property>
99
 
+   <layout class="QHBoxLayout" name="horizontalLayout" >
100
 
+    <item>
101
 
+     <widget class="KPushButton" name="btnIPPBrowseRefresh" >
102
 
+      <property name="text" >
103
 
+       <string>Refresh</string>
104
 
+      </property>
105
 
+     </widget>
106
 
+    </item>
107
 
+    <item>
108
 
+     <spacer name="horizontalSpacer" >
109
 
+      <property name="orientation" >
110
 
+       <enum>Qt::Horizontal</enum>
111
 
+      </property>
112
 
+      <property name="sizeHint" stdset="0" >
113
 
+       <size>
114
 
+        <width>40</width>
115
 
+        <height>20</height>
116
 
+       </size>
117
 
+      </property>
118
 
+     </spacer>
119
 
+    </item>
120
 
+    <item>
121
 
+     <widget class="KPushButton" name="btnIPPBrowseOk" >
122
 
+      <property name="text" >
123
 
+       <string>Ok</string>
124
 
+      </property>
125
 
+      <property name="shortcut" >
126
 
+       <string>Ctrl+O</string>
127
 
+      </property>
128
 
+     </widget>
129
 
+    </item>
130
 
+    <item>
131
 
+     <widget class="KPushButton" name="btnIPPBrowseCancel" >
132
 
+      <property name="text" >
133
 
+       <string>Cancel</string>
134
 
+      </property>
135
 
+     </widget>
136
 
+    </item>
137
 
+   </layout>
138
 
+  </widget>
139
 
+  <widget class="QTreeWidget" name="twIPPBrowser" >
140
 
+   <property name="geometry" >
141
 
+    <rect>
142
 
+     <x>30</x>
143
 
+     <y>10</y>
144
 
+     <width>341</width>
145
 
+     <height>221</height>
146
 
+    </rect>
147
 
+   </property>
148
 
+   <property name="sizePolicy" >
149
 
+    <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
150
 
+     <horstretch>0</horstretch>
151
 
+     <verstretch>0</verstretch>
152
 
+    </sizepolicy>
153
 
+   </property>
154
 
+   <property name="sortingEnabled" >
155
 
+    <bool>true</bool>
156
 
+   </property>
157
 
+   <property name="allColumnsShowFocus" >
158
 
+    <bool>true</bool>
159
 
+   </property>
160
 
+   <property name="columnCount" >
161
 
+    <number>2</number>
162
 
+   </property>
163
 
+   <column>
164
 
+    <property name="text" >
165
 
+     <string>1</string>
166
 
+    </property>
167
 
+   </column>
168
 
+   <column>
169
 
+    <property name="text" >
170
 
+     <string>1</string>
171
 
+    </property>
172
 
+   </column>
173
 
+  </widget>
174
 
+ </widget>
175
 
+ <customwidgets>
176
 
+  <customwidget>
177
 
+   <class>KPushButton</class>
178
 
+   <extends>QPushButton</extends>
179
 
+   <header>kpushbutton.h</header>
180
 
+  </customwidget>
181
 
+ </customwidgets>
182
 
+ <resources/>
183
 
+ <connections/>
184
 
+</ui>
185
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.desktop kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.desktop
186
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.desktop      1970-01-01 01:00:00.000000000 +0100
187
 
+++ kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.desktop   2009-04-09 22:56:08.000000000 +0100
188
 
@@ -0,0 +1,21 @@
189
 
+[Desktop Entry]
190
 
+Exec=kcmshell4 kcm-scpk
191
 
+Icon=printer
192
 
+Type=Service
193
 
+X-KDE-ServiceTypes=KCModule
194
 
+X-DocPath=kcontrol/colors/index.html
195
 
+
196
 
+X-KDE-Library=kpythonpluginfactory
197
 
+X-KDE-ParentApp=kcontrol
198
 
+X-KDE-PluginKeyword=system-config-printer-kde/kcm-scpk.py
199
 
+
200
 
+X-KDE-System-Settings-Parent-Category=system
201
 
+X-KDE-Weight=60
202
 
+
203
 
+Name=Printer Configuration
204
 
+
205
 
+Comment=Configure local and remote Printers
206
 
+
207
 
+X-KDE-Keywords=python kcm
208
 
+
209
 
+Categories=Qt;KDE;System;
210
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.py kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.py
211
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.py   1970-01-01 01:00:00.000000000 +0100
212
 
+++ kdeadmin-4.2.2/system-config-printer-kde/kcm-scpk.py        2009-04-09 22:56:08.000000000 +0100
213
 
@@ -0,0 +1,4035 @@
214
 
+#!/usr/bin/env python
215
 
+# -*- coding: utf-8 -*-
216
 
+
217
 
+#############################################################################
218
 
+##
219
 
+## Copyright 2007-2009 Canonical Ltd
220
 
+## Copyright 2008-2009 Richard Birnie <arbyuk@googlemail.com>
221
 
+## Author: Jonathan Riddell <jriddell@ubuntu.com>
222
 
+##         Richard Birnie <arbyuk@googlemail.com>
223
 
+##
224
 
+## Includes code from System Config Printer:
225
 
+## Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
226
 
+## Copyright (C) 2006, 2007 Florian Festi <ffesti@redhat.com>
227
 
+## Copyright (C) 2006, 2007, 2008 Tim Waugh <twaugh@redhat.com>
228
 
+##
229
 
+## This program is free software; you can redistribute it and/or
230
 
+## modify it under the terms of the GNU General Public License as
231
 
+## published by the Free Software Foundation; either version 2 of
232
 
+## the License, or (at your option) any later version.
233
 
+##
234
 
+## This program is distributed in the hope that it will be useful,
235
 
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
236
 
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
237
 
+## GNU General Public License for more details.
238
 
+##
239
 
+## You should have received a copy of the GNU General Public License
240
 
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
241
 
+##
242
 
+#############################################################################
243
 
+
244
 
+MIN_REFRESH_INTERVAL = 1 # seconds
245
 
+import locale
246
 
+
247
 
+import sys, os, time, traceback, re, tempfile, httplib, thread
248
 
+
249
 
+#load modules from system-config-printer-common (debug, smburi), change path here if you have it installed elsewhere
250
 
+SYSTEM_CONFIG_PRINTER_DIR = "/usr/share/system-config-printer"
251
 
+if os.path.exists(SYSTEM_CONFIG_PRINTER_DIR + "/debug.py"):
252
 
+    sys.path.append(SYSTEM_CONFIG_PRINTER_DIR)
253
 
+
254
 
+from PyQt4.QtCore import *
255
 
+from PyQt4.QtGui import *
256
 
+from PyQt4 import uic
257
 
+
258
 
+from PyKDE4.kdecore import *
259
 
+from PyKDE4.kdeui import *
260
 
+from PyKDE4.kio import *
261
 
+
262
 
+#use _() to keep code the same as gnome system-config-printer
263
 
+def _(string):
264
 
+    return unicode(i18n(string), "utf-8")
265
 
+
266
 
+def translate(self, prop):
267
 
+    """reimplement method from uic to change it to use gettext"""
268
 
+    if prop.get("notr", None) == "true":
269
 
+        return self._cstring(prop)
270
 
+    else:
271
 
+        if prop.text is None:
272
 
+            return ""
273
 
+        text = prop.text.encode("UTF-8")
274
 
+        return i18n(text)
275
 
+
276
 
+uic.properties.Properties._string = translate
277
 
+
278
 
+import cups
279
 
+cups.require ("1.9.27")
280
 
+
281
 
+# These come from system-config-printer
282
 
+import config
283
 
+import cupshelpers, options
284
 
+from optionwidgets import OptionWidget
285
 
+from smburi import SMBURI
286
 
+from debug import *
287
 
+
288
 
+import dbus
289
 
+import dbus.mainloop.qt
290
 
+import dbus.service
291
 
+import urllib
292
 
+
293
 
+ellipsis = unichr(0x2026)
294
 
+
295
 
+try:
296
 
+    try_CUPS_SERVER_REMOTE_ANY = cups.CUPS_SERVER_REMOTE_ANY
297
 
+except AttributeError:
298
 
+    # cups module was compiled with CUPS < 1.3
299
 
+    try_CUPS_SERVER_REMOTE_ANY = "_remote_any"
300
 
+
301
 
+def validDeviceURI (uri):
302
 
+    """Returns True is the provided URI is valid."""
303
 
+    if uri.find (":/") > 0:
304
 
+        return True
305
 
+    return False
306
 
+
307
 
+if os.path.exists("system-config-printer.ui"):
308
 
+    APPDIR = QDir.currentPath()
309
 
+else:
310
 
+    file = KStandardDirs.locate("data", "system-config-printer-kde/system-config-printer.ui")
311
 
+    APPDIR = file.left(file.lastIndexOf("/"))
312
 
+
313
 
+class PyKcm(KCModule):
314
 
+    def __init__(self, component_data, parent, gui):
315
 
+        KCModule.__init__(self, component_data, parent)
316
 
+
317
 
+        uic.loadUi(APPDIR + "/" + "system-config-printer.ui", self)
318
 
+        self.setButtons(KCModule.Apply)
319
 
+        self.gui = gui
320
 
+        
321
 
+    def changed(self, state):
322
 
+        """a setting has changed, activate the Apply button"""
323
 
+        self.emit(SIGNAL("changed(bool)"), state)
324
 
+
325
 
+    def save(self):
326
 
+        self.gui.on_btnPrinterPropertiesApply_clicked()
327
 
+
328
 
+    def load(self):
329
 
+        self.gui.on_btnRevert_clicked()
330
 
+
331
 
+class GUI(QWidget):
332
 
+    """our main class is the main window"""
333
 
+
334
 
+    printer_states = { cups.IPP_PRINTER_IDLE: i18nc("Printer state", "Idle"),
335
 
+                       cups.IPP_PRINTER_PROCESSING: i18nc("Printer state", "Processing"),
336
 
+                       cups.IPP_PRINTER_BUSY: i18nc("Printer state", "Busy"),
337
 
+                       cups.IPP_PRINTER_STOPPED: i18nc("Printer state", "Stopped") }
338
 
+
339
 
+
340
 
+    def makeui(self, component_data, parent):
341
 
+        self.ui = PyKcm(component_data, parent, self)
342
 
+        start_printer = None
343
 
+        change_ppd = False
344
 
+        
345
 
+        try:
346
 
+            self.language = locale.getlocale(locale.LC_MESSAGES)
347
 
+            self.encoding = locale.getlocale(locale.LC_CTYPE)
348
 
+        except:
349
 
+            nonfatalException()
350
 
+            os.environ['LC_ALL'] = 'C'
351
 
+            locale.setlocale (locale.LC_ALL, "")
352
 
+            self.language = locale.getlocale(locale.LC_MESSAGES)
353
 
+            self.encoding = locale.getlocale(locale.LC_CTYPE)
354
 
+
355
 
+        self.printer = None
356
 
+        self.conflicts = set() # of options
357
 
+        self.connect_server = (self.printer and self.printer.getServer()) \
358
 
+                               or cups.getServer()        
359
 
+        self.connect_user = cups.getUser()
360
 
+        self.password = '' #FIXME not in Gnome version
361
 
+        self.passwd_retry = False #FIXME not in Gnome version
362
 
+        self.widget_data_setting = {} #FIXME not in Gnome version
363
 
+        #FIXMEcups.setPasswordCB(self.cupsPasswdCallback)        
364
 
+        ##self.server_is_publishing = False #FIXME new in Gnome version
365
 
+
366
 
+        self.changed = set() # of options
367
 
+
368
 
+        self.servers = set((self.connect_server,))
369
 
+
370
 
+        try:
371
 
+            self.cups = cups.Connection()
372
 
+        except RuntimeError:
373
 
+            self.cups = None
374
 
+
375
 
+        # New Printer Dialog
376
 
+        self.newPrinterGUI = np = NewPrinterGUI(self)
377
 
+        
378
 
+        self.setConnected()
379
 
+
380
 
+        self.ui.connect(self.ui.mainlist, SIGNAL("itemSelectionChanged()"), self.on_tvMainList_cursor_changed)
381
 
+        self.ui.connect(self.ui.mainlist, SIGNAL("currentItemChanged (QTreeWidgetItem*, QTreeWidgetItem*)"), self.on_tvMainList_changed)
382
 
+        self.ui.connect(self.ui.chkServerBrowse, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
383
 
+        self.ui.connect(self.ui.chkServerShare, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
384
 
+        self.ui.connect(self.ui.chkServerShareAny, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
385
 
+        self.ui.connect(self.ui.chkServerRemoteAdmin, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
386
 
+        self.ui.connect(self.ui.chkServerAllowCancelAll, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
387
 
+        self.ui.connect(self.ui.chkServerLogDebug, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
388
 
+
389
 
+        self.ui.connect(self.ui.btnChangePPD, SIGNAL("clicked()"), self.on_btnChangePPD_clicked)
390
 
+        self.ui.connect(self.ui.btnNewClass, SIGNAL("clicked()"), self.on_new_class_activate)
391
 
+        self.ui.connect(self.ui.btnNewPrinterNetwork, SIGNAL("clicked()"), self.on_new_printer_activate)
392
 
+        self.ui.connect(self.ui.btnPrintTestPage, SIGNAL("clicked()"), self.on_btnPrintTestPage_clicked)
393
 
+        self.ui.connect(self.ui.btnSelfTest, SIGNAL("clicked()"), self.on_btnSelfTest_clicked)
394
 
+        self.ui.connect(self.ui.btnCleanHeads, SIGNAL("clicked()"), self.on_btnCleanHeads_clicked)
395
 
+
396
 
+        self.ui.connect(self.ui.btnNewJobOption, SIGNAL("clicked()"), self.on_btnNewJobOption_clicked)
397
 
+        self.ui.connect(self.ui.entNewJobOption, SIGNAL("textChanged(QString)"), self.on_entNewJobOption_changed)
398
 
+
399
 
+        self.ui.connect(self.ui.entPDescription, SIGNAL("textEdited(const QString&)"), self.on_printer_changed)
400
 
+        self.ui.connect(self.ui.entPLocation, SIGNAL("textEdited(const QString&)"), self.on_printer_changed)
401
 
+        self.ui.connect(self.ui.chkPMakeDefault, SIGNAL("stateChanged(int)"), self.chkPMakeDefault_stateChanged)
402
 
+        self.ui.connect(self.ui.btnDelete, SIGNAL("clicked()"), self.btnDelete_clicked)
403
 
+        self.ui.connect(self.ui.entPDevice, SIGNAL("textEdited(const QString&)"), self.on_printer_changed)
404
 
+        self.ui.connect(self.ui.chkPEnabled, SIGNAL("stateChanged(int)"),self.on_printer_changed)
405
 
+        self.ui.connect(self.ui.chkPAccepting, SIGNAL("stateChanged(int)"), self.on_printer_changed)
406
 
+        self.ui.connect(self.ui.chkPShared, SIGNAL("stateChanged(int)"), self.on_printer_changed)
407
 
+        self.ui.connect(self.ui.cmbPStartBanner, SIGNAL("currentIndexChanged(int)"), self.on_printer_changed)
408
 
+        self.ui.connect(self.ui.cmbPEndBanner, SIGNAL("currentIndexChanged(int)"), self.on_printer_changed)
409
 
+        self.ui.connect(self.ui.rbtnPAllow, SIGNAL("toggled(bool)"), self.on_printer_changed)
410
 
+        self.ui.connect(self.ui.btnPAddUser, SIGNAL("clicked()"), self.btnPAddUser_clicked)
411
 
+        self.ui.connect(self.ui.btnPDelUser, SIGNAL("clicked()"), self.btnPDelUser_clicked)
412
 
+
413
 
+        self.ui.connect(self.ui.btnClassAddMember, SIGNAL("clicked()"), self.on_btnClassAddMember_clicked)
414
 
+        self.ui.connect(self.ui.btnClassDelMember, SIGNAL("clicked()"), self.on_btnClassDelMember_clicked)
415
 
+
416
 
+        self.ui.mainlist.header().hide()
417
 
+
418
 
+        self.policiesTabWidget = self.ui.ntbkPrinter.widget(1)
419
 
+        self.memberTabWidget = self.ui.ntbkPrinter.widget(2)
420
 
+        self.optionsTabWidget = self.ui.ntbkPrinter.widget(3)
421
 
+
422
 
+        self.ui.btnClassAddMember.setIcon(KIcon("arrow-left"))
423
 
+        self.ui.btnClassDelMember.setIcon(KIcon("arrow-right"))
424
 
+        self.mainListSelectedName = None
425
 
+        self.mainListSelectedType = None
426
 
+
427
 
+        # Job Options widgets.
428
 
+        opts = [ options.OptionAlwaysShown ("copies", int, 1,
429
 
+                                            self.ui.sbJOCopies,
430
 
+                                            self.ui.btnJOResetCopies),
431
 
+                 options.OptionAlwaysShownSpecial \
432
 
+                 ("orientation-requested", int, 3,
433
 
+                  self.ui.cmbJOOrientationRequested,
434
 
+                  self.ui.btnJOResetOrientationRequested,
435
 
+                  combobox_map = [3, 4, 5, 6],
436
 
+                  special_choice=_("Automatic rotation")),
437
 
+
438
 
+                 options.OptionAlwaysShown ("fitplot", bool, False,
439
 
+                                            self.ui.cbJOFitplot,
440
 
+                                            self.ui.btnJOResetFitplot),
441
 
+
442
 
+                 options.OptionAlwaysShown ("number-up", int, 1,
443
 
+                                            self.ui.cmbJONumberUp,
444
 
+                                            self.ui.btnJOResetNumberUp,
445
 
+                                            combobox_map=[1, 2, 4, 6, 9, 16]),
446
 
+
447
 
+                 options.OptionAlwaysShown ("number-up-layout", str, "lrtb",
448
 
+                                            self.ui.cmbJONumberUpLayout,
449
 
+                                            self.ui.btnJOResetNumberUpLayout,
450
 
+                                            combobox_map = [ "lrtb",
451
 
+                                                             "lrbt",
452
 
+                                                             "rltb",
453
 
+                                                             "rlbt",
454
 
+                                                             "tblr",
455
 
+                                                             "tbrl",
456
 
+                                                             "btlr",
457
 
+                                                             "btrl" ]),
458
 
+
459
 
+                 options.OptionAlwaysShown ("brightness", int, 100,
460
 
+                                            self.ui.sbJOBrightness,
461
 
+                                            self.ui.btnJOResetBrightness),
462
 
+
463
 
+                 options.OptionAlwaysShown ("finishings", int, 3,
464
 
+                                            self.ui.cmbJOFinishings,
465
 
+                                            self.ui.btnJOResetFinishings,
466
 
+                                            combobox_map = [ 3, 4, 5, 6,
467
 
+                                                             7, 8, 9, 10,
468
 
+                                                             11, 12, 13, 14,
469
 
+                                                             20, 21, 22, 23,
470
 
+                                                             24, 25, 26, 27,
471
 
+                                                             28, 29, 30, 31,
472
 
+                                                             50, 51, 52, 53 ],
473
 
+                                            use_supported = True),
474
 
+
475
 
+                 options.OptionAlwaysShown ("job-priority", int, 50,
476
 
+                                            self.ui.sbJOJobPriority,
477
 
+                                            self.ui.btnJOResetJobPriority),
478
 
+
479
 
+                 options.OptionAlwaysShown ("media", str,
480
 
+                                            "A4", # This is the default for
481
 
+                                                  # when media-default is
482
 
+                                                  # not supplied by the IPP
483
 
+                                                  # server.  Fortunately it
484
 
+                                                  # is a mandatory attribute.
485
 
+                                            self.ui.cmbJOMedia,
486
 
+                                            self.ui.btnJOResetMedia,
487
 
+                                            use_supported = True),
488
 
+
489
 
+                 options.OptionAlwaysShown ("sides", str, "one-sided",
490
 
+                                            self.ui.cmbJOSides,
491
 
+                                            self.ui.btnJOResetSides,
492
 
+                                            combobox_map =
493
 
+                                            [ "one-sided",
494
 
+                                              "two-sided-long-edge",
495
 
+                                              "two-sided-short-edge" ]),
496
 
+
497
 
+                 options.OptionAlwaysShown ("job-hold-until", str,
498
 
+                                            "no-hold",
499
 
+                                            self.ui.cmbJOHoldUntil,
500
 
+                                            self.ui.btnJOResetHoldUntil,
501
 
+                                            use_supported = True),
502
 
+
503
 
+                 options.OptionAlwaysShown ("mirror", bool, False,
504
 
+                                            self.ui.cbJOMirror,
505
 
+                                            self.ui.btnJOResetMirror),
506
 
+
507
 
+                 options.OptionAlwaysShown ("scaling", int, 100,
508
 
+                                            self.ui.sbJOScaling,
509
 
+                                            self.ui.btnJOResetScaling),
510
 
+
511
 
+
512
 
+                 options.OptionAlwaysShown ("saturation", int, 100,
513
 
+                                            self.ui.sbJOSaturation,
514
 
+                                            self.ui.btnJOResetSaturation),
515
 
+
516
 
+                 options.OptionAlwaysShown ("hue", int, 0,
517
 
+                                            self.ui.sbJOHue,
518
 
+                                            self.ui.btnJOResetHue),
519
 
+
520
 
+                 options.OptionAlwaysShown ("gamma", int, 1000,
521
 
+                                            self.ui.sbJOGamma,
522
 
+                                            self.ui.btnJOResetGamma),
523
 
+
524
 
+                 options.OptionAlwaysShown ("cpi", float, 10.0,
525
 
+                                            self.ui.sbJOCpi, self.ui.btnJOResetCpi),
526
 
+
527
 
+                 options.OptionAlwaysShown ("lpi", float, 6.0,
528
 
+                                            self.ui.sbJOLpi, self.ui.btnJOResetLpi),
529
 
+
530
 
+                 options.OptionAlwaysShown ("page-left", int, 18,
531
 
+                                            self.ui.sbJOPageLeft,
532
 
+                                            self.ui.btnJOResetPageLeft),
533
 
+
534
 
+                 options.OptionAlwaysShown ("page-right", int, 18,
535
 
+                                            self.ui.sbJOPageRight,
536
 
+                                            self.ui.btnJOResetPageRight),
537
 
+
538
 
+                 options.OptionAlwaysShown ("page-top", int, 36,
539
 
+                                            self.ui.sbJOPageTop,
540
 
+                                            self.ui.btnJOResetPageTop),
541
 
+
542
 
+                 options.OptionAlwaysShown ("page-bottom", int, 36,
543
 
+                                            self.ui.sbJOPageBottom,
544
 
+                                            self.ui.btnJOResetPageBottom),
545
 
+
546
 
+                 options.OptionAlwaysShown ("prettyprint", bool, False,
547
 
+                                            self.ui.cbJOPrettyPrint,
548
 
+                                            self.ui.btnJOResetPrettyPrint),
549
 
+
550
 
+                 options.OptionAlwaysShown ("wrap", bool, False, self.ui.cbJOWrap,
551
 
+                                            self.ui.btnJOResetWrap),
552
 
+
553
 
+                 options.OptionAlwaysShown ("columns", int, 1,
554
 
+                                            self.ui.sbJOColumns,
555
 
+                                            self.ui.btnJOResetColumns),
556
 
+                 ]
557
 
+        self.job_options_widgets = {}
558
 
+        self.job_options_buttons = {}
559
 
+        for option in opts:
560
 
+            self.job_options_widgets[option.widget] = option
561
 
+            self.job_options_buttons[option.button] = option
562
 
+            self.connect(option.button, SIGNAL("clicked()"), self.on_job_option_reset)
563
 
+            if type(option.widget) == QSpinBox:
564
 
+                self.connect(option.widget, SIGNAL("valueChanged(int)"), self.on_job_option_changed)
565
 
+            elif type(option.widget) == QComboBox:
566
 
+                self.connect(option.widget, SIGNAL("currentIndexChanged(int)"), self.on_job_option_changed)
567
 
+            elif type(option.widget) == QCheckBox:
568
 
+                self.connect(option.widget, SIGNAL("stateChanged(int)"), self.on_job_option_changed)
569
 
+            else:
570
 
+                raise RuntimeError
571
 
+
572
 
+        try:
573
 
+            self.populateList(start_printer, change_ppd)
574
 
+        except cups.HTTPError, (s,):
575
 
+            self.cups = None
576
 
+            self.setConnected()
577
 
+            self.populateList()
578
 
+            self.show_HTTP_Error(s)
579
 
+
580
 
+        #hide some bits until implemented
581
 
+        self.ui.btnNewPrinter.hide()
582
 
+        self.ui.newPrinterLabel.hide()
583
 
+        self.ui.btnNewPrinterSpecial.hide()
584
 
+        self.ui.newPrinterSpecialLabel.hide()
585
 
+        self.ui.entPName.hide()
586
 
+        self.ui.lblPName.hide()
587
 
+
588
 
+        #catch the currentItemChanged signal. This should stop the
589
 
+        # 'Do you want to save settings' pop-up at startup
590
 
+        self.ui.mainlist.blockSignals(True)
591
 
+        self.ui.mainlist.setCurrentItem(self.settingsItem)
592
 
+        self.ui.mainlist.blockSignals(False) #unblock the signal
593
 
+        
594
 
+        #FIXME hide labels until implemented
595
 
+        self.ui.lblPOptions.hide()
596
 
+        self.ui.lblPInstallOptions.hide()
597
 
+
598
 
+        return self.ui
599
 
+
600
 
+    # now called  dests_iconview_item_activated() in the Gnome version
601
 
+    def on_tvMainList_cursor_changed(self):
602
 
+        if self.changed:
603
 
+            # The unapplied changes for this item have not been saved,
604
 
+            # and the user just pressed "Cancel".
605
 
+            #FIXME, should offer dialog prompting to save or cancel here
606
 
+            return
607
 
+        items = self.ui.mainlist.selectedItems()
608
 
+
609
 
+        if len(items) < 1:
610
 
+            return
611
 
+        item = items[0]
612
 
+
613
 
+        #FIXME only show settings until ready for the rest
614
 
+        #item = self.settingsItem
615
 
+        type = unicode(item.text(1))
616
 
+        name = unicode(item.text(0))
617
 
+
618
 
+        #name, type = self.getSelectedItem()
619
 
+        #model, self.mainListSelected = self.tvMainList.get_selection().get_selected()
620
 
+        #Save the values incase it gets deselected
621
 
+        self.mainListSelectedType = type
622
 
+        self.mainListSelectedName = name
623
 
+        item_selected = True
624
 
+        if type == "New":
625
 
+            self.ui.ntbkMain.setCurrentIndex(0)
626
 
+        elif type == "Settings":
627
 
+            self.ui.ntbkMain.setCurrentIndex(1)
628
 
+            if self.cups:
629
 
+                self.fillServerTab()
630
 
+            else:
631
 
+                # No connection to CUPS.  Make sure the Apply/Revert buttons
632
 
+                # are not sensitive.
633
 
+                self.setDataButtonState()
634
 
+            item_selected = False
635
 
+        elif type in ['Printer', 'Class']:
636
 
+            try:
637
 
+                self.fillPrinterTab(name)
638
 
+                # the below not needed, fillPrinterTab() already calls fillPrinterOptions()
639
 
+                ##self.fillPrinterOptions("foo", True) #FIXME parameters need fixing
640
 
+                self.setDataButtonState()
641
 
+                self.ui.ntbkPrinter.setCurrentIndex(0)
642
 
+            except RuntimeError:
643
 
+                # Perhaps cupsGetPPD2 failed for a browsed printer.
644
 
+                self.ui.ntbkMain.setCurrentIndex(3)
645
 
+                return
646
 
+
647
 
+            self.ui.printerNameLabel.setText(name)
648
 
+            self.ui.ntbkMain.setCurrentIndex(2)
649
 
+        elif type == "None":
650
 
+            self.ui.ntbkMain.setCurrentIndex(3)
651
 
+            self.setDataButtonState()
652
 
+            item_selected = False
653
 
+
654
 
+        """FIXME, copy button
655
 
+        is_local = item_selected and not self.printers[name].discovered
656
 
+        for widget in [self.copy, self.btnCopy]:
657
 
+            widget.set_sensitive(item_selected)
658
 
+        for widget in [self.delete, self.btnDelete]:
659
 
+            widget.set_sensitive(is_local)
660
 
+        """
661
 
+
662
 
+    def printer_properties_response(self):
663
 
+        name, type = self.getSelectedItem()
664
 
+        if type in ("Printer", "Class"):
665
 
+            return self.save_printer(self.printer)
666
 
+        elif type == "Settings":
667
 
+            return self.save_serversettings()
668
 
+
669
 
+    @pyqtSignature("")
670
 
+    def on_tvMainList_changed(self, new, old):
671
 
+        """about to change, offer to save"""
672
 
+        if self.changed:
673
 
+            answer = KMessageBox.questionYesNo(self, "Do you want to save changes?", "Save Changes", KStandardGuiItem.save(), KStandardGuiItem.discard() )
674
 
+    
675
 
+            if answer == KMessageBox.Yes: #save is equivalent to yes
676
 
+                self.printer_properties_response()
677
 
+            elif answer == KMessageBox.No: #discard is equivalent to no
678
 
+                self.changed = set() # avoid asking the user
679
 
+
680
 
+    def busy (self, win = None):
681
 
+        try:
682
 
+            if not win:
683
 
+                win = self
684
 
+            win.setCursor(Qt.WaitCursor)
685
 
+            KApplication.processEvents()
686
 
+        except:
687
 
+            nonfatalException ()
688
 
+
689
 
+    def ready (self, win = None):
690
 
+        try:
691
 
+            if not win:
692
 
+                win = self
693
 
+            win.setCursor(Qt.ArrowCursor)
694
 
+            KApplication.processEvents()
695
 
+        except:
696
 
+            nonfatalException ()
697
 
+
698
 
+    def setConnected(self):
699
 
+        connected = bool(self.cups)
700
 
+
701
 
+        host = cups.getServer()
702
 
+
703
 
+        if host[0] == '/':
704
 
+            host = 'localhost'
705
 
+        self.setWindowTitle(i18n("Printer configuration - %1", host))
706
 
+
707
 
+        if connected:
708
 
+            status_msg = i18n("Connected to %1", host)
709
 
+        else:
710
 
+            status_msg = i18n("Not connected")
711
 
+        #FIXME do we want a statusbar? 
712
 
+        #self.statusbarMain.push(self.status_context_id, status_msg)
713
 
+
714
 
+        for widget in (#FIXMEself.btnNewPrinter, self.btnNewClass,
715
 
+                       #self.new_printer, self.new_class,
716
 
+                       self.ui.chkServerBrowse, self.ui.chkServerShare,
717
 
+                       self.ui.chkServerRemoteAdmin,
718
 
+                       self.ui.chkServerAllowCancelAll,
719
 
+                       self.ui.chkServerLogDebug):
720
 
+            widget.setEnabled(connected)
721
 
+
722
 
+        sharing = self.ui.chkServerShare.isChecked ()
723
 
+        self.ui.chkServerShareAny.setEnabled (sharing)
724
 
+
725
 
+        try:
726
 
+            del self.server_settings
727
 
+        except:
728
 
+            pass
729
 
+
730
 
+    def populateList(self, start_printer = None, change_ppd = False):
731
 
+        old_name, old_type = self.getSelectedItem()
732
 
+        if self.ui.ntbkMain.currentIndex() == 1:
733
 
+            serverPageShowing = True
734
 
+        else:
735
 
+            serverPageShowing = False
736
 
+
737
 
+        select_path = None
738
 
+
739
 
+        if self.cups:
740
 
+            try:
741
 
+                # get Printers
742
 
+                self.printers = cupshelpers.getPrinters(self.cups)
743
 
+
744
 
+                # Get default printer.
745
 
+                try:
746
 
+                    self.default_printer = self.cups.getDefault ()
747
 
+                except AttributeError: # getDefault appeared in pycups-1.9.31
748
 
+                    # This fetches the list of printers and classes *again*,
749
 
+                    # just to find out the default printer.
750
 
+                    dests = self.cups.getDests ()
751
 
+                    if dests.has_key ((None,None)):
752
 
+                        self.default_printer = dests[(None,None)].name
753
 
+                    else:
754
 
+                        self.default_printer = None
755
 
+            except cups.IPPError, (e, m):
756
 
+                self.show_IPP_Error(e, m)
757
 
+                self.printers = {}
758
 
+                self.default_printer = None
759
 
+        else:
760
 
+            self.printers = {}
761
 
+            self.default_printer = None
762
 
+
763
 
+        local_printers = []
764
 
+        local_classes = []
765
 
+        remote_printers = []
766
 
+        remote_classes = []
767
 
+
768
 
+        for name, printer in self.printers.iteritems():
769
 
+            if printer.default:
770
 
+                self.default_printer = name
771
 
+            self.servers.add(printer.getServer())
772
 
+
773
 
+            if printer.remote:
774
 
+                if printer.is_class: remote_classes.append(name)
775
 
+                else: remote_printers.append(name)
776
 
+            else:
777
 
+                if printer.is_class: local_classes.append(name)
778
 
+                else: local_printers.append(name)
779
 
+
780
 
+        local_printers.sort()
781
 
+        local_classes.sort()
782
 
+        remote_printers.sort()
783
 
+        remote_classes.sort()
784
 
+
785
 
+        if (old_name != "" and
786
 
+            (not old_name in local_printers) and
787
 
+            (not old_name in local_classes) and
788
 
+            (not old_name in remote_printers) and
789
 
+            (not old_name in remote_classes)):
790
 
+            # The previously selected printer no longer exists.
791
 
+            old_name = ""
792
 
+
793
 
+        if (self.default_printer != None and
794
 
+            start_printer == None and
795
 
+            old_name == ""):
796
 
+            start_printer = self.default_printer
797
 
+
798
 
+        if not start_printer:
799
 
+            start_printer = old_name
800
 
+
801
 
+        expanded = {
802
 
+            "_printers" : True,
803
 
+            "_classes" : True,
804
 
+            "_remote_printers" : True,
805
 
+            "_remote_classes" : True,
806
 
+            }
807
 
+
808
 
+        """
809
 
+        # remove old printers/classes
810
 
+        iter = self.mainlist.get_iter_first()
811
 
+        iter = self.mainlist.iter_next(iter) # step over server settings
812
 
+        while iter:
813
 
+            entry = self.mainlist.get_value(iter, 1)
814
 
+            path = self.mainlist.get_path(iter)
815
 
+            expanded[entry] = self.tvMainList.row_expanded(path)
816
 
+            more_entries =  self.mainlist.remove(iter)
817
 
+            if not more_entries: break
818
 
+        """
819
 
+        self.ui.mainlist.clear()
820
 
+        QTreeWidgetItem(self.ui.mainlist, ["New Printer", 'New'])
821
 
+        self.settingsItem = QTreeWidgetItem(self.ui.mainlist, ["Server Settings", 'Settings'])
822
 
+        if serverPageShowing:
823
 
+            self.settingsItem.setSelected(True)
824
 
+
825
 
+        # add new
826
 
+        for printers, text, name in (
827
 
+            (local_printers, i18n("Local Printers"), "_printers"),
828
 
+            (local_classes, i18n("Local Classes"), "_classes"),
829
 
+            (remote_printers, i18n("Remote Printers"), "_remote_printers"),
830
 
+            (remote_classes, i18n("Remote Classes"), "_remote_classes")):
831
 
+            if not printers: continue
832
 
+
833
 
+            #self.mainlist.addTopLevelItem(QTreeWidgetItem(self.mainlist, text))
834
 
+            rootTreeItem = QTreeWidgetItem(self.ui.mainlist, [text, name])
835
 
+            #iter = self.mainlist.append(None, (text, name))
836
 
+            #path = self.mainlist.get_path(iter)
837
 
+
838
 
+            for printer_name in printers:
839
 
+                if start_printer == None:
840
 
+                    start_printer = printer_name
841
 
+                treeItem = QTreeWidgetItem(rootTreeItem, [printer_name, "Printer"])
842
 
+                #p_iter = self.mainlist.append(iter, (printer_name, "Printer"))
843
 
+                if printer_name==start_printer and not serverPageShowing:
844
 
+                    treeItem.setSelected(True)
845
 
+                    expanded[name] = True
846
 
+            if expanded[name]:
847
 
+                rootTreeItem.setExpanded(True)
848
 
+                #self.tvMainList.expand_row(path, False)
849
 
+        self.on_tvMainList_cursor_changed()
850
 
+        self.setDataButtonState()
851
 
+
852
 
+        """FIXME
853
 
+        if change_ppd:
854
 
+            self.on_btnChangePPD_clicked (self.btnChangePPD)
855
 
+        """
856
 
+
857
 
+    #TODO
858
 
+    # Connect to Server
859
 
+
860
 
+    def on_printer_changed(self, text):
861
 
+        widget = self.sender()
862
 
+        if not widget:  #method called as a method not a slot
863
 
+            return
864
 
+        if isinstance(widget, QCheckBox):
865
 
+            value = widget.isChecked()
866
 
+        elif isinstance(widget, QLineEdit): #this should be a KLineEdit but causes errors
867
 
+            value = unicode(widget.text())
868
 
+        elif isinstance(widget, QRadioButton):
869
 
+            value = widget.isChecked()
870
 
+        elif isinstance(widget, QComboBox): #KCombobox causes errors
871
 
+            value = unicode(widget.currentText())
872
 
+        else:
873
 
+            raise ValueError, "Widget type not supported (yet)"
874
 
+
875
 
+        p = self.printer
876
 
+        old_values = {
877
 
+            self.ui.entPDescription : p.info,
878
 
+            self.ui.entPLocation : p.location,
879
 
+            self.ui.entPDevice : p.device_uri,
880
 
+            self.ui.chkPEnabled : p.enabled,
881
 
+            self.ui.chkPAccepting : not p.rejecting,
882
 
+            self.ui.chkPShared : p.is_shared,
883
 
+            self.ui.cmbPStartBanner : p.job_sheet_start,
884
 
+            self.ui.cmbPEndBanner : p.job_sheet_end,
885
 
+            self.ui.rbtnPAllow: p.default_allow
886
 
+            #FIXME Not implemented in the current UI
887
 
+            #self.cmbPErrorPolicy : p.error_policy,
888
 
+            #self.cmbPOperationPolicy : p.op_policy,
889
 
+            }
890
 
+
891
 
+        old_value = old_values[widget]
892
 
+
893
 
+        if old_value == value:
894
 
+            self.changed.discard(widget)
895
 
+        else:
896
 
+            self.changed.add(widget)
897
 
+        self.setDataButtonState()
898
 
+
899
 
+    #TODO
900
 
+    # Access control
901
 
+
902
 
+    #TODO
903
 
+    # Server side options
904
 
+
905
 
+    # set buttons sensitivity
906
 
+    def setDataButtonState(self):
907
 
+        try: # Might not be a printer selected
908
 
+            possible = (self.ppd and
909
 
+                        not bool (self.changed) and
910
 
+                        self.printer.enabled and
911
 
+                        not self.printer.rejecting)
912
 
+
913
 
+            self.btnPrintTestPage.setEnabled(possible)
914
 
+
915
 
+            commands = (self.printer.type & cups.CUPS_PRINTER_COMMANDS) != 0
916
 
+            self.btnSelfTest.setEnabled(commands and possible)
917
 
+            self.btnCleanHeads.setEnabled(commands and possible)
918
 
+        except:
919
 
+            debugprint ("exception in setDataButtonState")
920
 
+            pass
921
 
+
922
 
+        installablebold = False
923
 
+        optionsbold = False
924
 
+        """ FIXME, no conflicts button in system settings
925
 
+        if self.conflicts:
926
 
+            debugprint ("Conflicts detected")
927
 
+            self.btnConflict.show()
928
 
+            for option in self.conflicts:
929
 
+                if option.tab_label == self.lblPInstallOptions:
930
 
+                    installablebold = True
931
 
+                else:
932
 
+                    optionsbold = True
933
 
+        else:
934
 
+            self.ui.btnConflict.hide()
935
 
+        """
936
 
+        installabletext = i18n("Installable Options")
937
 
+        optionstext = i18n("Printer Options")
938
 
+        if installablebold:
939
 
+            installabletext = i18nc("Conflicted entry", "<b>%1</b>", installabletext)
940
 
+        if optionsbold:
941
 
+            optionstext = i18nc("Conflicted entry", "<b>%1</b>", optionstext)
942
 
+        self.ui.lblPInstallOptions.setText(installabletext)
943
 
+        self.ui.lblPOptions.setText(optionstext)
944
 
+
945
 
+        """  FIXME
946
 
+        store = self.tvPrinterProperties.get_model ()
947
 
+        if store:
948
 
+            for n in range (self.ntbkPrinter.get_n_pages ()):
949
 
+                page = self.ntbkPrinter.get_nth_page (n)
950
 
+                label = self.ntbkPrinter.get_tab_label (page)
951
 
+                if label == self.lblPInstallOptions:
952
 
+                    iter = store.get_iter ((n,))
953
 
+                    store.set_value (iter, 0, installabletext)
954
 
+                elif label == self.lblPOptions:
955
 
+                    iter = store.get_iter ((n,))
956
 
+                    store.set_value (iter, 0, optionstext)
957
 
+        """
958
 
+
959
 
+        self.ui.changed(len (self.changed) > 0)
960
 
+        #self.ui.btnPrinterPropertiesApply.setEnabled(len (self.changed) > 0)
961
 
+        #self.ui.btnRevert.setEnabled(len (self.changed) > 0)
962
 
+
963
 
+    def save_printer(self, printer, saveall=False):
964
 
+        class_deleted = False
965
 
+        name = printer.name
966
 
+
967
 
+        try:
968
 
+            if not printer.is_class and self.ppd: 
969
 
+                self.getPrinterSettings()
970
 
+                if self.ppd.nondefaultsMarked() or saveall:
971
 
+                    self.passwd_retry = False # use cached Passwd 
972
 
+                    self.cups.addPrinter(name, ppd=self.ppd)
973
 
+
974
 
+            if printer.is_class:
975
 
+                # update member list
976
 
+                new_members = self.getCurrentClassMembers(self.ui.tvClassMembers)
977
 
+                if not new_members:
978
 
+                    result = KMessageBox.warningContinueCancel(self.ui, i18n("Class now has no members. Proceed anyway?"), i18n("Class Empty"))
979
 
+                    if result == KMessageBox.Continue:
980
 
+                        return True
981
 
+                    class_deleted = True
982
 
+
983
 
+                # update member list
984
 
+                old_members = printer.class_members[:]
985
 
+
986
 
+                for member in new_members:
987
 
+                    member = unicode(member)
988
 
+                    if member in old_members:
989
 
+                        old_members.remove(member)
990
 
+                    else:
991
 
+                        self.cups.addPrinterToClass(member, name)
992
 
+                for member in old_members:
993
 
+                    self.cups.deletePrinterFromClass(member, name)    
994
 
+
995
 
+            location = unicode(self.ui.entPLocation.text())
996
 
+            info = unicode(self.ui.entPDescription.text())
997
 
+            device_uri = unicode(self.ui.entPDevice.text())
998
 
+            if device_uri.find (ellipsis) != -1:
999
 
+                # The URI is sanitized and not editable.
1000
 
+                device_uri = printer.device_uri
1001
 
+
1002
 
+            enabled = self.ui.chkPEnabled.isChecked()
1003
 
+            accepting = self.ui.chkPAccepting.isChecked()
1004
 
+            shared = self.ui.chkPShared.isChecked()
1005
 
+
1006
 
+            if info!=printer.info or saveall:
1007
 
+                self.passwd_retry = False # use cached Passwd 
1008
 
+                self.cups.setPrinterInfo(name, info)
1009
 
+            if location!=printer.location or saveall:
1010
 
+                self.passwd_retry = False # use cached Passwd 
1011
 
+                self.cups.setPrinterLocation(name, location)
1012
 
+            if (not printer.is_class and
1013
 
+                (device_uri!=printer.device_uri or saveall)):
1014
 
+                self.passwd_retry = False # use cached Passwd 
1015
 
+                self.cups.setPrinterDevice(name, device_uri)
1016
 
+
1017
 
+            if enabled != printer.enabled or saveall:
1018
 
+                self.passwd_retry = False # use cached Passwd 
1019
 
+                self.printer.setEnabled(enabled)
1020
 
+            if accepting == printer.rejecting or saveall:
1021
 
+                self.passwd_retry = False # use cached Passwd 
1022
 
+                self.printer.setAccepting(accepting)
1023
 
+            if shared != printer.is_shared or saveall:
1024
 
+                self.passwd_retry = False # use cached Passwd 
1025
 
+                self.printer.setShared(shared)
1026
 
+
1027
 
+            job_sheet_start = unicode(self.ui.cmbPStartBanner.currentText())
1028
 
+            job_sheet_end = unicode(self.ui.cmbPEndBanner.currentText())
1029
 
+            #FIXME Not implemented in current UI
1030
 
+            #error_policy = unicode(self.cmbPErrorPolicy.currentText())
1031
 
+            #op_policy = unicode(self.cmbPOperationPolicy.currentText())
1032
 
+
1033
 
+            if (job_sheet_start != printer.job_sheet_start or
1034
 
+                job_sheet_end != printer.job_sheet_end) or saveall:
1035
 
+                self.passwd_retry = False # use cached Passwd
1036
 
+                printer.setJobSheets(job_sheet_start, job_sheet_end)
1037
 
+            #FIXME Not implemented in current UI
1038
 
+            #if error_policy != printer.error_policy or saveall:
1039
 
+                #self.passwd_retry = False # use cached Passwd
1040
 
+                #printer.setErrorPolicy(error_policy)
1041
 
+            #if op_policy != printer.op_policy or saveall:
1042
 
+                #self.passwd_retry = False # use cached Passwd
1043
 
+                #printer.setOperationPolicy(op_policy)
1044
 
+
1045
 
+            #Access Control
1046
 
+            default_allow = self.ui.rbtnPAllow.isChecked()
1047
 
+            except_users = self.getPUsers()
1048
 
+
1049
 
+            if (default_allow != printer.default_allow or
1050
 
+                except_users != printer.except_users) or saveall:
1051
 
+                self.passwd_retry = False # use cached Passwd
1052
 
+                printer.setAccess(default_allow, except_users)
1053
 
+
1054
 
+            for option in printer.attributes:
1055
 
+                if option not in self.server_side_options:
1056
 
+                    printer.unsetOption(option)
1057
 
+            for option in self.server_side_options.itervalues():
1058
 
+                if (option.is_changed() or
1059
 
+                    saveall and
1060
 
+                    option.get_current_value () != option.system_default):
1061
 
+                    printer.setOption(unicode(option.name), unicode(option.get_current_value()) )
1062
 
+
1063
 
+        except cups.IPPError, (e, s):
1064
 
+            self.show_IPP_Error(e, s)
1065
 
+            return True
1066
 
+        self.changed = set() # of options
1067
 
+        
1068
 
+        if not self.__dict__.has_key ("server_settings"):
1069
 
+            # We can authenticate with the server correctly at this point,
1070
 
+            # but we have never fetched the server settings to see whether
1071
 
+            # the server is publishing shared printers.  Fetch the settings
1072
 
+            # now so that we can update the "not published" label if necessary.
1073
 
+            try:
1074
 
+                self.server_settings = self.cups.adminGetServerSettings()
1075
 
+            except:
1076
 
+                nonfatalException()
1077
 
+
1078
 
+        if class_deleted:
1079
 
+            self.populateList ()
1080
 
+        else:
1081
 
+            # Update our copy of the printer's settings.
1082
 
+            try:
1083
 
+                printers = cupshelpers.getPrinters (self.cups)
1084
 
+                this_printer = { name: printers[name] }
1085
 
+                self.printers.update (this_printer)
1086
 
+            except cups.IPPError, (e, s):
1087
 
+                show_IPP_Error(e, s, self.PrinterPropertiesDialog)
1088
 
+
1089
 
+        return False
1090
 
+
1091
 
+    def getPrinterSettings(self):
1092
 
+        #self.ppd.markDefaults()
1093
 
+        for option in self.options.itervalues():
1094
 
+            option.writeback()
1095
 
+
1096
 
+    @pyqtSignature("")
1097
 
+    def on_btnPrintTestPage_clicked(self):
1098
 
+        self.setTestButton(self.printer)
1099
 
+        if self.test_button_cancels:
1100
 
+            jobs = self.printer.testsQueued ()
1101
 
+            for job in jobs:
1102
 
+                debugprint ("Canceling job %s" % job)
1103
 
+                try:
1104
 
+                    self.cups.cancelJob (job)
1105
 
+                except cups.IPPError, (e, msg):
1106
 
+                    self.show_IPP_Error(e, msg)
1107
 
+            self.setTestButton (self.printer)
1108
 
+            return
1109
 
+        try:
1110
 
+            # if we have a page size specific custom test page, use it;
1111
 
+            # otherwise use cups' default one
1112
 
+            custom_testpage = None
1113
 
+            opt = self.ppd.findOption ("PageSize")
1114
 
+            if opt:
1115
 
+                print opt
1116
 
+                custom_testpage = os.path.join(SYSTEM_CONFIG_PRINTER_DIR, 'testpage-%s.ps' % opt.defchoice.lower())
1117
 
+                print custom_testpage
1118
 
+
1119
 
+            if custom_testpage and os.path.exists(custom_testpage):
1120
 
+                debugprint ('Printing custom test page ' + custom_testpage)
1121
 
+                job_id = self.cups.printTestPage(self.printer.name,
1122
 
+                    file=custom_testpage)
1123
 
+                print job_id
1124
 
+            else:
1125
 
+                debugprint ('Printing default test page')
1126
 
+                job_id = self.cups.printTestPage(self.printer.name)
1127
 
+
1128
 
+            self.setTestButton (self.printer)
1129
 
+            KMessageBox.information(self, i18n("Test page submitted as job %1", job_id), i18nc("Test page submitted", "Submitted"))
1130
 
+        except cups.IPPError, (e, msg):
1131
 
+            if (e == cups.IPP_NOT_AUTHORIZED and
1132
 
+                self.connect_server != 'localhost' and
1133
 
+                self.connect_server[0] != '/'):
1134
 
+                self.lblError.set_markup ('<span size="larger">'+
1135
 
+                                          i18n("<b>Not possible</b>") + '</span>\n\n' +
1136
 
+                                          i18n("The remote server did not accept "
1137
 
+                                            "the print job, most likely "
1138
 
+                                            "because the printer is not "
1139
 
+                                            "shared."))
1140
 
+                self.ErrorDialog.set_transient_for (self.MainWindow)
1141
 
+                self.ErrorDialog.run ()
1142
 
+                self.ErrorDialog.hide ()
1143
 
+            else:
1144
 
+                self.show_IPP_Error(e, msg)
1145
 
+
1146
 
+    def maintenance_command (self, command):
1147
 
+        (tmpfd, tmpfname) = tempfile.mkstemp ()
1148
 
+        os.write (tmpfd, "#CUPS-COMMAND\n%s\n" % command)
1149
 
+        os.close (tmpfd)
1150
 
+        try:
1151
 
+            format = "application/vnd.cups-command"
1152
 
+            job_id = self.cups.printTestPage (self.printer.name,
1153
 
+                                              format=format,
1154
 
+                                              file=tmpfname,
1155
 
+                                              user=self.connect_user)
1156
 
+            self.lblInfo.set_markup ('<span size="larger">' +
1157
 
+                                     i18nc("Maintenance command submitted", "<b>Submitted</b>") + '</span>\n\n' +
1158
 
+                                     i18n("Maintenance command submitted as "
1159
 
+                                       "job %d", job_id))
1160
 
+            self.InfoDialog.set_transient_for (self.MainWindow)
1161
 
+            self.InfoDialog.run ()
1162
 
+            self.InfoDialog.hide ()
1163
 
+        except cups.IPPError, (e, msg):
1164
 
+            if (e == cups.IPP_NOT_AUTHORIZED and
1165
 
+                self.printer.name != 'localhost'):
1166
 
+                self.lblError.set_markup ('<span size="larger">'+
1167
 
+                                          i18n("<b>Not possible</b>") + '</span>\n\n' +
1168
 
+                                          i18n("The remote server did not accept "
1169
 
+                                            "the print job, most likely "
1170
 
+                                            "because the printer is not "
1171
 
+                                            "shared."))
1172
 
+                self.ErrorDialog.set_transient_for (self.MainWindow)
1173
 
+                self.ErrorDialog.run ()
1174
 
+                self.ErrorDialog.hide ()
1175
 
+            else:
1176
 
+                self.show_IPP_Error(e, msg)
1177
 
+
1178
 
+    @pyqtSignature("")
1179
 
+    def on_btnSelfTest_clicked(self):
1180
 
+        self.maintenance_command ("PrintSelfTestPage")
1181
 
+
1182
 
+    @pyqtSignature("")
1183
 
+    def on_btnCleanHeads_clicked(self):
1184
 
+        self.maintenance_command ("Clean all")
1185
 
+
1186
 
+    def fillComboBox(self, combobox, values, value):
1187
 
+        combobox.clear()
1188
 
+        for nr, val in enumerate(values):
1189
 
+            combobox.addItem(val)
1190
 
+            if val == value: 
1191
 
+                combobox.setCurrentIndex(nr)
1192
 
+
1193
 
+    def fillPrinterTab(self, name):
1194
 
+        self.changed = set() # of options
1195
 
+        self.options = {} # keyword -> Option object
1196
 
+        self.conflicts = set() # of options
1197
 
+
1198
 
+        printer = self.printers[name] 
1199
 
+        self.printer = printer
1200
 
+        printer.getAttributes ()
1201
 
+
1202
 
+        editable = not self.printer.discovered
1203
 
+        editablePPD = not self.printer.remote
1204
 
+
1205
 
+        try:
1206
 
+            self.ppd = printer.getPPD()
1207
 
+        except cups.IPPError, (e, m):
1208
 
+            # Some IPP error other than IPP_NOT_FOUND.
1209
 
+            self.show_IPP_Error(e, m)
1210
 
+            # Treat it as a raw queue.
1211
 
+            self.ppd = False
1212
 
+        except RuntimeError:
1213
 
+            # The underlying cupsGetPPD2() function returned NULL without
1214
 
+            # setting an IPP error, so it'll be something like a failed
1215
 
+            # connection.
1216
 
+            #FIXME show a dialogue
1217
 
+            debugprint("Error!")
1218
 
+            """
1219
 
+            self.lblError.set_markup('<span size="larger">' +
1220
 
+                                     _("<b>Error</b>") + '</span>\n\n' +
1221
 
+                                     _("There was a problem connecting to "
1222
 
+                                       "the CUPS server."))
1223
 
+            self.ErrorDialog.set_transient_for(self.MainWindow)
1224
 
+            self.ErrorDialog.run()
1225
 
+            self.ErrorDialog.hide()
1226
 
+            """
1227
 
+            raise
1228
 
+
1229
 
+        for widget in (self.ui.entPDescription, self.ui.entPLocation,
1230
 
+                        self.ui.entPName, self.ui.entPDevice):
1231
 
+                            widget.setReadOnly(not editable)
1232
 
+
1233
 
+        for widget in (self.ui.btnChangePPD,
1234
 
+                       self.ui.chkPEnabled, self.ui.chkPAccepting, self.ui.chkPShared,
1235
 
+                       self.ui.cmbPStartBanner, self.ui.cmbPEndBanner,  self.ui.btnPAddUser,
1236
 
+                       self.ui.btnPDelUser, self.ui.rbtnPAllow, self.ui.rbtnPDeny):
1237
 
+                    #""",FIXME
1238
 
+                       #self.btnSelectDevice, self.cmbPErrorPolicy,
1239
 
+                       #self.cmbPOperationPolicy,):
1240
 
+                    #"""
1241
 
+                widget.setEnabled(editable)
1242
 
+
1243
 
+        # Description page
1244
 
+        self.ui.entPName.setText(printer.name)
1245
 
+        self.ui.entPDescription.setText(printer.info)
1246
 
+        self.ui.entPLocation.setText(printer.location)
1247
 
+
1248
 
+        uri = printer.device_uri
1249
 
+        if uri.startswith("smb://"):
1250
 
+            (group, host, share,
1251
 
+             user, password) = SMBURI (uri=uri[6:]).separate ()
1252
 
+            if password:
1253
 
+                uri = "smb://"
1254
 
+                if len (user) or len (password):
1255
 
+                    uri += ellipsis
1256
 
+                uri += SMBURI (group=group, host=host, share=share).get_uri ()
1257
 
+                self.ui.entPDevice.setEnabled(False)
1258
 
+            else:
1259
 
+                self.ui.entPDevice.setEnabled(True)
1260
 
+
1261
 
+        self.ui.entPDevice.setText(uri)
1262
 
+        self.changed.discard(self.ui.entPDevice)
1263
 
+
1264
 
+        # Hide make/model and Device URI for classes
1265
 
+        for widget in (self.ui.lblPMakeModel2, self.ui.lblPMakeModel,
1266
 
+                        self.ui.lblPDevice2, self.ui.entPDevice,
1267
 
+                        self.ui.btnChangePPD):
1268
 
+                       #, self.btnSelectDevice):
1269
 
+            if printer.is_class:
1270
 
+                widget.hide()
1271
 
+            else:
1272
 
+                widget.show()
1273
 
+
1274
 
+        ## default printer
1275
 
+        default = self.cups.getDefault()
1276
 
+        
1277
 
+        if printer.name == default:
1278
 
+            #catch the stateChanged signal to prevent a signal loop
1279
 
+            self.ui.chkPMakeDefault.blockSignals(True) 
1280
 
+            self.ui.chkPMakeDefault.setChecked(True) #set checked
1281
 
+            #unblock the signal
1282
 
+            self.ui.chkPMakeDefault.blockSignals(False)
1283
 
+            self.ui.chkPMakeDefault.setText(i18n("This is the default printer"))
1284
 
+        else:
1285
 
+            #catch the stateChanged signal to prevent a signal loop
1286
 
+            self.ui.chkPMakeDefault.blockSignals(True)
1287
 
+            self.ui.chkPMakeDefault.setChecked(False) #set unchecked
1288
 
+            #unblock the signal
1289
 
+            self.ui.chkPMakeDefault.blockSignals(False)
1290
 
+            if default is not None:
1291
 
+                self.ui.chkPMakeDefault.setText(i18n('Make Default. (The current default is %1)', default))
1292
 
+            else:
1293
 
+                self.ui.chkPMakeDefault.setText(i18n('Make Default. (There is no current default)'))
1294
 
+
1295
 
+        #self.setTestButton (printer)
1296
 
+
1297
 
+        # Policy tab
1298
 
+        # ----------
1299
 
+
1300
 
+        ## State
1301
 
+        self.ui.chkPEnabled.setChecked(printer.enabled)
1302
 
+        self.ui.chkPAccepting.setChecked(not printer.rejecting)
1303
 
+        self.ui.chkPShared.setChecked(printer.is_shared)
1304
 
+        try:
1305
 
+            if printer.is_shared:
1306
 
+                flag = cups.CUPS_SERVER_SHARE_PRINTERS
1307
 
+                publishing = int (self.server_settings[flag])
1308
 
+                if publishing:
1309
 
+                    self.ui.lblNotPublished.hide()
1310
 
+                else:
1311
 
+                    self.ui.lblNotPublished.show()
1312
 
+            else:
1313
 
+                self.ui.lblNotPublished.hide()
1314
 
+        except:
1315
 
+            self.ui.lblNotPublished.hide()
1316
 
+
1317
 
+        # Job sheets
1318
 
+        self.ui.cmbPStartBanner.setEnabled(editable)
1319
 
+        self.ui.cmbPEndBanner.setEnabled(editable)
1320
 
+
1321
 
+#FIXME Not implemented in the current UI
1322
 
+        # Policies
1323
 
+        #self.cmbPErrorPolicy.setEnabled(editable)
1324
 
+        #self.cmbPOperationPolicy.setEnabled(editable)
1325
 
+
1326
 
+        
1327
 
+        # Access control
1328
 
+        self.ui.rbtnPAllow.setChecked(printer.default_allow)
1329
 
+        self.ui.rbtnPDeny.setChecked(not printer.default_allow)
1330
 
+        self.setPUsers(printer.except_users)
1331
 
+
1332
 
+        #self.entPUser.set_text("")
1333
 
+        # Server side options (Job options)
1334
 
+        self.server_side_options = {}
1335
 
+        for option in self.job_options_widgets.values ():
1336
 
+            if option.name == "media" and self.ppd:
1337
 
+                # Slightly special case because the 'system default'
1338
 
+                # (i.e. what you get when you press Reset) depends
1339
 
+                # on the printer's PageSize.
1340
 
+                opt = self.ppd.findOption ("PageSize")
1341
 
+                if opt:
1342
 
+                    option.set_default (opt.defchoice)
1343
 
+
1344
 
+            option_editable = editable
1345
 
+            try:
1346
 
+                value = self.printer.attributes[option.name]
1347
 
+            except KeyError:
1348
 
+                option.reinit (None)
1349
 
+            else:
1350
 
+                try:
1351
 
+                    if self.printer.possible_attributes.has_key (option.name):
1352
 
+                        supported = self.printer.\
1353
 
+                                    possible_attributes[option.name][1]
1354
 
+                        # Set the option widget.
1355
 
+                        # In CUPS 1.3.x the orientation-requested-default
1356
 
+                        # attribute may have the value None; this means there
1357
 
+                        # is no value set.  This suits our needs here, as None
1358
 
+                        # resets the option to the system default and makes the
1359
 
+                        # Reset button insensitive.
1360
 
+                        option.reinit (value, supported=supported)
1361
 
+                    else:
1362
 
+                        option.reinit (value)
1363
 
+
1364
 
+                    self.server_side_options[option.name] = option
1365
 
+                except ValueError, inst:
1366
 
+                    option_editable = False
1367
 
+                    text = ('<span ' +
1368
 
+                                              'size="larger">' +
1369
 
+                                              _("<b>Error</b>") + '</span>\n\n' +
1370
 
+                                              _("Option '%s' has value '%s' "
1371
 
+                                                "and cannot be edited.") %
1372
 
+                                              (option.name, value))
1373
 
+                    QMessageBox.critical(self.ui, i18n("Error"), text)
1374
 
+            option.widget.setEnabled(option_editable)
1375
 
+            if not editable:
1376
 
+                option.button.setEnabled(False)
1377
 
+        self.other_job_options = []
1378
 
+        self.draw_other_job_options (editable=editable)
1379
 
+        for option in self.printer.attributes.keys ():
1380
 
+            if self.server_side_options.has_key (option):
1381
 
+                continue
1382
 
+            supported = ""
1383
 
+            if self.printer.possible_attributes.has_key (option):
1384
 
+                supported = self.printer.possible_attributes[option][1]
1385
 
+            self.add_job_option (option, value=self.printer.attributes[option],
1386
 
+                                 supported=supported, is_new=False,
1387
 
+                                 editable=editable)
1388
 
+        self.ui.entNewJobOption.setText ('')
1389
 
+        self.ui.entNewJobOption.setEnabled(editable)
1390
 
+        self.ui.btnNewJobOption.setEnabled(False)
1391
 
+
1392
 
+        if printer.is_class:
1393
 
+            # remove InstallOptions tab
1394
 
+            ##tab_nr = self.ui.ntbkPrinter.page_num(self.swPInstallOptions)
1395
 
+            ##if tab_nr != -1:
1396
 
+            ##    self.ui.ntbkPrinter.remove_page(tab_nr)
1397
 
+            self.fillClassMembers(name, editable)
1398
 
+            pass
1399
 
+        else:
1400
 
+            # real Printer
1401
 
+            self.fillPrinterOptions(name, editablePPD)
1402
 
+
1403
 
+        #self.changed = set() # of options
1404
 
+        self.updatePrinterProperties ()
1405
 
+        self.setDataButtonState()
1406
 
+
1407
 
+
1408
 
+    def fillPrinterOptions(self, name, editable):
1409
 
+        # remove Member tab
1410
 
+        tab_nr = self.ui.ntbkPrinter.indexOf(self.memberTabWidget)
1411
 
+        if tab_nr != -1:
1412
 
+            self.ui.ntbkPrinter.removeTab(tab_nr)
1413
 
+        policiesTabNo = self.ui.ntbkPrinter.indexOf(self.policiesTabWidget)
1414
 
+        self.ui.ntbkPrinter.insertTab(policiesTabNo+1, self.optionsTabWidget, i18n("Options"))
1415
 
+
1416
 
+        """
1417
 
+        # clean Installable Options Tab
1418
 
+        for widget in self.vbPInstallOptions.get_children():
1419
 
+            self.vbPInstallOptions.remove(widget)
1420
 
+
1421
 
+        """
1422
 
+        # clean Options Tab
1423
 
+        for widget in self.ui.optionsPageWidget.children():
1424
 
+            if isinstance(widget, QWidget):
1425
 
+                self.ui.vbPOptions.removeWidget(widget)
1426
 
+                widget.hide()
1427
 
+            del widget
1428
 
+        """
1429
 
+
1430
 
+        # insert Options Tab
1431
 
+        if self.ntbkPrinter.page_num(self.swPOptions) == -1:
1432
 
+            self.ntbkPrinter.insert_page(
1433
 
+                self.swPOptions, self.lblPOptions, self.static_tabs)
1434
 
+
1435
 
+        if not self.ppd:
1436
 
+            tab_nr = self.ntbkPrinter.page_num(self.swPInstallOptions)
1437
 
+            if tab_nr != -1:
1438
 
+                self.ntbkPrinter.remove_page(tab_nr)
1439
 
+            tab_nr = self.ntbkPrinter.page_num(self.swPOptions)
1440
 
+            if tab_nr != -1:
1441
 
+                self.ntbkPrinter.remove_page(tab_nr)           
1442
 
+            return
1443
 
+        """
1444
 
+        ppd = self.ppd
1445
 
+        ppd.markDefaults()
1446
 
+
1447
 
+        hasInstallableOptions = False
1448
 
+        
1449
 
+        # build option tabs
1450
 
+        for group in ppd.optionGroups:
1451
 
+            if group.name == "InstallableOptions":
1452
 
+                """
1453
 
+                hasInstallableOptions = True
1454
 
+                container = self.vbPInstallOptions
1455
 
+                tab_nr = self.ntbkPrinter.page_num(self.swPInstallOptions)
1456
 
+                if tab_nr == -1:
1457
 
+                    self.ntbkPrinter.insert_page(
1458
 
+                        self.swPInstallOptions, gtk.Label(group.text),
1459
 
+                        self.static_tabs)
1460
 
+                """
1461
 
+                tab_label = self.ui.lblPInstallOptions
1462
 
+            else:
1463
 
+                """
1464
 
+                frame = gtk.Frame("<b>%s</b>" % group.text)
1465
 
+                frame.get_label_widget().set_use_markup(True)
1466
 
+                frame.set_shadow_type (gtk.SHADOW_NONE)
1467
 
+                self.vbPOptions.pack_start (frame, False, False, 0)
1468
 
+                container = gtk.Alignment (0.5, 0.5, 1.0, 1.0)
1469
 
+                # We want a left padding of 12, but there is a Table with
1470
 
+                # spacing 6, and the left-most column of it (the conflict
1471
 
+                # icon) is normally hidden, so just use 6 here.
1472
 
+                container.set_padding (6, 12, 6, 0)
1473
 
+                frame.add (container)
1474
 
+                """
1475
 
+                tab_label = self.ui.lblPOptions
1476
 
+            container = QGroupBox(self)
1477
 
+            self.ui.vbPOptions.addWidget(container)
1478
 
+            container.setTitle(group.text)
1479
 
+            """
1480
 
+            
1481
 
+            table = gtk.Table(1, 3, False)
1482
 
+            table.set_col_spacings(6)
1483
 
+            table.set_row_spacings(6)
1484
 
+            container.add(table)
1485
 
+            """
1486
 
+            table = QGridLayout(container)
1487
 
+            container.setLayout(table)
1488
 
+
1489
 
+            rows = 0
1490
 
+
1491
 
+            # InputSlot and ManualFeed need special handling.  With
1492
 
+            # libcups, if ManualFeed is True, InputSlot gets unset.
1493
 
+            # Likewise, if InputSlot is set, ManualFeed becomes False.
1494
 
+            # We handle it by toggling the sensitivity of InputSlot
1495
 
+            # based on ManualFeed.
1496
 
+            self.option_inputslot = self.option_manualfeed = None
1497
 
+
1498
 
+            for nr, option in enumerate(group.options):
1499
 
+                if option.keyword == "PageRegion":
1500
 
+                    continue
1501
 
+                rows += 1
1502
 
+                """
1503
 
+                table.resize (rows, 3)
1504
 
+                """
1505
 
+                o = OptionWidget(option, ppd, self, tab_label=tab_label)
1506
 
+                """
1507
 
+                table.attach(o.conflictIcon, 0, 1, nr, nr+1, 0, 0, 0, 0)
1508
 
+
1509
 
+                hbox = gtk.HBox()
1510
 
+                """
1511
 
+                if o.label:
1512
 
+                    table.addWidget(o.label, rows-1, 0)
1513
 
+                """
1514
 
+                    a = gtk.Alignment (0.5, 0.5, 1.0, 1.0)
1515
 
+                    a.set_padding (0, 0, 0, 6)
1516
 
+                    a.add (o.label)
1517
 
+                    table.attach(a, 1, 2, nr, nr+1, gtk.FILL, 0, 0, 0)
1518
 
+                    table.attach(hbox, 2, 3, nr, nr+1, gtk.FILL, 0, 0, 0)
1519
 
+                else:
1520
 
+                    table.attach(hbox, 1, 3, nr, nr+1, gtk.FILL, 0, 0, 0)
1521
 
+                hbox.pack_start(o.selector, False)
1522
 
+                """
1523
 
+                table.addWidget(o.selector, rows-1, 1)
1524
 
+                self.options[option.keyword] = o
1525
 
+                o.selector.setEnabled(editable)
1526
 
+                if option.keyword == "InputSlot":
1527
 
+                    self.option_inputslot = o
1528
 
+                elif option.keyword == "ManualFeed":
1529
 
+                    self.option_manualfeed = o
1530
 
+
1531
 
+        """
1532
 
+        # remove Installable Options tab if not needed
1533
 
+        if not hasInstallableOptions:
1534
 
+            tab_nr = self.ntbkPrinter.page_num(self.swPInstallOptions)
1535
 
+            if tab_nr != -1:
1536
 
+                self.ntbkPrinter.remove_page(tab_nr)
1537
 
+
1538
 
+        # check for conflicts
1539
 
+        for option in self.options.itervalues():
1540
 
+            conflicts = option.checkConflicts()
1541
 
+            if conflicts:
1542
 
+                self.conflicts.add(option)
1543
 
+
1544
 
+        self.swPInstallOptions.show_all()
1545
 
+        self.swPOptions.show_all()
1546
 
+        """
1547
 
+
1548
 
+
1549
 
+    # Class members
1550
 
+    
1551
 
+    def fillClassMembers(self, name, editable):
1552
 
+        printer = self.printers[name]
1553
 
+
1554
 
+        self.ui.btnClassAddMember.setEnabled(editable)
1555
 
+        self.ui.btnClassDelMember.setEnabled(editable)
1556
 
+
1557
 
+        # remove Options tab
1558
 
+        tab_nr = self.ui.ntbkPrinter.indexOf(self.optionsTabWidget)
1559
 
+        if tab_nr != -1:
1560
 
+            self.ui.ntbkPrinter.removeTab(tab_nr)
1561
 
+        policiesTabNo = self.ui.ntbkPrinter.indexOf(self.policiesTabWidget)
1562
 
+        self.ui.ntbkPrinter.insertTab(policiesTabNo+1, self.memberTabWidget, i18n("Members"))
1563
 
+
1564
 
+        self.ui.tvClassMembers.clear()
1565
 
+        self.ui.tvClassNotMembers.clear()
1566
 
+        names = self.printers.keys()
1567
 
+        names.sort()
1568
 
+        for name in names:
1569
 
+            p = self.printers[name]
1570
 
+            if p is not printer:
1571
 
+                if name in printer.class_members:
1572
 
+                    self.ui.tvClassMembers.addItem(name)
1573
 
+                else:
1574
 
+                    self.ui.tvClassNotMembers.addItem(name)
1575
 
+
1576
 
+    def on_btnClassAddMember_clicked(self):
1577
 
+        self.moveClassMembers(self.ui.tvClassNotMembers,
1578
 
+                              self.ui.tvClassMembers)
1579
 
+        if self.getCurrentClassMembers(self.ui.tvClassMembers) != self.printer.class_members:
1580
 
+            self.changed.add(self.ui.tvClassMembers)
1581
 
+        else:
1582
 
+            self.changed.discard(self.ui.tvClassMembers)
1583
 
+        self.setDataButtonState()
1584
 
+
1585
 
+    def on_btnClassDelMember_clicked(self):
1586
 
+        self.moveClassMembers(self.ui.tvClassMembers,
1587
 
+                              self.ui.tvClassNotMembers)
1588
 
+        if self.getCurrentClassMembers(self.ui.tvClassMembers) != self.printer.class_members:
1589
 
+            self.changed.add(self.ui.tvClassMembers)
1590
 
+        else:
1591
 
+            self.changed.discard(self.ui.tvClassMembers)
1592
 
+        self.setDataButtonState()
1593
 
+
1594
 
+    #In Gnome is now on_delete_activate(self, UNUSED):
1595
 
+    def btnDelete_clicked(self):
1596
 
+        name, type = self.getSelectedItem()
1597
 
+
1598
 
+        # Confirm
1599
 
+        if type == "Printer":
1600
 
+            message_format = i18n("Really delete printer %s?")
1601
 
+        else:
1602
 
+            message_format = i18n("Really delete class %s?")
1603
 
+
1604
 
+        answer = KMessageBox.questionYesNo(self,
1605
 
+                    unicode(message_format) % name,
1606
 
+                    "")
1607
 
+
1608
 
+        if answer == KMessageBox.Yes:
1609
 
+            try:
1610
 
+                self.cups.deletePrinter(name)
1611
 
+            except cups.IPPError, (e, msg):
1612
 
+                self.show_IPP_Error(e, msg)
1613
 
+        elif answer == KMessageBox.No:
1614
 
+            return
1615
 
+
1616
 
+        self.changed = set()
1617
 
+        self.populateList()
1618
 
+        self.ui.mainlist.setCurrentItem(self.ui.mainlist.itemAt(0,0))
1619
 
+
1620
 
+    #Taken from the gnome version
1621
 
+    def setDefaultPrinter(self, name):
1622
 
+        printer = self.printers[name]
1623
 
+        try:
1624
 
+            printer.setAsDefault()
1625
 
+        except cups.HTTPError, (s,):
1626
 
+            self.show_HTTP_Error(s)
1627
 
+            return
1628
 
+        except cups.IPPError(e, msg):
1629
 
+            show_IPP_Error(e, msg)
1630
 
+            return
1631
 
+
1632
 
+    def chkPMakeDefault_stateChanged(self):
1633
 
+        default = self.cups.getDefault()
1634
 
+        try:
1635
 
+            if self.ui.chkPMakeDefault.isChecked():
1636
 
+                name = self.ui.entPName.text()
1637
 
+                self.setDefaultPrinter(unicode(name))
1638
 
+                self.ui.chkPMakeDefault.setText(i18n("This is the default printer"))
1639
 
+            else:
1640
 
+                if default is not None:
1641
 
+                    self.ui.chkPMakeDefault.setText(i18n('Make Default. (The current default is %1)', default))
1642
 
+                else:
1643
 
+                    self.ui.chkPMakeDefault.setText(i18n('Make Default. (There is no current default)'))
1644
 
+
1645
 
+            self.ui.changed(len(self.changed) > 0)
1646
 
+            #self.ui.btnPrinterPropertiesApply.setEnabled(len (self.changed) > 0)
1647
 
+            #self.ui.btnRevert.setEnabled(len (self.changed) > 0)
1648
 
+            
1649
 
+        except cups.IPPError, (e, msg):
1650
 
+            self.show_IPP_Error(e, msg)
1651
 
+            return
1652
 
+
1653
 
+##############################
1654
 
+        #Obsolete? Possibly no longer necessary. Not included in 
1655
 
+        #current gnome version
1656
 
+        # Also need to check system-wide lpoptions because that's how
1657
 
+        # previous Fedora versions set the default (bug #217395).
1658
 
+        (tmpfd, tmpfname) = tempfile.mkstemp ()
1659
 
+        success = False
1660
 
+        try:
1661
 
+            resource = "/admin/conf/lpoptions"
1662
 
+            self.cups.getFile(resource, tmpfname)
1663
 
+            #success = True
1664
 
+        except cups.HTTPError, (s,):
1665
 
+            try:
1666
 
+                os.remove (tmpfname)
1667
 
+            except OSError:
1668
 
+                pass
1669
 
+
1670
 
+            if s != cups.HTTP_NOT_FOUND:
1671
 
+                self.show_HTTP_Error(s)
1672
 
+                return
1673
 
+
1674
 
+        if success:
1675
 
+            lines = file (tmpfname).readlines ()
1676
 
+            changed = False
1677
 
+            i = 0
1678
 
+            for line in lines:
1679
 
+                if line.startswith ("Default "):
1680
 
+                    # This is the system-wide default.
1681
 
+                    name = line.split (' ')[1]
1682
 
+                    if name != self.printer.name:
1683
 
+                        # Stop it from over-riding the server default.
1684
 
+                        lines[i] = "Dest " + line[8:]
1685
 
+                        changed = True
1686
 
+                i += 1
1687
 
+
1688
 
+            if changed:
1689
 
+                file (tmpfname, 'w').writelines (lines)
1690
 
+                try:
1691
 
+                    self.cups.putFile (resource, tmpfname)
1692
 
+                except cups.HTTPError, (s,):
1693
 
+                    os.remove (tmpfname)
1694
 
+                    self.show_HTTP_Error(s)
1695
 
+                    return
1696
 
+#########################
1697
 
+                # Now reconnect because the server needs to reload.
1698
 
+                self.reconnect ()
1699
 
+
1700
 
+        try:
1701
 
+            os.remove (tmpfname)
1702
 
+        except OSError:
1703
 
+            pass
1704
 
+
1705
 
+        try:
1706
 
+            self.populateList()
1707
 
+        except cups.HTTPError, (s,):
1708
 
+            self.cups = None
1709
 
+            self.setConnected()
1710
 
+            self.populateList()
1711
 
+            self.show_HTTP_Error(s)
1712
 
+
1713
 
+    def option_changed(self, option):
1714
 
+        if option.is_changed():
1715
 
+            self.changed.add(option)
1716
 
+        else:
1717
 
+            self.changed.discard(option)
1718
 
+
1719
 
+        if option.conflicts:
1720
 
+            self.conflicts.add(option)
1721
 
+        else:
1722
 
+            self.conflicts.discard(option)
1723
 
+        self.setDataButtonState()
1724
 
+
1725
 
+        if (self.option_manualfeed and self.option_inputslot and
1726
 
+            option == self.option_manualfeed):
1727
 
+            if option.get_current_value() == "True":
1728
 
+                self.option_inputslot.disable ()
1729
 
+            else:
1730
 
+                self.option_inputslot.enable ()
1731
 
+
1732
 
+    # Access control
1733
 
+    def getPUsers(self):
1734
 
+        """return list of usernames from the GUI"""
1735
 
+        result = [] #empty list to hold result
1736
 
+        #if there is only one user in the list
1737
 
+        if self.ui.tvPUsers.topLevelItemCount() < 2:
1738
 
+            item = self.ui.tvPUsers.itemAt(0, 0)
1739
 
+            #use a string instead of a QString.
1740
 
+            #system-config-printer fails in 
1741
 
+            #self.connection.setPrinterUsersDenied(self.name, except_users)
1742
 
+            #if we use a QString
1743
 
+            if item is not None:
1744
 
+                name = str(item.text(0))
1745
 
+                result.append(name)
1746
 
+        else:
1747
 
+            #create an iterator for the QTreeWidgetObject
1748
 
+            #had to create an iterator class manually because QTreeWidgetItemIterator
1749
 
+            #is broken
1750
 
+            it = Iter(self.ui.tvPUsers)    
1751
 
+            while it: #iterate over the tree
1752
 
+                try:
1753
 
+                    item = it.next()
1754
 
+                    name = item.text(0)
1755
 
+                    result.append(name)
1756
 
+                except StopIteration:
1757
 
+                    break
1758
 
+                    
1759
 
+        result.sort()
1760
 
+        return result
1761
 
+
1762
 
+    def setPUsers(self, users):
1763
 
+        """write list of usernames into the GUI"""
1764
 
+        self.ui.tvPUsers.clear()
1765
 
+        for user in users:
1766
 
+            #create a QTreeWidgetItem
1767
 
+            u = QTreeWidgetItem(self.ui.tvPUsers)
1768
 
+            u.setText(0, user) #set the label for the item
1769
 
+            #add the item to the top level of the tree
1770
 
+            self.ui.tvPUsers.addTopLevelItem(u)
1771
 
+
1772
 
+    def checkPUsersChanged(self):
1773
 
+        """check if users in GUI and printer are different
1774
 
+        and set self.changed"""
1775
 
+        if self.getPUsers() != self.printer.except_users:
1776
 
+            self.changed.add(self.ui.tvPUsers)
1777
 
+        else:
1778
 
+            self.changed.discard(self.ui.tvPUsers)
1779
 
+
1780
 
+        self.setDataButtonState()
1781
 
+
1782
 
+    def btnPAddUser_clicked(self):
1783
 
+        current_user = os.getenv('USER')
1784
 
+        user, ok = KInputDialog.getText(i18n('Add User'), i18n('Enter Username'), current_user)
1785
 
+        type(user)
1786
 
+        
1787
 
+        if ok and not user.isEmpty():
1788
 
+            u = QTreeWidgetItem(self.ui.tvPUsers)
1789
 
+            u.setText(0, user)
1790
 
+            self.ui.tvPUsers.addTopLevelItem(u)
1791
 
+        
1792
 
+        self.checkPUsersChanged()
1793
 
+
1794
 
+    def btnPDelUser_clicked(self):
1795
 
+        users = self.ui.tvPUsers.selectedItems()
1796
 
+        for u in users:
1797
 
+            index = self.ui.tvPUsers.indexOfTopLevelItem(u)
1798
 
+            self.ui.tvPUsers.takeTopLevelItem(index)
1799
 
+    
1800
 
+        self.checkPUsersChanged()
1801
 
+
1802
 
+    # Server side options
1803
 
+    def on_job_option_reset(self):
1804
 
+        button = self.sender()
1805
 
+        option = self.job_options_buttons[button]
1806
 
+        option.reset ()
1807
 
+        # Remember to set this option for removal in the IPP request.
1808
 
+        if self.server_side_options.has_key (option.name):
1809
 
+            del self.server_side_options[option.name]
1810
 
+        if option.is_changed ():
1811
 
+            self.changed.add(option)
1812
 
+        else:
1813
 
+            self.changed.discard(option)
1814
 
+        self.setDataButtonState()
1815
 
+
1816
 
+    def on_job_option_changed(self):
1817
 
+        if not self.printer:
1818
 
+            return
1819
 
+        widget = self.sender()
1820
 
+        option = self.job_options_widgets[widget]
1821
 
+        option.changed ()
1822
 
+        if option.is_changed ():
1823
 
+            self.server_side_options[option.name] = option
1824
 
+            self.changed.add(option)
1825
 
+        else:
1826
 
+            if self.server_side_options.has_key (option.name):
1827
 
+                del self.server_side_options[option.name]
1828
 
+            self.changed.discard(option)
1829
 
+        self.setDataButtonState()
1830
 
+        # Don't set the reset button insensitive if the option hasn't
1831
 
+        # changed from the original value: it's still meaningful to
1832
 
+        # reset the option to the system default.
1833
 
+
1834
 
+    def draw_other_job_options (self, editable=True):
1835
 
+        n = len (self.other_job_options)
1836
 
+        #if n == 0:
1837
 
+        #    self.tblJOOther.hide_all ()
1838
 
+        #    return
1839
 
+
1840
 
+        #self.tblJOOther.resize (n, 3)
1841
 
+        children = self.ui.tblJOOtherWidget.children()
1842
 
+        for child in children:
1843
 
+            if type(child) != QGridLayout:
1844
 
+                self.ui.tblJOOther.removeWidget(child)
1845
 
+                child.hide()
1846
 
+        i = 0
1847
 
+        self.removeJobOptionButtons = {}
1848
 
+        for opt in self.other_job_options:
1849
 
+            self.ui.tblJOOther.addWidget(opt.label, i, 0)
1850
 
+            self.ui.tblJOOther.addWidget(opt.selector, i, 1)
1851
 
+            opt.label.show()
1852
 
+            opt.selector.show()
1853
 
+            opt.selector.setEnabled(editable)
1854
 
+
1855
 
+            btn = QPushButton("Remove", self.ui.tblJOOtherWidget)
1856
 
+            self.connect(btn, SIGNAL("clicked()"), self.on_btnJOOtherRemove_clicked)
1857
 
+            #btn.set_data("pyobject", opt)
1858
 
+            self.removeJobOptionButtons[btn] = opt
1859
 
+            btn.setEnabled(editable)
1860
 
+            self.ui.tblJOOther.addWidget(btn, i, 2)
1861
 
+            i += 1
1862
 
+
1863
 
+        #self.tblJOOther.show_all ()
1864
 
+
1865
 
+    def add_job_option(self, name, value = "", supported = "", is_new=True,
1866
 
+                       editable=True):
1867
 
+        option = options.OptionWidget(name, value, supported,
1868
 
+                                      self.option_changed)
1869
 
+        option.is_new = is_new
1870
 
+        self.other_job_options.append (option)
1871
 
+        self.draw_other_job_options (editable=editable)
1872
 
+        self.server_side_options[name] = option
1873
 
+        if name in self.changed: # was deleted before
1874
 
+            option.is_new = False
1875
 
+        self.changed.add(option)
1876
 
+        self.setDataButtonState()
1877
 
+        if is_new:
1878
 
+            ##option.selector.grab_focus ()
1879
 
+            pass #FIXME
1880
 
+
1881
 
+    def on_btnJOOtherRemove_clicked(self):
1882
 
+        button = self.sender()
1883
 
+        option = self.removeJobOptionButtons[button]
1884
 
+        #option = button.get_data("pyobject")
1885
 
+        self.other_job_options.remove (option)
1886
 
+        self.draw_other_job_options ()
1887
 
+        if option.is_new:
1888
 
+            self.changed.discard(option)
1889
 
+        else:
1890
 
+            # keep name as reminder that option got deleted
1891
 
+            self.changed.add(option.name)
1892
 
+        del self.server_side_options[option.name]
1893
 
+        self.setDataButtonState()
1894
 
+
1895
 
+    def on_btnNewJobOption_clicked(self):
1896
 
+        name = self.ui.entNewJobOption.text()
1897
 
+        self.add_job_option(name)
1898
 
+        #self.tblJOOther.show_all()
1899
 
+        self.ui.entNewJobOption.setText('')
1900
 
+        self.ui.btnNewJobOption.setEnabled(False)
1901
 
+        self.setDataButtonState()
1902
 
+
1903
 
+    def on_entNewJobOption_changed(self, widget):
1904
 
+        text = unicode(self.ui.entNewJobOption.text())
1905
 
+        active = (len(text) > 0) and text not in self.server_side_options
1906
 
+        self.ui.btnNewJobOption.setEnabled(active)
1907
 
+
1908
 
+    def on_entNewJobOption_activate(self, widget):
1909
 
+        self.on_btnNewJobOption_clicked (widget) # wrong widget but ok
1910
 
+
1911
 
+    ##########################################################################
1912
 
+    ### Server settings
1913
 
+    ##########################################################################
1914
 
+
1915
 
+    def fillServerTab(self):
1916
 
+        self.changed = set()
1917
 
+        try:
1918
 
+            self.server_settings = self.cups.adminGetServerSettings()
1919
 
+        except cups.IPPError, (e, m):
1920
 
+            #FIXME
1921
 
+            self.show_IPP_Error(e, m)
1922
 
+            self.ui.tvMainList.get_selection().unselect_all()
1923
 
+            self.on_tvMainList_cursor_changed(self.ui.tvMainList)
1924
 
+            return
1925
 
+
1926
 
+        for widget, setting in [
1927
 
+            (self.ui.chkServerBrowse, cups.CUPS_SERVER_REMOTE_PRINTERS),
1928
 
+            (self.ui.chkServerShare, cups.CUPS_SERVER_SHARE_PRINTERS),
1929
 
+            (self.ui.chkServerShareAny, try_CUPS_SERVER_REMOTE_ANY),
1930
 
+            (self.ui.chkServerRemoteAdmin, cups.CUPS_SERVER_REMOTE_ADMIN),
1931
 
+            (self.ui.chkServerAllowCancelAll, cups.CUPS_SERVER_USER_CANCEL_ANY),
1932
 
+            (self.ui.chkServerLogDebug, cups.CUPS_SERVER_DEBUG_LOGGING),]:
1933
 
+            # widget.set_data("setting", setting)
1934
 
+            self.widget_data_setting[widget] = setting
1935
 
+            self.disconnect(widget, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
1936
 
+            if self.server_settings.has_key(setting):
1937
 
+                widget.setChecked(int(self.server_settings[setting]))
1938
 
+                widget.setEnabled(True)
1939
 
+            else:
1940
 
+                widget.setChecked(False)
1941
 
+                widget.setEnabled(False)
1942
 
+            self.connect(widget, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
1943
 
+        self.setDataButtonState()
1944
 
+        # Set sensitivity of 'Allow printing from the Internet'.
1945
 
+        self.on_server_changed (self.ui.chkServerShare) # (any will do here)
1946
 
+
1947
 
+    def on_server_widget_changed(self, value):
1948
 
+        self.on_server_changed(self.sender())
1949
 
+
1950
 
+    def on_server_changed(self, widget):
1951
 
+        setting = self.widget_data_setting[widget]
1952
 
+        if self.server_settings.has_key (setting):
1953
 
+            if str(int(widget.isChecked())) == self.server_settings[setting]:
1954
 
+                self.changed.discard(widget)
1955
 
+            else:
1956
 
+                self.changed.add(widget)
1957
 
+
1958
 
+        sharing = self.ui.chkServerShare.isChecked ()
1959
 
+        self.ui.chkServerShareAny.setEnabled (
1960
 
+            sharing and self.server_settings.has_key(try_CUPS_SERVER_REMOTE_ANY))
1961
 
+
1962
 
+        self.setDataButtonState()
1963
 
+
1964
 
+    def save_serversettings(self):
1965
 
+        setting_dict = self.server_settings.copy()
1966
 
+        for widget, setting in [
1967
 
+            (self.ui.chkServerBrowse, cups.CUPS_SERVER_REMOTE_PRINTERS),
1968
 
+            (self.ui.chkServerShare, cups.CUPS_SERVER_SHARE_PRINTERS),
1969
 
+            (self.ui.chkServerShareAny, try_CUPS_SERVER_REMOTE_ANY),
1970
 
+            (self.ui.chkServerRemoteAdmin, cups.CUPS_SERVER_REMOTE_ADMIN),
1971
 
+            (self.ui.chkServerAllowCancelAll, cups.CUPS_SERVER_USER_CANCEL_ANY),
1972
 
+            (self.ui.chkServerLogDebug, cups.CUPS_SERVER_DEBUG_LOGGING),]:
1973
 
+            if not self.server_settings.has_key(setting): continue
1974
 
+            setting_dict[setting] = str(int(widget.isChecked()))
1975
 
+        try:
1976
 
+            self.cups.adminSetServerSettings(setting_dict)
1977
 
+        except cups.IPPError, (e, m):
1978
 
+            self.show_IPP_Error(e, m)
1979
 
+            return True
1980
 
+        except RuntimeError, s:
1981
 
+            self.show_IPP_Error(None, s)
1982
 
+            return True
1983
 
+        self.changed = set()
1984
 
+        self.setDataButtonState()
1985
 
+        time.sleep(1) # give the server a chance to process our request
1986
 
+
1987
 
+        # Now reconnect, in case the server needed to reload.
1988
 
+        self.reconnect ()
1989
 
+
1990
 
+        # Refresh the server settings in case they have changed in the
1991
 
+        # mean time.
1992
 
+        try:
1993
 
+            self.fillServerTab()
1994
 
+        except:
1995
 
+            nonfatalException()
1996
 
+
1997
 
+    # ====================================================================
1998
 
+    # == New Printer Dialog ==============================================
1999
 
+    # ====================================================================
2000
 
+
2001
 
+    # new printer
2002
 
+    def on_new_printer_activate(self):
2003
 
+        self.ui.setCursor(Qt.WaitCursor)
2004
 
+        self.newPrinterGUI.init("printer")
2005
 
+        self.ui.setCursor(Qt.ArrowCursor)
2006
 
+
2007
 
+    # new class
2008
 
+    def on_new_class_activate(self):
2009
 
+        self.ui.setCursor(Qt.WaitCursor)
2010
 
+        self.newPrinterGUI.init("class")
2011
 
+        self.ui.setCursor(Qt.ArrowCursor)
2012
 
+
2013
 
+    @pyqtSignature("")
2014
 
+    def on_btnSelectDevice_clicked(self):
2015
 
+        self.newPrinterGUI.init("device")
2016
 
+
2017
 
+    @pyqtSignature("")
2018
 
+    def on_btnChangePPD_clicked(self):
2019
 
+        self.ui.setCursor(Qt.WaitCursor)
2020
 
+        self.newPrinterGUI.init("ppd")
2021
 
+        self.ui.setCursor(Qt.ArrowCursor)
2022
 
+
2023
 
+    def checkNPName(self, name):
2024
 
+        if not name: return False
2025
 
+        name = name.lower()
2026
 
+        for printer in self.printers.values():
2027
 
+            if not printer.discovered and printer.name.lower()==name:
2028
 
+                return False
2029
 
+        return True
2030
 
+
2031
 
+    def makeNameUnique(self, name):
2032
 
+        """Make a suggested queue name valid and unique."""
2033
 
+        name = name.replace (" ", "_")
2034
 
+        name = name.replace ("/", "_")
2035
 
+        name = name.replace ("#", "_")
2036
 
+        if not self.checkNPName (name):
2037
 
+            suffix=2
2038
 
+            while not self.checkNPName (name + str (suffix)):
2039
 
+                suffix += 1
2040
 
+                if suffix == 100:
2041
 
+                    break
2042
 
+            name += str (suffix)
2043
 
+        return name
2044
 
+
2045
 
+    #TODO
2046
 
+    ## Watcher interface helpers
2047
 
+
2048
 
+    @pyqtSignature("")
2049
 
+    def on_btnRevert_clicked(self):
2050
 
+        self.changed = set() # avoid asking the user
2051
 
+        self.on_tvMainList_cursor_changed()
2052
 
+
2053
 
+    @pyqtSignature("")
2054
 
+    def on_btnPrinterPropertiesApply_clicked(self):
2055
 
+        err = self.printer_properties_response()
2056
 
+        if not err:
2057
 
+            self.populateList()
2058
 
+        else:
2059
 
+            nonfatalException()
2060
 
+
2061
 
+    def show_IPP_Error(self, exception, message):
2062
 
+        if exception == cups.IPP_NOT_AUTHORIZED:
2063
 
+            KMessageBox.error(self, i18n('The password may be incorrect.'), i18n('Not authorized'))
2064
 
+        else:
2065
 
+            KMessageBox.error(self, i18n("There was an error during the CUPS " "operation: '%1'.", message),
2066
 
+                                    i18n('CUPS server error'))
2067
 
+
2068
 
+    def show_HTTP_Error(self, status):
2069
 
+        if (status == cups.HTTP_UNAUTHORIZED or
2070
 
+            status == cups.HTTP_FORBIDDEN):
2071
 
+            
2072
 
+            KMessageBox.error(self,i18n('The password may be incorrect, or the '
2073
 
+                                   'server may be configured to deny '
2074
 
+                                   'remote administration.'),
2075
 
+                                   i18n('Not authorized') )
2076
 
+        else:
2077
 
+            if status == cups.HTTP_BAD_REQUEST:
2078
 
+                msg = i18nc("HTTP error", "Bad request")
2079
 
+            elif status == cups.HTTP_NOT_FOUND:
2080
 
+                msg = i18nc("HTTP error", "Not found")
2081
 
+            elif status == cups.HTTP_REQUEST_TIMEOUT:
2082
 
+                msg = i18nc("HTTP error", "Request timeout")
2083
 
+            elif status == cups.HTTP_UPGRADE_REQUIRED:
2084
 
+                msg = i18nc("HTTP error", "Upgrade required")
2085
 
+            elif status == cups.HTTP_SERVER_ERROR:
2086
 
+                msg = i18nc("HTTP error", "Server error")
2087
 
+            elif status == -1:
2088
 
+                msg = i18nc("HTTP error", "Not connected")
2089
 
+            else:
2090
 
+                msg = i18nc("HTTP error", "status %1", status)
2091
 
+
2092
 
+        KMessageBox.error(self, i18n("There was an HTTP error: %1.", msg), i18n('CUPS server error'))
2093
 
+
2094
 
+    def getSelectedItem(self):
2095
 
+        return unicode(self.mainListSelectedName), unicode(self.mainListSelectedType)
2096
 
+        """
2097
 
+        items = self.mainlist.selectedItems()
2098
 
+        if len(items) < 1:
2099
 
+            return ("", 'None')
2100
 
+            item = items[0]
2101
 
+            name = item.text(0)
2102
 
+            type = item.text(1)
2103
 
+            name = str(name).decode ('utf-8')
2104
 
+            return name.strip(), type
2105
 
+        """
2106
 
+
2107
 
+    def reconnect (self):
2108
 
+        """Reconnect to CUPS after the server has reloaded."""
2109
 
+        # libcups would handle the reconnection if we just told it to
2110
 
+        # do something, for example fetching a list of classes.
2111
 
+        # However, our local authentication certificate would be
2112
 
+        # invalidated by a server restart, so it is better for us to
2113
 
+        # handle the reconnection ourselves.
2114
 
+
2115
 
+        # Disconnect.
2116
 
+        self.cups = None
2117
 
+        self.setConnected()
2118
 
+
2119
 
+        cups.setServer(self.connect_server)
2120
 
+        cups.setUser(self.connect_user)
2121
 
+        attempt = 1
2122
 
+        while attempt <= 5:
2123
 
+            try:
2124
 
+                self.cups = cups.Connection ()
2125
 
+                break
2126
 
+            except RuntimeError:
2127
 
+                # Connection failed.
2128
 
+                time.sleep(1)
2129
 
+                attempt += 1
2130
 
+
2131
 
+        self.setConnected()
2132
 
+        self.passwd_retry = False
2133
 
+
2134
 
+    def updatePrinterProperties(self):
2135
 
+        debugprint ("update printer properties")
2136
 
+        printer = self.printer
2137
 
+        self.ui.lblPMakeModel.setText(printer.make_and_model)
2138
 
+        state = self.printer_states.get (printer.state, i18nc("Printer state", "Unknown"))[:]
2139
 
+        reason = printer.other_attributes.get ('printer-state-message', '')
2140
 
+        if len (reason) > 0:
2141
 
+            state += ' - ' + reason
2142
 
+        self.ui.lblPState.setText(state)
2143
 
+        if len (self.changed) == 0:
2144
 
+            debugprint ("no changes yet: full printer properties update")
2145
 
+
2146
 
+            # State
2147
 
+            self.ui.chkPEnabled.setEnabled(printer.enabled)
2148
 
+            self.ui.chkPAccepting.setEnabled(not printer.rejecting)
2149
 
+            self.ui.chkPShared.setEnabled(printer.is_shared)
2150
 
+
2151
 
+            # Job sheets
2152
 
+            self.fillComboBox(self.ui.cmbPStartBanner,
2153
 
+                              printer.job_sheets_supported,
2154
 
+                              printer.job_sheet_start),
2155
 
+            self.fillComboBox(self.ui.cmbPEndBanner, printer.job_sheets_supported,
2156
 
+                              printer.job_sheet_end)
2157
 
+
2158
 
+#FIXME Not implemented in current UI
2159
 
+            # Policies
2160
 
+            #self.fillComboBox(self.cmbPErrorPolicy,
2161
 
+                              #printer.error_policy_supported,
2162
 
+                              #printer.error_policy)
2163
 
+            #self.fillComboBox(self.cmbPOperationPolicy,
2164
 
+                              #printer.op_policy_supported,
2165
 
+                              #printer.op_policy)
2166
 
+
2167
 
+            
2168
 
+            # Access control
2169
 
+            self.ui.rbtnPAllow.setChecked(printer.default_allow)
2170
 
+            self.ui.rbtnPDeny.setChecked(not printer.default_allow)
2171
 
+            self.setPUsers(printer.except_users)
2172
 
+            
2173
 
+
2174
 
+    def setTestButton (self, printer):
2175
 
+        if printer.testsQueued ():
2176
 
+            self.test_button_cancels = True
2177
 
+            self.ui.btnPrintTestPage.setText(i18n('Cancel Tests'))
2178
 
+            self.ui.btnPrintTestPage.setEnabled(True)
2179
 
+        else:
2180
 
+            self.test_button_cancels = False
2181
 
+            self.ui.btnPrintTestPage.setText(i18n('Print Test Page'))
2182
 
+            self.setDataButtonState()
2183
 
+
2184
 
+    def getCurrentClassMembers(self, listwidget):
2185
 
+        count = listwidget.count()
2186
 
+        result = []
2187
 
+        for i in range(count):            
2188
 
+            result.append(listwidget.item(i).text())
2189
 
+        result.sort()
2190
 
+        return result
2191
 
+
2192
 
+    def moveClassMembers(self, treeview_from, treeview_to):
2193
 
+        rows = treeview_from.selectedItems()
2194
 
+        for row in rows:
2195
 
+            treeview_from.takeItem(treeview_from.row(row))
2196
 
+            treeview_to.addItem(row)
2197
 
+
2198
 
+    #FIXME obsolete?
2199
 
+    def cupsPasswdCallback(self, querystring):
2200
 
+        return "" #FIXME
2201
 
+        if self.passwd_retry or len(self.password) == 0:
2202
 
+            waiting = self.WaitWindow.get_property('visible')
2203
 
+            if waiting:
2204
 
+                self.WaitWindow.hide ()
2205
 
+            self.lblPasswordPrompt.set_label (self.prompt_primary +
2206
 
+                                            querystring)
2207
 
+            self.PasswordDialog.set_transient_for (self.MainWindow)
2208
 
+            self.entPasswd.grab_focus ()
2209
 
+
2210
 
+            result = self.PasswordDialog.run()
2211
 
+            self.PasswordDialog.hide()
2212
 
+            if waiting:
2213
 
+                self.WaitWindow.show ()
2214
 
+            while gtk.events_pending ():
2215
 
+                gtk.main_iteration ()
2216
 
+            if result == gtk.RESPONSE_OK:
2217
 
+                self.password = self.entPasswd.get_text()
2218
 
+            else:
2219
 
+                self.password = ''
2220
 
+            self.passwd_retry = False
2221
 
+        else:
2222
 
+            self.passwd_retry = True
2223
 
+        return self.password
2224
 
+
2225
 
+
2226
 
+class NewPrinterGUI(QDialog):
2227
 
+
2228
 
+    new_printer_device_tabs = {
2229
 
+        "parallel" : 0, # empty tab
2230
 
+        "usb" : 0,
2231
 
+        "hal" : 0,
2232
 
+        "beh" : 0,
2233
 
+        "hp" : 0,
2234
 
+        "hpfax" : 0,
2235
 
+        "socket": 2,
2236
 
+        "ipp" : 3,
2237
 
+        "http" : 3,
2238
 
+        "lpd" : 4,
2239
 
+        "scsi" : 5,
2240
 
+        "serial" : 6,
2241
 
+        "smb" : 7,
2242
 
+        }
2243
 
+
2244
 
+    ntbkNewPrinterPages = {
2245
 
+        "name" : 0,
2246
 
+        "device" : 1,
2247
 
+        "make" : 2,
2248
 
+        "model" : 3,
2249
 
+        "class-members" : 4,
2250
 
+        "downloadable" : -1,
2251
 
+    }
2252
 
+
2253
 
+    def __init__(self, mainapp):
2254
 
+        QDialog.__init__(self, mainapp)
2255
 
+        self.mainapp = mainapp
2256
 
+        self.language = mainapp.language
2257
 
+        self.dialog_mode = ""
2258
 
+
2259
 
+        self.WaitWindow = QMessageBox(self.mainapp)
2260
 
+        self.WaitWindow.setStandardButtons(QMessageBox.NoButton)
2261
 
+
2262
 
+        uic.loadUi(APPDIR + "/" + "new-printer.ui", self)
2263
 
+
2264
 
+        self.btnNPBack.setIcon(KIcon("go-previous"))
2265
 
+        self.btnNPForward.setIcon(KIcon("go-next"))
2266
 
+        self.btnNPCancel.setIcon(KIcon("dialog-cancel"))
2267
 
+        self.btnNPApply.setIcon(KIcon("dialog-ok"))
2268
 
+        self.btnNCAddMember.setIcon(KIcon("arrow-left"))
2269
 
+        self.btnNCDelMember.setIcon(KIcon("arrow-right"))
2270
 
+
2271
 
+        self.connect(self.tvNPDevices, SIGNAL("itemSelectionChanged()"), self.on_tvNPDevices_cursor_changed)
2272
 
+        self.connect(self.tvNPMakes, SIGNAL("itemSelectionChanged()"), self.on_tvNPMakes_cursor_changed)
2273
 
+        self.connect(self.tvNPModels, SIGNAL("itemSelectionChanged()"), self.on_tvNPModels_cursor_changed)
2274
 
+        self.connect(self.entNPTDevice, SIGNAL("textEdited(const QString&)"), self.on_entNPTDevice_changed)
2275
 
+#        self.connect(self.entNPTIPPHostname, SIGNAL("textEdited(const QString&)"), self.on_entNPTIPPHostname_changed)
2276
 
+#        self.connect(self.entNPTIPPQueuename, SIGNAL("textEdited(const QString&)"), self.on_entNPTIPPQueuename_changed)
2277
 
+        self.connect(self.entSMBURI, SIGNAL("textEdited(const QString&)"), self.on_entSMBURI_changed)
2278
 
+        self.rbtnSMBAuthPrompt.setChecked(True)
2279
 
+        self.on_rbtnSMBAuthSet_toggled(False)
2280
 
+        self.connect(self.rbtnSMBAuthSet, SIGNAL("toggled(bool)"), self.on_rbtnSMBAuthSet_toggled)
2281
 
+        self.rbtnNPFoomatic.setChecked(True)
2282
 
+        self.connect(self.rbtnNPFoomatic, SIGNAL("toggled(bool)"), self.on_rbtnNPFoomatic_toggled)
2283
 
+        self.connect(self.filechooserPPDButton, SIGNAL("clicked()"),self.on_filechooserPPDButton)
2284
 
+        self.options = {} # keyword -> Option object
2285
 
+        self.changed = set()
2286
 
+        self.conflicts = set()
2287
 
+        self.ppd = None
2288
 
+        
2289
 
+        # Synchronisation objects.
2290
 
+        self.ppds_lock = thread.allocate_lock()
2291
 
+        self.devices_lock = thread.allocate_lock()
2292
 
+        self.smb_lock = thread.allocate_lock()
2293
 
+        self.ipp_lock = thread.allocate_lock()
2294
 
+        self.drivers_lock = thread.allocate_lock()
2295
 
+
2296
 
+        #self.connect(self.btnNCAddMember, SIGNAL("clicked()"), self.slot_btnNCAddMember_clicked)
2297
 
+        #self.connect(self.btnNCDelMember, SIGNAL("clicked()"), self.slot_btnNCDelMember_clicked)
2298
 
+
2299
 
+        # Optionally disable downloadable driver support.
2300
 
+        #if not config.DOWNLOADABLE_DRIVER_SUPPORT:
2301
 
+        if True:
2302
 
+            self.rbtnNPDownloadableDriverSearch.setEnabled(False)
2303
 
+            self.downloadableDriverSearchFrame.hide()
2304
 
+
2305
 
+        """
2306
 
+        # Set up OpenPrinting widgets.
2307
 
+        self.openprinting = openprinting.OpenPrinting ()
2308
 
+        self.openprinting_query_handle = None
2309
 
+        combobox = self.cmbNPDownloadableDriverFoundPrinters
2310
 
+        cell = gtk.CellRendererText()
2311
 
+        combobox.pack_start (cell, True)
2312
 
+        combobox.add_attribute(cell, 'text', 0)
2313
 
+
2314
 
+        # SMB browser
2315
 
+        self.smb_store = gtk.TreeStore (str, # host or share
2316
 
+                                        str, # comment
2317
 
+                                        gobject.TYPE_PYOBJECT, # domain dict
2318
 
+                                        gobject.TYPE_PYOBJECT) # host dict
2319
 
+        self.tvSMBBrowser.set_model (self.smb_store)
2320
 
+        self.smb_store.set_sort_column_id (0, gtk.SORT_ASCENDING)
2321
 
+
2322
 
+        # SMB list columns
2323
 
+        col = gtk.TreeViewColumn (_("Share"), gtk.CellRendererText (),
2324
 
+                                  text=0)
2325
 
+        col.set_resizable (True)
2326
 
+        col.set_sort_column_id (0)
2327
 
+        self.tvSMBBrowser.append_column (col)
2328
 
+
2329
 
+        col = gtk.TreeViewColumn (_("Comment"), gtk.CellRendererText (),
2330
 
+                                  text=1)
2331
 
+        self.tvSMBBrowser.append_column (col)
2332
 
+        slct = self.tvSMBBrowser.get_selection ()
2333
 
+        slct.set_select_function (self.smb_select_function)
2334
 
+
2335
 
+        self.SMBBrowseDialog.set_transient_for(self.NewPrinterWindow)
2336
 
+
2337
 
+        # IPP browser
2338
 
+        self.ipp_store = gtk.TreeStore (str, # queue
2339
 
+                                        str, # location
2340
 
+                                        gobject.TYPE_PYOBJECT) # dict
2341
 
+        self.tvIPPBrowser.set_model (self.ipp_store)
2342
 
+        self.ipp_store.set_sort_column_id (0, gtk.SORT_ASCENDING)
2343
 
+
2344
 
+        # IPP list columns
2345
 
+        col = gtk.TreeViewColumn (_("Queue"), gtk.CellRendererText (),
2346
 
+                                  text=0)
2347
 
+        col.set_resizable (True)
2348
 
+        col.set_sort_column_id (0)
2349
 
+        self.tvIPPBrowser.append_column (col)
2350
 
+
2351
 
+        col = gtk.TreeViewColumn (_("Location"), gtk.CellRendererText (),
2352
 
+                                  text=1)
2353
 
+        self.tvIPPBrowser.append_column (col)
2354
 
+        self.IPPBrowseDialog.set_transient_for(self.NewPrinterWindow)
2355
 
+
2356
 
+        self.tvNPDriversTooltips = TreeViewTooltips(self.tvNPDrivers, self.NPDriversTooltips)
2357
 
+
2358
 
+        ppd_filter = gtk.FileFilter()
2359
 
+        ppd_filter.set_name(_("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"))
2360
 
+        ppd_filter.add_pattern("*.ppd")
2361
 
+        ppd_filter.add_pattern("*.PPD")
2362
 
+        ppd_filter.add_pattern("*.ppd.gz")
2363
 
+        ppd_filter.add_pattern("*.PPD.gz")
2364
 
+        ppd_filter.add_pattern("*.PPD.GZ")
2365
 
+        self.filechooserPPD.add_filter(ppd_filter)
2366
 
+
2367
 
+        ppd_filter = gtk.FileFilter()
2368
 
+        ppd_filter.set_name(_("All files (*)"))
2369
 
+        ppd_filter.add_pattern("*")
2370
 
+        self.filechooserPPD.add_filter(ppd_filter)
2371
 
+
2372
 
+        self.xml.signal_autoconnect(self)
2373
 
+        """
2374
 
+
2375
 
+        #FIXME hide bits which are not yet implemented
2376
 
+        self.btnSMBBrowse.hide()
2377
 
+        self.btnSMBVerify.hide()
2378
 
+        self.btnNPTLpdProbe.hide()
2379
 
+
2380
 
+    def option_changed(self, option):
2381
 
+        if option.is_changed():
2382
 
+            self.changed.add(option)
2383
 
+        else:
2384
 
+            self.changed.discard(option)
2385
 
+
2386
 
+        if option.conflicts:
2387
 
+            self.conflicts.add(option)
2388
 
+        else:
2389
 
+            self.conflicts.discard(option)
2390
 
+        self.setDataButtonState()
2391
 
+
2392
 
+        return
2393
 
+
2394
 
+    def setDataButtonState(self):
2395
 
+        self.btnNPForward.setEnabled(not bool(self.conflicts))
2396
 
+
2397
 
+    def init(self, dialog_mode):
2398
 
+        self.dialog_mode = dialog_mode
2399
 
+        self.options = {} # keyword -> Option object
2400
 
+        self.changed = set()
2401
 
+        self.conflicts = set()
2402
 
+
2403
 
+        """
2404
 
+        combobox = self.cmbNPDownloadableDriverFoundPrinters
2405
 
+        combobox.set_model (gtk.ListStore (str, str))
2406
 
+        self.entNPDownloadableDriverSearch.set_text ('')
2407
 
+        button = self.btnNPDownloadableDriverSearch
2408
 
+        label = button.get_children ()[0].get_children ()[0].get_children ()[1]
2409
 
+        self.btnNPDownloadableDriverSearch_label = label
2410
 
+        label.set_text (_("Search"))
2411
 
+        """
2412
 
+
2413
 
+        if self.dialog_mode == "printer":
2414
 
+            self.setWindowTitle(i18n("New Printer"))
2415
 
+            # Start on devices page (1, not 0)
2416
 
+            self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages["device"])
2417
 
+            self.fillDeviceTab()
2418
 
+            self.on_rbtnNPFoomatic_toggled()
2419
 
+            # Start fetching information from CUPS in the background
2420
 
+            self.new_printer_PPDs_loaded = False
2421
 
+            self.queryPPDs ()
2422
 
+        elif self.dialog_mode == "class":
2423
 
+            self.setWindowTitle(i18n("New Class"))
2424
 
+            self.fillNewClassMembers()
2425
 
+            # Start on name page
2426
 
+            self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages["name"])
2427
 
+        elif self.dialog_mode == "device":
2428
 
+            self.setWindowTitle(i18n("Change Device URI"))
2429
 
+            self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages["device"])
2430
 
+            self.queryDevices ()
2431
 
+            self.loadPPDs()
2432
 
+            self.fillDeviceTab(self.mainapp.printer.device_uri)
2433
 
+            # Start fetching information from CUPS in the background
2434
 
+            self.new_printer_PPDs_loaded = False
2435
 
+            self.queryPPDs ()
2436
 
+        elif self.dialog_mode == "ppd":
2437
 
+            self.setWindowTitle(i18n("Change Driver"))
2438
 
+            self.ntbkNewPrinter.setCurrentIndex(2)
2439
 
+            self.on_rbtnNPFoomatic_toggled()
2440
 
+
2441
 
+            self.auto_model = ""
2442
 
+            ppd = self.mainapp.ppd
2443
 
+            if ppd:
2444
 
+                attr = ppd.findAttr("Manufacturer")
2445
 
+                if attr:
2446
 
+                    self.auto_make = attr.value
2447
 
+                else:
2448
 
+                    self.auto_make = ""
2449
 
+                attr = ppd.findAttr("ModelName")
2450
 
+                if not attr: attr = ppd.findAttr("ShortNickName")
2451
 
+                if not attr: attr = ppd.findAttr("NickName")
2452
 
+                if attr:
2453
 
+                    if attr.value.startswith(self.auto_make):
2454
 
+                        self.auto_model = attr.value[len(self.auto_make):].strip ()
2455
 
+                    else:
2456
 
+                        try:
2457
 
+                            self.auto_model = attr.value.split(" ", 1)[1]
2458
 
+                        except IndexError:
2459
 
+                            self.auto_model = ""
2460
 
+                else:
2461
 
+                    self.auto_model = ""
2462
 
+            else:
2463
 
+                # Special CUPS names for a raw queue.
2464
 
+                self.auto_make = 'Raw'
2465
 
+                self.auto_model = 'Queue'
2466
 
+
2467
 
+            self.loadPPDs ()
2468
 
+            self.fillMakeList()
2469
 
+
2470
 
+        if self.dialog_mode in ("printer", "class"):
2471
 
+            self.entNPName.setText (self.mainapp.makeNameUnique(self.dialog_mode))
2472
 
+            #FIXMEself.entNPName.grab_focus()
2473
 
+            for widget in [self.entNPLocation,
2474
 
+                           self.entNPDescription]: #,
2475
 
+                           #self.entSMBURI, self.entSMBUsername,
2476
 
+                           #self.entSMBPassword, self.entNPTDirectJetHostname]:
2477
 
+                widget.setText('')
2478
 
+
2479
 
+            try:
2480
 
+                p = os.popen ('/bin/hostname', 'r')
2481
 
+                hostname = p.read ().strip ()
2482
 
+                p.close ()
2483
 
+                self.entNPLocation.setText(hostname)
2484
 
+            except:
2485
 
+                nonfatalException ()
2486
 
+
2487
 
+        self.entNPTDirectJetPort.setText('9100')
2488
 
+        self.setNPButtons()
2489
 
+        self.exec_()
2490
 
+
2491
 
+    # get PPDs
2492
 
+
2493
 
+    def queryPPDs(self):
2494
 
+        debugprint ("queryPPDs")
2495
 
+        if not self.ppds_lock.acquire(0):
2496
 
+            debugprint ("queryPPDs: in progress")
2497
 
+            return
2498
 
+        debugprint ("Lock acquired for PPDs thread")
2499
 
+
2500
 
+        self.getPPDs_thread(self.language[0])
2501
 
+        debugprint ("PPDs thread started")
2502
 
+
2503
 
+    def getPPDs_thread(self, language):
2504
 
+        try:
2505
 
+            debugprint ("Connecting (PPDs)")
2506
 
+            cups.setServer (self.mainapp.connect_server)
2507
 
+            cups.setUser (self.mainapp.connect_user)
2508
 
+            cups.setPasswordCB (self.mainapp.cupsPasswdCallback)
2509
 
+            # cups.setEncryption (...)
2510
 
+            c = cups.Connection ()
2511
 
+            debugprint ("Fetching PPDs")
2512
 
+            ppds_dict = c.getPPDs()
2513
 
+            self.ppds_result = cupshelpers.ppds.PPDs(ppds_dict,
2514
 
+                                                     language=language)
2515
 
+            debugprint ("Closing connection (PPDs)")
2516
 
+            del c
2517
 
+        except cups.IPPError, (e, msg):
2518
 
+            self.ppds_result = cups.IPPError (e, msg)
2519
 
+        except:
2520
 
+            nonfatalException()
2521
 
+            self.ppds_result = { }
2522
 
+
2523
 
+        debugprint ("Releasing PPDs lock")
2524
 
+        self.ppds_lock.release ()
2525
 
+
2526
 
+    def fetchPPDs(self, parent=None):
2527
 
+        debugprint ("fetchPPDs")
2528
 
+        self.queryPPDs()
2529
 
+        time.sleep (0.1)
2530
 
+
2531
 
+        # Keep the UI refreshed while we wait for the devices to load.
2532
 
+        waiting = False
2533
 
+        while (self.ppds_lock.locked()):
2534
 
+            if not waiting:
2535
 
+                waiting = True
2536
 
+                self.WaitWindow.setText(i18n('<b>Searching</b>') + '<br /><br />' +
2537
 
+                                         i18n('Searching for drivers'))
2538
 
+                self.WaitWindow.show ()
2539
 
+
2540
 
+            KApplication.processEvents()
2541
 
+
2542
 
+            time.sleep (0.1)
2543
 
+
2544
 
+        if waiting:
2545
 
+            self.WaitWindow.hide ()
2546
 
+
2547
 
+        debugprint ("Got PPDs")
2548
 
+        result = self.ppds_result # atomic operation
2549
 
+        if isinstance (result, cups.IPPError):
2550
 
+            # Propagate exception.
2551
 
+            raise result
2552
 
+        return result
2553
 
+
2554
 
+    def loadPPDs(self, parent=None):
2555
 
+        try:
2556
 
+            return self.ppds
2557
 
+        except:
2558
 
+            self.ppds = self.fetchPPDs (parent=parent)
2559
 
+            return self.ppds
2560
 
+
2561
 
+    def dropPPDs(self):
2562
 
+        try:
2563
 
+            del self.ppds
2564
 
+        except:
2565
 
+            pass
2566
 
+
2567
 
+    # Class members
2568
 
+
2569
 
+    def fillNewClassMembers(self):
2570
 
+        self.tvNCMembers.clear()
2571
 
+        self.tvNCNotMembers.clear()
2572
 
+        for printer in self.mainapp.printers.itervalues():
2573
 
+            self.tvNCNotMembers.addItem(printer.name)
2574
 
+
2575
 
+    @pyqtSignature("")
2576
 
+    def on_btnNCAddMember_clicked(self):
2577
 
+        self.mainapp.moveClassMembers(self.tvNCNotMembers, self.tvNCMembers)
2578
 
+        self.btnNPApply.setEnabled(
2579
 
+            bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
2580
 
+
2581
 
+    @pyqtSignature("")
2582
 
+    def on_btnNCDelMember_clicked(self):
2583
 
+        self.mainapp.moveClassMembers(self.tvNCMembers, self.tvNCNotMembers)
2584
 
+        self.btnNPApply.setEnabled(
2585
 
+            bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
2586
 
+
2587
 
+    @pyqtSignature("")
2588
 
+    def on_btnNPBack_clicked(self):
2589
 
+        self.nextNPTab(-1)
2590
 
+
2591
 
+    @pyqtSignature("")
2592
 
+    def on_btnNPForward_clicked(self):
2593
 
+        self.nextNPTab()
2594
 
+
2595
 
+    def nextNPTab(self, step=1):
2596
 
+        self.setCursor(Qt.WaitCursor)
2597
 
+        page_nr = self.ntbkNewPrinter.currentIndex()
2598
 
+
2599
 
+        if self.dialog_mode == "class":
2600
 
+            #order = [0, 4, 5]
2601
 
+            order = [self.ntbkNewPrinterPages["name"], self.ntbkNewPrinterPages["class-members"]]
2602
 
+        elif self.dialog_mode == "printer":
2603
 
+            if page_nr == 1: # Device (first page)
2604
 
+                # Choose an appropriate name.
2605
 
+                name = 'printer'
2606
 
+                try:
2607
 
+                    if self.device.id:
2608
 
+                        name = self.device.id_dict["MDL"]
2609
 
+                    name = self.mainapp.makeNameUnique (name)
2610
 
+                    self.entNPName.setText(name)
2611
 
+                except:
2612
 
+                    nonfatalException ()
2613
 
+                self.auto_make, self.auto_model = None, None
2614
 
+                self.device.uri = self.getDeviceURI()
2615
 
+                if self.device.type in ("socket", "lpd", "ipp", "bluetooth"):
2616
 
+                    host = self.getNetworkPrinterMakeModel(self.device)
2617
 
+                    faxuri = None
2618
 
+                    if host:
2619
 
+                        faxuri = self.get_hplip_uri_for_network_printer(host,
2620
 
+                                                                        "fax")
2621
 
+                    if faxuri:
2622
 
+                        #create message string
2623
 
+                        q = i18n("This printer supports both "
2624
 
+                                            "printing and sending faxes.  "
2625
 
+                                            "Which functionality should be "
2626
 
+                                            "used for this queue?")
2627
 
+                        
2628
 
+                        #buttons need to be KGuiItem objects
2629
 
+                        printer_button = KGuiItem(i18n("Printer"))
2630
 
+                        fax_button = KGuiItem(i18n("Fax"))
2631
 
+
2632
 
+                        #This is a bit hackish. Essentially Printer is mapped to the Yes button, Fax to
2633
 
+                        #the No button. KMessageBox doesn't seem to provide a version for 'This OR That'
2634
 
+                        queue_type = KMessageBox.questionYesNo(self.NewPrinterWindow, q , 'Choose function', printer_button, fax_button)
2635
 
+
2636
 
+                        #test return value of messagebox Printer == 3, Fax == 4
2637
 
+                        if (queue_type == 3): 
2638
 
+                            self.device.id_dict = \
2639
 
+                               self.get_hpfax_device_id(faxuri)
2640
 
+                            self.device.uri = faxuri
2641
 
+                            self.auto_make = self.device.id_dict["MFG"]
2642
 
+                            self.auto_model = self.device.id_dict["MDL"]
2643
 
+                            self.device.id = "MFG:" + self.auto_make + \
2644
 
+                                             ";MDL:" + self.auto_model + \
2645
 
+                                             ";DES:" + \
2646
 
+                                             self.device.id_dict["DES"] + ";"
2647
 
+                uri = self.device.uri
2648
 
+                if uri and uri.startswith ("smb://"):
2649
 
+                    uri = SMBURI (uri=uri[6:]).sanitize_uri ()
2650
 
+
2651
 
+                # Try to access the PPD, in this case our detected IPP
2652
 
+                # printer is a queue on a remote CUPS server which is
2653
 
+                # not automatically set up on our local CUPS server
2654
 
+                # (for example DNS-SD broadcasted queue from Mac OS X)
2655
 
+                self.remotecupsqueue = None
2656
 
+                res = re.search ("ipp://(\S+(:\d+|))/printers/(\S+)", uri)
2657
 
+                if res:
2658
 
+                    resg = res.groups()
2659
 
+                    try:
2660
 
+                        conn = httplib.HTTPConnection(resg[0])
2661
 
+                        conn.request("GET", "/printers/%s.ppd" % resg[2])
2662
 
+                        resp = conn.getresponse()
2663
 
+                        if resp.status == 200: self.remotecupsqueue = resg[2]
2664
 
+                    except:
2665
 
+                        debugprint("exception in getting remotecupsqueue")
2666
 
+                        pass
2667
 
+
2668
 
+                    # We also want to fetch the printer-info and
2669
 
+                    # printer-location attributes, to pre-fill those
2670
 
+                    # fields for this new queue.
2671
 
+                    oldserver = cups.getServer()
2672
 
+                    oldport = cups.getPort()
2673
 
+                    try:
2674
 
+                        cups.setServer (resg[0])
2675
 
+                        if len (resg[1]) > 0:
2676
 
+                            cups.setPort (int (resg[1]))
2677
 
+                        else:
2678
 
+                            cups.setPort (631)
2679
 
+
2680
 
+                        c = cups.Connection ()
2681
 
+                        r = ['printer-info', 'printer-location']
2682
 
+                        attrs = c.getPrinterAttributes (uri=uri,
2683
 
+                                                        requested_attributes=r)
2684
 
+                        info = attrs.get ('printer-info', '')
2685
 
+                        location = attrs.get ('printer-location', '')
2686
 
+                        if len (info) > 0:
2687
 
+                            self.entNPDescription.setText(info)
2688
 
+                        if len (location) > 0:
2689
 
+                            self.entNPLocation.setText(location)
2690
 
+                    except:
2691
 
+                        nonfatalException ()
2692
 
+
2693
 
+                    cups.setServer (oldserver)
2694
 
+                    cups.setPort (oldport)
2695
 
+
2696
 
+                if (not self.remotecupsqueue and
2697
 
+                    not self.new_printer_PPDs_loaded):
2698
 
+                    try:
2699
 
+                        self.loadPPDs(self)
2700
 
+                    except cups.IPPError, (e, msg):
2701
 
+                        #self.ready (self)
2702
 
+                        self.show_IPP_Error(e, msg)
2703
 
+                        return
2704
 
+                    except:
2705
 
+                        self.ready (self)
2706
 
+                        return
2707
 
+                    self.new_printer_PPDs_loaded = True
2708
 
+
2709
 
+                ppdname = None
2710
 
+                try:
2711
 
+                    if self.remotecupsqueue:
2712
 
+                        # We have a remote CUPS queue, let the client queue
2713
 
+                        # stay raw so that the driver on the server gets used
2714
 
+                        ppdname = 'raw'
2715
 
+                        self.ppd = ppdname
2716
 
+                        name = self.remotecupsqueue
2717
 
+                        name = self.mainapp.makeNameUnique (name)
2718
 
+                        self.entNPName.setText(name)
2719
 
+                    elif self.device.id:
2720
 
+                        id_dict = self.device.id_dict
2721
 
+                        (status, ppdname) = self.ppds.\
2722
 
+                            getPPDNameFromDeviceID (id_dict["MFG"],
2723
 
+                                                    id_dict["MDL"],
2724
 
+                                                    id_dict["DES"],
2725
 
+                                                    id_dict["CMD"],
2726
 
+                                                    self.device.uri)
2727
 
+                    else:
2728
 
+                        (status, ppdname) = self.ppds.\
2729
 
+                            getPPDNameFromDeviceID ("Generic",
2730
 
+                                                    "Printer",
2731
 
+                                                    "Generic Printer",
2732
 
+                                                    [],
2733
 
+                                                    self.device.uri)
2734
 
+
2735
 
+                    if ppdname and not self.remotecupsqueue:
2736
 
+                        ppddict = self.ppds.getInfoFromPPDName (ppdname)
2737
 
+                        make_model = ppddict['ppd-make-and-model']
2738
 
+                        (make, model) = \
2739
 
+                            cupshelpers.ppds.ppdMakeModelSplit (make_model)
2740
 
+                        self.auto_make = make
2741
 
+                        self.auto_model = model
2742
 
+                except:
2743
 
+                    nonfatalException ()
2744
 
+                if not self.remotecupsqueue:
2745
 
+                    self.fillMakeList()
2746
 
+            elif page_nr == 3: # Model has been selected
2747
 
+                if not self.device.id:
2748
 
+                    # Choose an appropriate name when no Device ID
2749
 
+                    # is available, based on the model the user has
2750
 
+                    # selected.
2751
 
+                    try:
2752
 
+                        items = self.tvNPModels.selectedItems()
2753
 
+                        name = unicode(items[0].text())
2754
 
+                        name = self.mainapp.makeNameUnique (name)
2755
 
+                        self.entNPName.setText(name)
2756
 
+                    except:
2757
 
+                        nonfatalException ()
2758
 
+
2759
 
+            ##self.ready (self.NewPrinterWindow)
2760
 
+            if self.remotecupsqueue:
2761
 
+                order = [1, 0]
2762
 
+            elif self.rbtnNPFoomatic.isChecked():
2763
 
+                order = [1, 2, 3, 6, 0]
2764
 
+            elif self.rbtnNPPPD.isChecked():
2765
 
+                order = [1, 2, 6, 0]
2766
 
+            else:
2767
 
+                # Downloadable driver
2768
 
+                order = [1, 2, 7, 6, 0]
2769
 
+        elif self.dialog_mode == "device":
2770
 
+            order = [1]
2771
 
+        elif self.dialog_mode == "ppd":
2772
 
+            self.rbtnChangePPDasIs.setChecked(True)
2773
 
+            if self.rbtnNPFoomatic.isChecked():
2774
 
+                order = [2, 3, 5, 6]
2775
 
+            elif self.rbtnNPPPD.isChecked():
2776
 
+                order = [2, 5, 6]
2777
 
+            else:
2778
 
+                # Downloadable driver
2779
 
+                order = [2, 7, 5, 6]
2780
 
+
2781
 
+        next_page_nr = order[order.index(page_nr)+step]
2782
 
+
2783
 
+        # fill Installable Options tab
2784
 
+        if next_page_nr == 6 and step > 0:
2785
 
+            #TODO Prepare Installable Options screen.
2786
 
+            self.ppd = self.getNPPPD()
2787
 
+            """FIXME todo
2788
 
+            if next_page_nr == 6:
2789
 
+                # Prepare Installable Options screen.
2790
 
+                if isinstance(self.ppd, cups.PPD):
2791
 
+                    self.fillNPInstallableOptions()
2792
 
+                else:
2793
 
+                    self.installable_options = None
2794
 
+                    # Put a label there explaining why the page is empty.
2795
 
+                    ppd = self.ppd
2796
 
+                    self.ppd = None
2797
 
+                    self.fillNPInstallableOptions()
2798
 
+                    self.ppd = ppd
2799
 
+
2800
 
+                # step over if empty and not in PPD mode
2801
 
+                if self.dialog_mode != "ppd" and not self.installable_options:
2802
 
+                    next_page_nr = order[order.index(next_page_nr)+1]
2803
 
+            """
2804
 
+            next_page_nr = order[order.index(next_page_nr)+1]
2805
 
+        self.installable_options = False
2806
 
+        # Step over empty Installable Options tab
2807
 
+        if next_page_nr == 6 and not self.installable_options and step<0:
2808
 
+            next_page_nr = order[order.index(next_page_nr)-1]
2809
 
+
2810
 
+        if next_page_nr == 7: # About to show downloadable drivers
2811
 
+            if self.drivers_lock.locked ():
2812
 
+                # Still searching for drivers.
2813
 
+                self.lblWait.set_markup ('<span size="larger">' +
2814
 
+                                         i18n('<b>Searching</b>') + '</span>\n\n' +
2815
 
+                                         i18n('Searching for drivers'))
2816
 
+                self.WaitWindow.set_transient_for (self.NewPrinterWindow)
2817
 
+                self.WaitWindow.show ()
2818
 
+
2819
 
+                # Keep the UI refreshed while we wait for the drivers
2820
 
+                # query to complete.
2821
 
+                while self.drivers_lock.locked ():
2822
 
+                    self.mainapp.busy(self)
2823
 
+                    time.sleep (0.1)
2824
 
+
2825
 
+                self.ready (self.NewPrinterWindow)
2826
 
+                self.WaitWindow.hide ()
2827
 
+
2828
 
+            self.fillDownloadableDrivers()
2829
 
+
2830
 
+        self.ntbkNewPrinter.setCurrentIndex(next_page_nr)
2831
 
+
2832
 
+        self.setNPButtons()
2833
 
+        self.setCursor(Qt.ArrowCursor)
2834
 
+
2835
 
+    def setNPButtons(self):
2836
 
+        nr = self.ntbkNewPrinter.currentIndex()
2837
 
+
2838
 
+        if self.dialog_mode == "device":
2839
 
+            self.btnNPBack.hide()
2840
 
+            self.btnNPForward.hide()
2841
 
+            self.btnNPApply.show()
2842
 
+            uri = self.getDeviceURI ()
2843
 
+            self.btnNPApply.setEnabled(validDeviceURI (uri))
2844
 
+            return
2845
 
+
2846
 
+        if self.dialog_mode == "ppd":
2847
 
+            if nr == 5: # Apply
2848
 
+                if not self.installable_options:
2849
 
+                    # There are no installable options, so this is the
2850
 
+                    # last page.
2851
 
+                    debugprint ("No installable options")
2852
 
+                    self.btnNPForward.hide ()
2853
 
+                    self.btnNPApply.show ()
2854
 
+                else:
2855
 
+                    self.btnNPForward.show ()
2856
 
+                    self.btnNPApply.hide ()
2857
 
+                return
2858
 
+            elif nr == 6:
2859
 
+                self.btnNPForward.hide()
2860
 
+                self.btnNPApply.show()
2861
 
+                return
2862
 
+            else:
2863
 
+                self.btnNPForward.show()
2864
 
+                self.btnNPApply.hide()
2865
 
+            if nr == 2:
2866
 
+                self.btnNPBack.hide()
2867
 
+                self.btnNPForward.show()
2868
 
+                downloadable_selected = False
2869
 
+                if self.rbtnNPDownloadableDriverSearch.isChecked():
2870
 
+                    combobox = self.cmbNPDownloadableDriverFoundPrinters
2871
 
+                    iter = combobox.get_active_iter () #FIXME
2872
 
+                    if iter and combobox.get_model ().get_value (iter, 1):
2873
 
+                        downloadable_selected = True
2874
 
+
2875
 
+                self.btnNPForward.setEnabled(bool(
2876
 
+                        self.rbtnNPFoomatic.isChecked() or
2877
 
+                        not self.filechooserPPD.text().isEmpty() or
2878
 
+                        downloadable_selected))
2879
 
+                return
2880
 
+            else:
2881
 
+                self.btnNPBack.show()
2882
 
+
2883
 
+        # class/printer
2884
 
+
2885
 
+        if nr == 1: # Device
2886
 
+            valid = False
2887
 
+            try:
2888
 
+                uri = self.getDeviceURI ()
2889
 
+                valid = validDeviceURI (uri)
2890
 
+            except:
2891
 
+                pass
2892
 
+            self.btnNPForward.setEnabled(valid)
2893
 
+            self.btnNPBack.hide ()
2894
 
+        else:
2895
 
+            self.btnNPBack.show()
2896
 
+
2897
 
+        self.btnNPForward.show()
2898
 
+        self.btnNPApply.hide()
2899
 
+
2900
 
+        if nr == 0: # Name
2901
 
+            self.btnNPBack.show()
2902
 
+            if self.dialog_mode == "class":
2903
 
+                self.btnNPForward.setEnabled(True)
2904
 
+            if self.dialog_mode == "printer":
2905
 
+                self.btnNPForward.hide()
2906
 
+                self.btnNPApply.show()
2907
 
+                self.btnNPApply.setEnabled(
2908
 
+                    self.mainapp.checkNPName(unicode(self.entNPName.text())))
2909
 
+        if nr == 2: # Make/PPD file
2910
 
+            downloadable_selected = False
2911
 
+            if self.rbtnNPDownloadableDriverSearch.isChecked():
2912
 
+                combobox = self.cmbNPDownloadableDriverFoundPrinters
2913
 
+                iter = combobox.get_active_iter () #FIXME
2914
 
+                if iter and combobox.get_model ().get_value (iter, 1):
2915
 
+                    downloadable_selected = True
2916
 
+
2917
 
+            self.btnNPForward.setEnabled(bool(
2918
 
+                self.rbtnNPFoomatic.isChecked() or
2919
 
+                not self.filechooserPPD.text().isEmpty() or
2920
 
+                downloadable_selected))
2921
 
+        
2922
 
+        if nr == 3: # Model/Driver
2923
 
+            iter = self.tvNPDrivers.currentItem()
2924
 
+            self.btnNPForward.setEnabled(bool(iter))
2925
 
+        if nr == 4: # Class Members
2926
 
+            self.btnNPForward.hide()
2927
 
+            self.btnNPApply.show()
2928
 
+            self.btnNPApply.setEnabled(self.tvNCMembers.count() > 0)
2929
 
+        if nr == 7: # Downloadable drivers
2930
 
+            if self.ntbkNPDownloadableDriverProperties.get_current_page() == 1: #FIXME
2931
 
+                accepted = self.rbtnNPDownloadLicenseYes.get_active ()
2932
 
+            else:
2933
 
+                treeview = self.tvNPDownloadableDrivers
2934
 
+                model, iter = treeview.get_selection ().get_selected ()
2935
 
+                accepted = (iter != None)
2936
 
+
2937
 
+            self.btnNPForward.set_sensitive(accepted)
2938
 
+    
2939
 
+    def on_filechooserPPDButton(self):
2940
 
+        home = QDir.homePath()
2941
 
+        url = KUrl.fromPath(home)
2942
 
+        filename = KFileDialog.getOpenFileName(url, '*.ppd', self)
2943
 
+        self.filechooserPPD.setText(filename)
2944
 
+        self.btnNPForward.setEnabled(True)
2945
 
+
2946
 
+    def getDevices_thread(self):
2947
 
+        try:
2948
 
+            debugprint ("Connecting (devices)")
2949
 
+            cups.setServer (self.mainapp.connect_server)
2950
 
+            #cups.setUser (self.mainapp.connect_user)
2951
 
+            cups.setUser ("jr")
2952
 
+            cups.setPasswordCB (self.mainapp.cupsPasswdCallback)
2953
 
+            # cups.setEncryption (...)
2954
 
+            c = cups.Connection ()
2955
 
+            debugprint ("Fetching devices")
2956
 
+            self.devices_result = cupshelpers.getDevices(c)
2957
 
+        except cups.IPPError, (e, msg):
2958
 
+            self.devices_result = cups.IPPError (e, msg)
2959
 
+        except:
2960
 
+            debugprint ("Exception in getDevices_thread")
2961
 
+            self.devices_result = {}
2962
 
+
2963
 
+        try:
2964
 
+            debugprint ("Closing connection (devices)")
2965
 
+            del c
2966
 
+        except:
2967
 
+            pass
2968
 
+
2969
 
+        debugprint ("Releasing devices lock")
2970
 
+        self.devices_lock.release ()
2971
 
+
2972
 
+
2973
 
+    # Device URI
2974
 
+    def queryDevices(self):
2975
 
+        if not self.devices_lock.acquire(0):
2976
 
+            debugprint ("queryDevices: in progress")
2977
 
+            return
2978
 
+        debugprint ("Lock acquired for devices thread")
2979
 
+        self.getDevices_thread()
2980
 
+        debugprint ("Devices thread started")
2981
 
+
2982
 
+    def fetchDevices(self, parent=None):
2983
 
+        debugprint ("fetchDevices")
2984
 
+        self.queryDevices ()
2985
 
+        time.sleep (0.1)
2986
 
+
2987
 
+        # Keep the UI refreshed while we wait for the devices to load.
2988
 
+        waiting = False
2989
 
+        #crashes kcm here as soon as this loop exits
2990
 
+        while (self.devices_lock.locked()):
2991
 
+            if not waiting:
2992
 
+                waiting = True
2993
 
+                self.WaitWindow.setText (i18n('<b>Searching</b>') + '<br/><br/>' +
2994
 
+                                         i18n('Searching for printers'))
2995
 
+                if not parent:
2996
 
+                   parent = self.mainapp
2997
 
+                self.WaitWindow.show ()
2998
 
+            
2999
 
+            KApplication.processEvents()
3000
 
+
3001
 
+            time.sleep (0.1)
3002
 
+        
3003
 
+        #if waiting:
3004
 
+            #self.WaitWindow.hide()
3005
 
+
3006
 
+        debugprint ("Got devices")
3007
 
+        
3008
 
+        result = self.devices_result # atomic operation
3009
 
+
3010
 
+        if isinstance (result, cups.IPPError):
3011
 
+            # Propagate exception.
3012
 
+            raise result
3013
 
+        return result
3014
 
+
3015
 
+    def get_hpfax_device_id(self, faxuri):
3016
 
+        os.environ["URI"] = faxuri
3017
 
+        cmd = 'LC_ALL=C DISPLAY= hp-info -d "${URI}"'
3018
 
+        debugprint (faxuri + ": " + cmd)
3019
 
+        try:
3020
 
+            p = subprocess.Popen (cmd, shell=True,
3021
 
+                                  stdin=file("/dev/null"),
3022
 
+                                  stdout=subprocess.PIPE,
3023
 
+                                  stderr=subprocess.PIPE)
3024
 
+            (stdout, stderr) = p.communicate ()
3025
 
+        except:
3026
 
+            # Problem executing command.
3027
 
+            return None
3028
 
+
3029
 
+        for line in stdout.split ("\n"):
3030
 
+            if line.find ("fax-type") == -1:
3031
 
+                continue
3032
 
+            faxtype = -1
3033
 
+            res = re.search ("(\d+)", line)
3034
 
+            if res:
3035
 
+                resg = res.groups()
3036
 
+                faxtype = resg[0]
3037
 
+            if faxtype >= 0: break
3038
 
+        if faxtype < 0:
3039
 
+            return None
3040
 
+        elif faxtype == 4:
3041
 
+            return cupshelpers.parseDeviceID ('MFG:HP;MDL:Fax 2;DES:HP Fax 2;')
3042
 
+        else:
3043
 
+            return cupshelpers.parseDeviceID ('MFG:HP;MDL:Fax;DES:HP Fax;')
3044
 
+
3045
 
+    def get_hplip_uri_for_network_printer(self, host, mode):
3046
 
+        os.environ["HOST"] = host
3047
 
+        if mode == "print": mod = "-c"
3048
 
+        elif mode == "fax": mod = "-f"
3049
 
+        else: mod = "-c"
3050
 
+        cmd = 'hp-makeuri ' + mod + ' "${HOST}"'
3051
 
+        debugprint (host + ": " + cmd)
3052
 
+        uri = None
3053
 
+        try:
3054
 
+            p = subprocess.Popen (cmd, shell=True,
3055
 
+                                  stdin=file("/dev/null"),
3056
 
+                                  stdout=subprocess.PIPE,
3057
 
+                                  stderr=subprocess.PIPE)
3058
 
+            (stdout, stderr) = p.communicate ()
3059
 
+        except:
3060
 
+            # Problem executing command.
3061
 
+            return None
3062
 
+
3063
 
+        uri = stdout.strip ()
3064
 
+        return uri
3065
 
+
3066
 
+    def getNetworkPrinterMakeModel(self, device):
3067
 
+        # Determine host name/IP
3068
 
+        host = None
3069
 
+        s = device.uri.find ("://")
3070
 
+        if s != -1:
3071
 
+            s += 3
3072
 
+            e = device.uri[s:].find (":")
3073
 
+            if e == -1: e = device.uri[s:].find ("/")
3074
 
+            if e == -1: e = device.uri[s:].find ("?")
3075
 
+            if e == -1: e = len (device.uri)
3076
 
+            host = device.uri[s:s+e]
3077
 
+        # Try to get make and model via SNMP
3078
 
+        if host:
3079
 
+            os.environ["HOST"] = host
3080
 
+            cmd = '/usr/lib/cups/backend/snmp "${HOST}"'
3081
 
+            debugprint (host + ": " + cmd)
3082
 
+            stdout = None
3083
 
+            try:
3084
 
+                p = subprocess.Popen (cmd, shell=True,
3085
 
+                                      stdin=file("/dev/null"),
3086
 
+                                      stdout=subprocess.PIPE,
3087
 
+                                      stderr=subprocess.PIPE)
3088
 
+                (stdout, stderr) = p.communicate ()
3089
 
+            except:
3090
 
+                # Problem executing command.
3091
 
+                pass
3092
 
+
3093
 
+            if stdout != None:
3094
 
+                mm = re.sub("^\s*\S+\s+\S+\s+\"", "", stdout)
3095
 
+                mm = re.sub("\"\s+.*$", "", mm)
3096
 
+                if mm and mm != "": device.make_and_model = mm
3097
 
+        # Extract make and model and create a pseudo device ID, so
3098
 
+        # that a PPD/driver can be assigned to the device
3099
 
+        make_and_model = None
3100
 
+        if len (device.make_and_model) > 7:
3101
 
+            make_and_model = device.make_and_model
3102
 
+        elif len (device.info) > 7:
3103
 
+            make_and_model = device.info
3104
 
+            make_and_model = re.sub("\s*(\(|\d+\.\d+\.\d+\.\d+).*$", "", make_and_model)
3105
 
+        if make_and_model and not device.id:
3106
 
+            mk = None
3107
 
+            md = None
3108
 
+            (mk, md) = cupshelpers.ppds.ppdMakeModelSplit (make_and_model)
3109
 
+            device.id = "MFG:" + mk + ";MDL:" + md + ";DES:" + mk + " " + md + ";"
3110
 
+            device.id_dict = cupshelpers.parseDeviceID (device.id)
3111
 
+        # Check whether the device is supported by HPLIP and replace
3112
 
+        # its URI by an HPLIP URI
3113
 
+        if host:
3114
 
+            hplipuri = self.get_hplip_uri_for_network_printer(host, "print")
3115
 
+            if hplipuri:
3116
 
+                device.uri = hplipuri
3117
 
+                s = hplipuri.find ("/usb/")
3118
 
+                if s == -1: s = hplipuri.find ("/par/")
3119
 
+                if s == -1: s = hplipuri.find ("/net/")
3120
 
+                if s != -1:
3121
 
+                    s += 5
3122
 
+                    e = hplipuri[s:].find ("?")
3123
 
+                    if e == -1: e = len (hplipuri)
3124
 
+                    mdl = hplipuri[s:s+e].replace ("_", " ")
3125
 
+                    if mdl.startswith ("hp ") or mdl.startswith ("HP "):
3126
 
+                        mdl = mdl[3:]
3127
 
+                        device.make_and_model = "HP " + mdl
3128
 
+                        device.id = "MFG:HP;MDL:" + mdl + ";DES:HP " + mdl + ";"
3129
 
+                        device.id_dict = cupshelpers.parseDeviceID (device.id)
3130
 
+        # Return the host name/IP for further actions
3131
 
+        return host
3132
 
+
3133
 
+    def fillDeviceTab(self, current_uri=None, query=True):
3134
 
+        if query:
3135
 
+            try:
3136
 
+                devices = self.fetchDevices()
3137
 
+            except cups.IPPError, (e, msg):
3138
 
+                self.show_IPP_Error(e, msg)
3139
 
+                devices = {}
3140
 
+            except:
3141
 
+                nonfatalException()
3142
 
+                devices = {}
3143
 
+
3144
 
+            if current_uri:
3145
 
+                if devices.has_key (current_uri):
3146
 
+                    current = devices.pop(current_uri)
3147
 
+                else:
3148
 
+                    current = cupshelpers.Device (current_uri)
3149
 
+                    current.info = "Current device"
3150
 
+
3151
 
+            self.devices = devices.values()
3152
 
+
3153
 
+        for device in self.devices:
3154
 
+            if device.type == "usb":
3155
 
+                # Find USB URIs with corresponding HPLIP URIs and mark them
3156
 
+                # for deleting, so that the user will only get the HPLIP
3157
 
+                # URIs for full device support in the list
3158
 
+                ser = None
3159
 
+                s = device.uri.find ("?serial=")
3160
 
+                if s != -1:
3161
 
+                    s += 8
3162
 
+                    e = device.uri[s:].find ("?")
3163
 
+                    if e == -1: e = len (device.uri)
3164
 
+                    ser = device.uri[s:s+e]
3165
 
+                mod = None
3166
 
+                s = device.uri[6:].find ("/")
3167
 
+                if s != -1:
3168
 
+                    s += 7
3169
 
+                    e = device.uri[s:].find ("?")
3170
 
+                    if e == -1: e = len (device.uri)
3171
 
+                    mod = device.uri[s:s+e].lower ().replace ("%20", "_")
3172
 
+                    if mod.startswith ("hp_"):
3173
 
+                        mod = mod[3:]
3174
 
+                matchfound = 0
3175
 
+                for hpdevice in self.devices:
3176
 
+                    hpser = None
3177
 
+                    hpmod = None
3178
 
+                    uri = hpdevice.uri
3179
 
+                    if not uri.startswith ("hp:"): continue
3180
 
+                    if ser:
3181
 
+                        s = uri.find ("?serial=")
3182
 
+                        if s != -1:
3183
 
+                            s += 8
3184
 
+                            e = uri[s:].find ("?")
3185
 
+                            if e == -1: e = len (uri)
3186
 
+                            hpser = uri[s:s+e]
3187
 
+                            if hpser != ser: continue
3188
 
+                            matchfound = 1
3189
 
+                    if mod and not (ser and hpser):
3190
 
+                        s = uri.find ("/usb/")
3191
 
+                        if s != -1:
3192
 
+                            s += 5
3193
 
+                            e = uri[s:].find ("?")
3194
 
+                            if e == -1: e = len (uri)
3195
 
+                            hpmod = uri[s:s+e].lower ()
3196
 
+                            if hpmod.startswith ("hp_"):
3197
 
+                                hpmod = hpmod[3:]
3198
 
+                            if hpmod != mod: continue
3199
 
+                            matchfound = 1
3200
 
+                    if matchfound == 1: break
3201
 
+                if matchfound == 1:
3202
 
+                    device.uri = "delete"
3203
 
+            if device.type == "hal":
3204
 
+                # Remove HAL USB URIs, for these printers there are already
3205
 
+                # USB URIs
3206
 
+                if device.uri.startswith("hal:///org/freedesktop/Hal/devices/usb_device"):
3207
 
+                    device.uri = "delete"
3208
 
+            if device.type == "socket":
3209
 
+                # Remove default port to more easily find duplicate URIs
3210
 
+                device.uri = device.uri.replace (":9100", "")
3211
 
+            try:
3212
 
+                ## XXX This needs to be moved to *after* the device is
3213
 
+                # selected.  Looping through all the network printers like
3214
 
+                # this is far too slow.
3215
 
+                if False and device.type in ("socket", "lpd", "ipp", "bluetooth"):
3216
 
+                    host = self.getNetworkPrinterMakeModel(device)
3217
 
+                    faxuri = None
3218
 
+                    if host:
3219
 
+                        faxuri = self.get_hplip_uri_for_network_printer(host,
3220
 
+                                                                        "fax")
3221
 
+                    if faxuri:
3222
 
+                        self.devices.append(cupshelpers.Device(faxuri,
3223
 
+                              **{'device-class' : "direct",
3224
 
+                                 'device-info' : device.info + " HP Fax HPLIP",
3225
 
+                                 'device-device-make-and-model' : "HP Fax",
3226
 
+                                 'device-id' : "MFG:HP;MDL:Fax;DES:HP Fax;"}))
3227
 
+                    if device.uri.startswith ("hp:"):
3228
 
+                        device.type = "hp" 
3229
 
+                        device.info += (" HPLIP")
3230
 
+            except:
3231
 
+                nonfatalException ()
3232
 
+        # Mark duplicate URIs for deletion
3233
 
+        for i in range (len (self.devices)):
3234
 
+            for j in range (len (self.devices)):
3235
 
+                if i == j: continue
3236
 
+                device1 = self.devices[i]
3237
 
+                device2 = self.devices[j]
3238
 
+                if device1.uri == "delete" or device2.uri == "delete":
3239
 
+                    continue
3240
 
+                if device1.uri == device2.uri:
3241
 
+                    # Keep the one with the longer (better) device ID
3242
 
+                    if (not device1.id):
3243
 
+                        device1.uri = "delete"
3244
 
+                    elif (not device2.id):
3245
 
+                        device2.uri = "delete"
3246
 
+                    elif (len (device1.id) < len (device2.id)):
3247
 
+                        device1.uri = "delete"
3248
 
+                    else:
3249
 
+                        device2.uri = "delete"
3250
 
+        self.devices = filter(lambda x: x.uri not in ("hp:/no_device_found",
3251
 
+                                                      "hpfax:/no_device_found",
3252
 
+                                                      "hp", "hpfax",
3253
 
+                                                      "hal", "beh",
3254
 
+                                                      "scsi", "http", "delete"),
3255
 
+                              self.devices)
3256
 
+        self.devices.sort()
3257
 
+
3258
 
+        self.devices.append(cupshelpers.Device('',
3259
 
+             **{'device-info' :i18nc("Other device", "Other")}))
3260
 
+        if current_uri:
3261
 
+            current.info = i18nc("Current device", "%1 (Current)", current.info)
3262
 
+            self.devices.insert(0, current)
3263
 
+            self.device = current
3264
 
+        self.tvNPDevices.clear()
3265
 
+
3266
 
+        for device in self.devices:
3267
 
+            self.tvNPDevices.addItem(device.info)
3268
 
+
3269
 
+        #self.tvNPDevices.get_selection().select_path(0)
3270
 
+        self.tvNPDevices.setCurrentRow(0)
3271
 
+        self.on_tvNPDevices_cursor_changed()
3272
 
+
3273
 
+    def on_entNPTDevice_changed(self, entry):
3274
 
+        self.setNPButtons()
3275
 
+
3276
 
+    #TODO
3277
 
+    ## SMB browsing
3278
 
+    def on_entSMBURI_changed (self, text):
3279
 
+        uri = unicode(text)
3280
 
+        (group, host, share, user, password) = SMBURI (uri=uri).separate ()
3281
 
+        if user:
3282
 
+            self.entSMBUsername.setText(user)
3283
 
+        if password:
3284
 
+            self.entSMBPassword.setText(password)
3285
 
+        if user or password:
3286
 
+            uri = SMBURI (group=group, host=host, share=share).get_uri ()
3287
 
+            self.entSMBURI.setText(uri)
3288
 
+            self.rbtnSMBAuthSet.setChecked(True)
3289
 
+        elif unicode(self.entSMBUsername.text()) == '':
3290
 
+            self.rbtnSMBAuthPrompt.setChecked(True)
3291
 
+
3292
 
+        self.btnSMBVerify.setEnabled(bool(uri))
3293
 
+
3294
 
+    def on_rbtnSMBAuthSet_toggled(self, ticked):
3295
 
+        self.tblSMBAuth.setEnabled(ticked)
3296
 
+
3297
 
+    def on_entNPTIPPHostname_textChanged(self):
3298
 
+        valid = len (self.entNPTIPPHostname.text ()) > 0
3299
 
+        self.btnIPPFindQueue.setEnabled(valid)
3300
 
+        self.update_IPP_URI_label ()
3301
 
+
3302
 
+    ### IPP Browsing
3303
 
+    def update_IPP_URI_label(self):
3304
 
+        hostname = unicode(self.entNPTIPPHostname.text())
3305
 
+        queue = unicode(self.entNPTIPPQueuename.text())
3306
 
+        valid = len (hostname) > 0 and queue != '/printers/'
3307
 
+
3308
 
+        if valid:
3309
 
+            uri = "ipp://%s%s" % (hostname, queue)
3310
 
+            self.lblIPPURI.setText(uri)
3311
 
+            self.lblIPPURI.show ()
3312
 
+            self.entNPTIPPQueuename.show ()
3313
 
+        else:
3314
 
+            self.lblIPPURI.hide ()
3315
 
+
3316
 
+        self.btnIPPVerify.setEnabled(valid)
3317
 
+        self.setNPButtons ()
3318
 
+
3319
 
+    @pyqtSignature("")
3320
 
+    def on_btnIPPFindQueue_clicked(self):
3321
 
+        self.mainapp.busy()
3322
 
+        self.entNPTIPPQueuename.clear()
3323
 
+        IPPBrowseDialog(self)
3324
 
+        self.mainapp.ready()
3325
 
+    
3326
 
+    @pyqtSignature("")
3327
 
+    def on_btnIPPVerify_clicked(self):
3328
 
+        uri = unicode(self.lblIPPURI.text())
3329
 
+        match = re.match ("(ipp|https?)://([^/]+)(.*)/([^/]*)", uri)
3330
 
+        verified = False
3331
 
+        if match:
3332
 
+            oldserver = cups.getServer ()
3333
 
+            host = match.group(2)
3334
 
+            try:
3335
 
+                cups.setServer (match.group (2))
3336
 
+                c = cups.Connection ()
3337
 
+                attributes = c.getPrinterAttributes (uri = uri)
3338
 
+                verified = True
3339
 
+            except cups.IPPError, (e, msg):
3340
 
+                debugprint ("Failed to get attributes: %s (%d)" % (msg, e))
3341
 
+            except:
3342
 
+                nonfatalException ()
3343
 
+            cups.setServer (oldserver)
3344
 
+        else:
3345
 
+            debugprint (uri)
3346
 
+
3347
 
+        if verified:
3348
 
+            KMessageBox.information (self, _("This print share is accessible."),
3349
 
+                                    _("Print Share Verified"))
3350
 
+        else:
3351
 
+            KMessageBox.error (self, _("This print share is not accessible."),
3352
 
+                               _("Inaccessible"))
3353
 
+
3354
 
+    def on_tvNPDevices_cursor_changed(self):
3355
 
+        device = self.devices[self.tvNPDevices.currentRow()]
3356
 
+        self.device = device
3357
 
+        self.lblNPDeviceDescription.setText('')
3358
 
+        page = self.new_printer_device_tabs.get(device.type, 1)
3359
 
+        self.ntbkNPType.setCurrentIndex(page)
3360
 
+
3361
 
+        type = device.type
3362
 
+        url = device.uri.split(":", 1)[-1]
3363
 
+        if page == 0:
3364
 
+            # This is the "no options" page, with just a label to describe
3365
 
+            # the selected device.
3366
 
+            if device.type == "parallel":
3367
 
+                text = i18n("A printer connected to the parallel port.")
3368
 
+            elif device.type == "usb":
3369
 
+                text = i18n("A printer connected to a USB port.")
3370
 
+            elif device.type == "hp":
3371
 
+                text = i18n("HPLIP software driving a printer, "
3372
 
+                         "or the printer function of a multi-function device.")
3373
 
+            elif device.type == "hpfax":
3374
 
+                text = i18n("HPLIP software driving a fax machine, "
3375
 
+                         "or the fax function of a multi-function device.")
3376
 
+            elif device.type == "hal":
3377
 
+                text = i18n("Local printer detected by the "
3378
 
+                         "Hardware Abstraction Layer (HAL).")
3379
 
+            else:
3380
 
+                text = device.uri
3381
 
+
3382
 
+            self.lblNPDeviceDescription.setText(text)
3383
 
+        elif device.type=="socket":
3384
 
+            if device.uri.startswith ("socket"):
3385
 
+                host = device.uri[9:]
3386
 
+                i = host.find (":")
3387
 
+                if i != -1:
3388
 
+                    port = int (host[i + 1:])
3389
 
+                    host = host[:i]
3390
 
+                else:
3391
 
+                    port = 9100
3392
 
+
3393
 
+                self.entNPTDirectJetHostname.setText(host)
3394
 
+                self.entNPTDirectJetPort.setText(str (port))
3395
 
+        elif device.type=="serial":
3396
 
+            pass
3397
 
+            """
3398
 
+            if not device.is_class:
3399
 
+                options = device.uri.split("?")[1]
3400
 
+                options = options.split("+")
3401
 
+                option_dict = {}
3402
 
+                for option in options:
3403
 
+                    name, value = option.split("=")
3404
 
+                    option_dict[name] = value
3405
 
+                    
3406
 
+                for widget, name, optionvalues in (
3407
 
+                    (self.cmbNPTSerialBaud, "baud", None),
3408
 
+                    (self.cmbNPTSerialBits, "bits", None),
3409
 
+                    (self.cmbNPTSerialParity, "parity",
3410
 
+                     ["none", "odd", "even"]),
3411
 
+                    (self.cmbNPTSerialFlow, "flow",
3412
 
+                     ["none", "soft", "hard", "hard"])):
3413
 
+                    if option_dict.has_key(name): # option given in URI?
3414
 
+                        if optionvalues is None: # use text in widget
3415
 
+                            model = widget.get_model()
3416
 
+                            iter = model.get_iter_first()
3417
 
+                            nr = 0
3418
 
+                            while iter:
3419
 
+                                value = model.get(iter,0)[0]
3420
 
+                                if value == option_dict[name]:
3421
 
+                                    widget.set_active(nr)
3422
 
+                                    break
3423
 
+                                iter = model.iter_next(iter)
3424
 
+                                nr += 1
3425
 
+                        else: # use optionvalues
3426
 
+                            nr = optionvalues.index(
3427
 
+                                option_dict[name])
3428
 
+                            widget.set_active(nr+1) # compensate "Default"
3429
 
+                    else:
3430
 
+                        widget.set_active(0)
3431
 
+            """
3432
 
+
3433
 
+        # XXX FILL TABS FOR VALID DEVICE URIs
3434
 
+        elif device.type in ("ipp", "http"):
3435
 
+            if (device.uri.startswith ("ipp:") or
3436
 
+                device.uri.startswith ("http:")):
3437
 
+                match = re.match ("(ipp|https?)://([^/]+)(.*)", device.uri)
3438
 
+                if match:
3439
 
+                    server = match.group (2)
3440
 
+                    printer = match.group (3)
3441
 
+                else:
3442
 
+                    server = ""
3443
 
+                    printer = ""
3444
 
+
3445
 
+                self.entNPTIPPHostname.setText(server)
3446
 
+                self.entNPTIPPQueuename.setText(printer)
3447
 
+                self.lblIPPURI.setText(device.uri)
3448
 
+                self.lblIPPURI.show()
3449
 
+                self.entNPTIPPQueuename.show()
3450
 
+            else:
3451
 
+                self.entNPTIPPHostname.setText('')
3452
 
+                self.entNPTIPPQueuename.setText('/printers/')
3453
 
+                self.entNPTIPPQueuename.show()
3454
 
+                self.lblIPPURI.hide()
3455
 
+        elif device.type=="lpd":
3456
 
+            if device.uri.startswith ("lpd"):
3457
 
+                host = device.uri[6:]
3458
 
+                i = host.find ("/")
3459
 
+                if i != -1:
3460
 
+                    printer = host[i + 1:]
3461
 
+                    host = host[:i]
3462
 
+                else:
3463
 
+                    printer = ""
3464
 
+                self.cmbentNPTLpdHost.addItem(host)
3465
 
+                self.cmbentNPTLpdQueue.addItem(printer)
3466
 
+        elif device.uri == "lpd":
3467
 
+            pass
3468
 
+        elif device.uri == "smb":
3469
 
+            self.entSMBURI.setText('')
3470
 
+            self.btnSMBVerify.setEnabled(False)
3471
 
+        elif device.type == "smb":
3472
 
+            self.entSMBUsername.setText('')
3473
 
+            self.entSMBPassword.setText('')
3474
 
+            self.entSMBURI.setText(device.uri[6:])
3475
 
+            self.btnSMBVerify.setEnabled(True)
3476
 
+        else:
3477
 
+            self.entNPTDevice.setText(device.uri)
3478
 
+
3479
 
+        self.setNPButtons()
3480
 
+
3481
 
+    def getDeviceURI(self):
3482
 
+        type = self.device.type
3483
 
+        if type == "socket": # DirectJet
3484
 
+            host = unicode(self.entNPTDirectJetHostname.text())
3485
 
+            port = unicode(self.entNPTDirectJetPort.text())
3486
 
+            device = "socket://" + host
3487
 
+            if port:
3488
 
+                device = device + ':' + port
3489
 
+        elif type in ("http", "ipp"): # IPP
3490
 
+            if self.lblIPPURI.isVisible:
3491
 
+                device = unicode(self.lblIPPURI.text())
3492
 
+            else:
3493
 
+                device = "ipp"
3494
 
+        elif type == "lpd": # LPD
3495
 
+            host = unicode(self.cmbentNPTLpdHost.currentText())
3496
 
+            printer = unicode(self.cmbentNPTLpdQueue.currentText())
3497
 
+            device = "lpd://" + host
3498
 
+            if printer:
3499
 
+                device = device + "/" + printer
3500
 
+        elif type == "parallel": # Parallel
3501
 
+            device = self.device.uri
3502
 
+        elif type == "scsi": # SCSII
3503
 
+            device = ""
3504
 
+        elif type == "serial": # Serial
3505
 
+            pass
3506
 
+            """
3507
 
+            options = []
3508
 
+            for widget, name, optionvalues in (
3509
 
+                (self.cmbNPTSerialBaud, "baud", None),
3510
 
+                (self.cmbNPTSerialBits, "bits", None),
3511
 
+                (self.cmbNPTSerialParity, "parity",
3512
 
+                 ("none", "odd", "even")),
3513
 
+                (self.cmbNPTSerialFlow, "flow",
3514
 
+                 ("none", "soft", "hard", "hard"))):
3515
 
+                nr = widget.get_active()
3516
 
+                if nr:
3517
 
+                    if optionvalues is not None:
3518
 
+                        option = optionvalues[nr-1]
3519
 
+                    else:
3520
 
+                        option = widget.get_active_text()
3521
 
+                    options.append(name + "=" + option)
3522
 
+            options = "+".join(options)
3523
 
+            device =  self.device.uri.split("?")[0] #"serial:/dev/ttyS%s" 
3524
 
+            if options:
3525
 
+                device = device + "?" + options
3526
 
+            """
3527
 
+        elif type == "smb":
3528
 
+            uri = unicode(self.entSMBURI.text())
3529
 
+            (group, host, share, u, p) = SMBURI (uri=uri).separate ()
3530
 
+            user = ''
3531
 
+            password = ''
3532
 
+            if self.rbtnSMBAuthSet.isChecked():
3533
 
+                user = unicode(self.entSMBUsername.text())
3534
 
+                password = unicode(self.entSMBPassword.text())
3535
 
+            uri = SMBURI (group=group, host=host, share=share,
3536
 
+                          user=user, password=password).get_uri ()
3537
 
+            device = "smb://" + uri
3538
 
+        elif not self.device.is_class:
3539
 
+            device = self.device.uri
3540
 
+        else:
3541
 
+            device = str(self.entNPTDevice.text())
3542
 
+        return device
3543
 
+        # class/printer
3544
 
+
3545
 
+        if nr == self.ntbkNewPrinterPages["device"]: # Device
3546
 
+            valid = False
3547
 
+            try:
3548
 
+                uri = self.getDeviceURI ()
3549
 
+                valid = validDeviceURI (uri)
3550
 
+            except:
3551
 
+                debugprint("exception in getDeviceURI()")
3552
 
+                pass
3553
 
+            self.btnNPForward.setEnabled(valid)
3554
 
+            self.btnNPBack.hide ()
3555
 
+        else:
3556
 
+            self.btnNPBack.show()
3557
 
+
3558
 
+        self.btnNPForward.show()
3559
 
+        self.btnNPApply.hide()
3560
 
+
3561
 
+        if nr == self.ntbkNewPrinterPages["name"]: # Name
3562
 
+            self.btnNPBack.show()
3563
 
+            if self.dialog_mode == "printer":
3564
 
+                self.btnNPForward.hide()
3565
 
+                self.btnNPApply.show()
3566
 
+                self.btnNPApply.setEnabled(
3567
 
+                    self.mainapp.checkNPName(self.entNPName.getText()))
3568
 
+        if nr == self.ntbkNewPrinterPages["make"]: # Make/PPD file
3569
 
+            downloadable_selected = False
3570
 
+            if self.rbtnNPDownloadableDriverSearch.get_active ():
3571
 
+                combobox = self.cmbNPDownloadableDriverFoundPrinters
3572
 
+                iter = combobox.get_active_iter ()
3573
 
+                if iter and combobox.get_model ().get_value (iter, 1):
3574
 
+                    downloadable_selected = True
3575
 
+
3576
 
+            self.btnNPForward.setEnabled(bool(
3577
 
+                self.rbtnNPFoomatic.get_active() or
3578
 
+                not self.filechooserPPD.text().isEmpty() or
3579
 
+                downloadable_selected))
3580
 
+        if nr == self.ntbkNewPrinterPages["model"]: # Model/Driver
3581
 
+            model, iter = self.tvNPDrivers.get_selection().get_selected()
3582
 
+            self.btnNPForward.set_sensitive(bool(iter))
3583
 
+        if nr == self.ntbkNewPrinterPages["class-members"]: # Class Members
3584
 
+            self.btnNPForward.hide()
3585
 
+            self.btnNPApply.show()
3586
 
+            self.btnNPApply.setEnabled(
3587
 
+                bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
3588
 
+        if nr == self.ntbkNewPrinterPages["downloadable"]: # Downloadable drivers
3589
 
+            if self.ntbkNPDownloadableDriverProperties.get_current_page() == 1:
3590
 
+                accepted = self.rbtnNPDownloadLicenseYes.get_active ()
3591
 
+            else:
3592
 
+                accepted = True
3593
 
+
3594
 
+            self.btnNPForward.set_sensitive(accepted)
3595
 
+
3596
 
+    # PPD
3597
 
+
3598
 
+    def on_rbtnNPFoomatic_toggled(self):
3599
 
+        rbtn1 = self.rbtnNPFoomatic.isChecked()
3600
 
+        rbtn2 = self.rbtnNPPPD.isChecked()
3601
 
+        rbtn3 = self.rbtnNPDownloadableDriverSearch.isChecked()
3602
 
+        self.tvNPMakes.setEnabled(rbtn1)
3603
 
+        self.filechooserPPD.setEnabled(rbtn2)
3604
 
+        
3605
 
+        """FIXME
3606
 
+        if not rbtn3 and self.openprinting_query_handle:
3607
 
+            # Need to cancel a search in progress.
3608
 
+            self.openprinting.cancelOperation (self.openprinting_query_handle)
3609
 
+            self.openprinting_query_handle = None
3610
 
+            self.btnNPDownloadableDriverSearch_label.setText(_("Search"))
3611
 
+            # Clear printer list.
3612
 
+            self.cmbNPDownloadableDriverFoundPrinters.clear()
3613
 
+        """
3614
 
+
3615
 
+        for widget in [self.entNPDownloadableDriverSearch,
3616
 
+                       self.cmbNPDownloadableDriverFoundPrinters]:
3617
 
+            widget.setEnabled(rbtn3)
3618
 
+        self.btnNPDownloadableDriverSearch.\
3619
 
+            setEnabled(rbtn3 and (self.openprinting_query_handle == None))
3620
 
+
3621
 
+        self.setNPButtons()
3622
 
+
3623
 
+    def fillMakeList(self):
3624
 
+        makes = self.ppds.getMakes()
3625
 
+        self.tvNPMakes.clear()
3626
 
+        found = False
3627
 
+        index = 0
3628
 
+        for make in makes:
3629
 
+            self.tvNPMakes.addItem(make)
3630
 
+            index = index + 1
3631
 
+            if make==self.auto_make:
3632
 
+                self.tvNPMakes.setCurrentRow(index-1)
3633
 
+                found = True
3634
 
+
3635
 
+        self.on_tvNPMakes_cursor_changed()
3636
 
+
3637
 
+    def on_tvNPMakes_cursor_changed(self):
3638
 
+        items = self.tvNPMakes.selectedItems()
3639
 
+        if len(items) > 0:
3640
 
+            self.NPMake = unicode(items[0].text())
3641
 
+            self.fillModelList()
3642
 
+
3643
 
+    def fillModelList(self):
3644
 
+        models = self.ppds.getModels(self.NPMake)
3645
 
+        self.tvNPModels.clear()
3646
 
+        selected = False
3647
 
+        index = 0
3648
 
+        selected = False
3649
 
+        for pmodel in models:
3650
 
+            self.tvNPModels.addItem(pmodel)
3651
 
+            if self.NPMake==self.auto_make and pmodel==self.auto_model:
3652
 
+                self.tvNPModels.setCurrentRow(index)
3653
 
+                selected = True
3654
 
+            index = index + 1
3655
 
+        if not selected:
3656
 
+            self.tvNPModels.setCurrentRow(0)
3657
 
+        ##self.tvNPModels.columns_autosize()
3658
 
+        self.on_tvNPModels_cursor_changed()
3659
 
+
3660
 
+    def fillDriverList(self, pmake, pmodel):
3661
 
+        self.NPModel = pmodel
3662
 
+        self.tvNPDrivers.clear()
3663
 
+
3664
 
+        ppds = self.ppds.getInfoFromModel(pmake, pmodel)
3665
 
+
3666
 
+        self.NPDrivers = self.ppds.orderPPDNamesByPreference(ppds.keys()) 
3667
 
+        for i in range (len(self.NPDrivers)):
3668
 
+            ppd = ppds[self.NPDrivers[i]]
3669
 
+            driver = ppd["ppd-make-and-model"]
3670
 
+            driver = driver.replace(" (recommended)", "")
3671
 
+
3672
 
+            try:
3673
 
+                lpostfix = " [%s]" % ppd["ppd-natural-language"]
3674
 
+                driver += lpostfix
3675
 
+            except KeyError:
3676
 
+                pass
3677
 
+
3678
 
+            if i == 0:
3679
 
+                self.tvNPDrivers.addItem(i18nc("Recommended driver", "%1 (recommended)", driver))
3680
 
+                self.tvNPDrivers.setCurrentRow(0)
3681
 
+            else:
3682
 
+                self.tvNPDrivers.addItem(driver)
3683
 
+        ##self.tvNPDrivers.columns_autosize()
3684
 
+
3685
 
+    def on_tvNPModels_cursor_changed(self):
3686
 
+        items = self.tvNPModels.selectedItems()
3687
 
+        if len(items) > 0:
3688
 
+            pmodel = unicode(items[0].text())
3689
 
+            self.fillDriverList(self.NPMake, pmodel)
3690
 
+
3691
 
+    def getNPPPD(self):
3692
 
+        try:
3693
 
+            if self.rbtnNPFoomatic.isChecked():
3694
 
+                #items = self.tvNPDrivers.selectedItems()
3695
 
+                #nr = unicode(items[0])
3696
 
+                nr = self.tvNPDrivers.currentRow()
3697
 
+                ppd = self.NPDrivers[nr]
3698
 
+            elif self.rbtnNPPPD.isChecked():
3699
 
+                ppd = cups.PPD(unicode(self.filechooserPPD.text()))
3700
 
+            else:
3701
 
+                """FIXME
3702
 
+                # PPD of the driver downloaded from OpenPrinting XXX
3703
 
+                treeview = self.tvNPDownloadableDrivers
3704
 
+                model, iter = treeview.get_selection ().get_selected ()
3705
 
+                driver = model.get_value (iter, 1)
3706
 
+                if driver.has_key ('ppds'):
3707
 
+                    # Only need to download a PPD.
3708
 
+                    file_to_download = driver
3709
 
+                """
3710
 
+
3711
 
+                ppd = "XXX"
3712
 
+
3713
 
+        except RuntimeError, e:
3714
 
+            if self.rbtnNPFoomatic.isChecked():
3715
 
+                # Foomatic database problem of some sort.
3716
 
+                err_title = i18n('Database error')
3717
 
+                model, iter = (self.tvNPDrivers.get_selection().
3718
 
+                               get_selected())
3719
 
+                nr = model.get_path(iter)[0]
3720
 
+                driver = self.NPDrivers[nr]
3721
 
+                if driver.startswith ("gutenprint"):
3722
 
+                    # This printer references some XML that is not
3723
 
+                    # installed by default.  Point the user at the
3724
 
+                    # package they need to install.
3725
 
+                    err = i18n("You will need to install the '%1' package "
3726
 
+                            "in order to use this driver.",
3727
 
+                            "gutenprint-foomatic")
3728
 
+                else:
3729
 
+                    err = i18n("The '%1' driver cannot be "
3730
 
+                             "used with printer '%2 %3'.", driver, self.NPMake, self.NPModel)
3731
 
+            elif self.rbtnNPPPD.isChecked():
3732
 
+                # This error came from trying to open the PPD file.
3733
 
+                err_title = i18n('PPD error')
3734
 
+                filename = self.filechooserPPD.text()
3735
 
+                err = i18n('Failed to read PPD file.  Possible reason '
3736
 
+                        'follows:') + '\n'
3737
 
+                os.environ["PPD"] = filename
3738
 
+                # We want this to be in the current natural language,
3739
 
+                # so we intentionally don't set LC_ALL=C here.
3740
 
+                p = os.popen ('/usr/bin/cupstestppd -rvv "$PPD"', 'r')
3741
 
+                output = p.readlines ()
3742
 
+                p.close ()
3743
 
+                err += reduce (lambda x, y: x + y, output)
3744
 
+            else:
3745
 
+                # Failed to get PPD downloaded from OpenPrinting XXX
3746
 
+                err_title = i18n('Downloadable drivers')
3747
 
+                err_text = i18n("Support for downloadable "
3748
 
+                             "drivers is not yet completed.")
3749
 
+
3750
 
+            error_text = ('<span size="larger">' +
3751
 
+                          i18nc("Error title", "<b>%1</b>", err_title) + '</span>\n\n' + err)
3752
 
+            KMessageBox.error(self, error_text, err_title)
3753
 
+            return None
3754
 
+
3755
 
+        if isinstance(ppd, str) or isinstance(ppd, unicode):
3756
 
+            try:
3757
 
+                if (ppd != "raw"):
3758
 
+                    f = self.mainapp.cups.getServerPPD(ppd)
3759
 
+                    ppd = cups.PPD(f)
3760
 
+                    os.unlink(f)
3761
 
+            except AttributeError:
3762
 
+                nonfatalException()
3763
 
+                debugprint ("pycups function getServerPPD not available: never mind")
3764
 
+            except RuntimeError:
3765
 
+                nonfatalException()
3766
 
+                debugprint ("libcups from CUPS 1.3 not available: never mind")
3767
 
+            except cups.IPPError:
3768
 
+                nonfatalException()
3769
 
+                debugprint ("CUPS 1.3 server not available: never mind")
3770
 
+
3771
 
+        return ppd
3772
 
+
3773
 
+    # Create new Printer
3774
 
+    @pyqtSignature("")
3775
 
+    def on_btnNPApply_clicked(self):
3776
 
+        if self.dialog_mode in ("class", "printer"):
3777
 
+            name = unicode(self.entNPName.text())
3778
 
+            location = unicode(self.entNPLocation.text())
3779
 
+            info = unicode(self.entNPDescription.text())
3780
 
+        else:
3781
 
+            name = self.mainapp.printer.name
3782
 
+
3783
 
+        #replace any whitespace in printer name with underscore otherwise
3784
 
+        #CUPS throws an error
3785
 
+        name = name.replace(" ", "_")
3786
 
+        
3787
 
+        # Whether to check for missing drivers.
3788
 
+        check = False
3789
 
+        checkppd = None
3790
 
+        ppd = self.ppd
3791
 
+
3792
 
+        if self.dialog_mode=="class":
3793
 
+            members = self.mainapp.getCurrentClassMembers(self.tvNCMembers)
3794
 
+            try:
3795
 
+                for member in members:
3796
 
+                    self.passwd_retry = False # use cached Passwd 
3797
 
+                    self.mainapp.cups.addPrinterToClass(str(member), name)
3798
 
+            except cups.IPPError, (e, msg):
3799
 
+                self.show_IPP_Error(e, msg)
3800
 
+                return
3801
 
+        elif self.dialog_mode=="printer":
3802
 
+            self.device.uri = unicode(self.device.uri)
3803
 
+            uri = None
3804
 
+            if self.device.uri:
3805
 
+                uri = self.device.uri
3806
 
+            else:
3807
 
+                uri = self.getDeviceURI()
3808
 
+            if not self.ppd: # XXX needed?
3809
 
+                # Go back to previous page to re-select driver.
3810
 
+                self.nextNPTab(-1)
3811
 
+                return
3812
 
+
3813
 
+            # write Installable Options to ppd
3814
 
+            for option in self.options.itervalues():
3815
 
+                option.writeback()
3816
 
+
3817
 
+            self.mainapp.busy(self)
3818
 
+            self.WaitWindow.setText(i18n('<b>Adding</b>') + '<br /><br />' +
3819
 
+                                    i18n('Adding printer'))
3820
 
+            #self.WaitWindow.set_transient_for (self.NewPrinterWindow)
3821
 
+            self.WaitWindow.show ()
3822
 
+            KApplication.processEvents()
3823
 
+            try:
3824
 
+                self.passwd_retry = False # use cached Passwd
3825
 
+                if isinstance(ppd, str) or isinstance(ppd, unicode):
3826
 
+                    self.mainapp.cups.addPrinter(name, ppdname=ppd,
3827
 
+                         device=uri, info=info, location=location)
3828
 
+                    check = True
3829
 
+                elif ppd is None: # raw queue
3830
 
+                    self.mainapp.cups.addPrinter(name, device=uri,
3831
 
+                                         info=info, location=location)
3832
 
+                else:
3833
 
+                    cupshelpers.setPPDPageSize(ppd, self.language[0])
3834
 
+                    self.mainapp.cups.addPrinter(name, ppd=ppd,
3835
 
+                         device=uri, info=info, location=location)
3836
 
+                    check = True
3837
 
+                    checkppd = ppd
3838
 
+                cupshelpers.activateNewPrinter (self.mainapp.cups, name)
3839
 
+            except cups.IPPError, (e, msg):
3840
 
+                #self.ready(self)
3841
 
+                self.WaitWindow.hide ()
3842
 
+                self.show_IPP_Error(e, msg)
3843
 
+                return
3844
 
+            except:
3845
 
+                ##self.ready (self.NewPrinterWindow)
3846
 
+                self.WaitWindow.hide ()
3847
 
+                fatalException (1)
3848
 
+            self.WaitWindow.hide ()
3849
 
+            ##self.ready (self.NewPrinterWindow)
3850
 
+    #comment  
3851
 
+        if self.dialog_mode in ("class", "printer"):
3852
 
+            try:
3853
 
+                self.passwd_retry = False # use cached Passwd 
3854
 
+                self.mainapp.cups.setPrinterLocation(name, location)
3855
 
+                self.passwd_retry = False # use cached Passwd 
3856
 
+                self.mainapp.cups.setPrinterInfo(name, info)
3857
 
+            except cups.IPPError, (e, msg):
3858
 
+                self.show_IPP_Error(e, msg)
3859
 
+                return
3860
 
+        elif self.dialog_mode == "device":
3861
 
+            try:
3862
 
+                uri = self.getDeviceURI()
3863
 
+                self.mainapp.cups.addPrinter(name, device=uri)
3864
 
+            except cups.IPPError, (e, msg):
3865
 
+                self.show_IPP_Error(e, msg)
3866
 
+                return 
3867
 
+        elif self.dialog_mode == "ppd":
3868
 
+            if not ppd:
3869
 
+                ppd = self.ppd = self.getNPPPD()
3870
 
+                if not ppd:
3871
 
+                    # Go back to previous page to re-select driver.
3872
 
+                    self.nextNPTab(-1)
3873
 
+                    return
3874
 
+
3875
 
+            # set ppd on server and retrieve it
3876
 
+            # cups doesn't offer a way to just download a ppd ;(=
3877
 
+            raw = False
3878
 
+            if isinstance(ppd, str) or isinstance(ppd, unicode):
3879
 
+                if self.rbtnChangePPDasIs.isChecked():
3880
 
+                    # To use the PPD as-is we need to prevent CUPS copying
3881
 
+                    # the old options over.  Do this by setting it to a
3882
 
+                    # raw queue (no PPD) first.
3883
 
+                    try:
3884
 
+                        self.mainapp.cups.addPrinter(name, ppdname='raw')
3885
 
+                    except cups.IPPError, (e, msg):
3886
 
+                        self.show_IPP_Error(e, msg)
3887
 
+                try:
3888
 
+                    self.mainapp.cups.addPrinter(name, ppdname=ppd)
3889
 
+                except cups.IPPError, (e, msg):
3890
 
+                    self.show_IPP_Error(e, msg)
3891
 
+                    return
3892
 
+
3893
 
+                try:
3894
 
+                    filename = self.mainapp.cups.getPPD(name)
3895
 
+                    ppd = cups.PPD(filename)
3896
 
+                    os.unlink(filename)
3897
 
+                except cups.IPPError, (e, msg):
3898
 
+                    if e == cups.IPP_NOT_FOUND:
3899
 
+                        raw = True
3900
 
+                    else:
3901
 
+                        self.show_IPP_Error(e, msg)
3902
 
+                        return
3903
 
+            else:
3904
 
+                # We have an actual PPD to upload, not just a name.
3905
 
+                if not self.rbtnChangePPDasIs.isChecked():
3906
 
+                    cupshelpers.copyPPDOptions(self.mainapp.ppd, ppd) # XXX
3907
 
+                else:
3908
 
+                    # write Installable Options to ppd
3909
 
+                    for option in self.options.itervalues():
3910
 
+                        option.writeback()
3911
 
+                    cupshelpers.setPPDPageSize(ppd, self.language[0])
3912
 
+
3913
 
+                try:
3914
 
+                    self.mainapp.cups.addPrinter(name, ppd=ppd)
3915
 
+                except cups.IPPError, (e, msg):
3916
 
+                    self.show_IPP_Error(e, msg)
3917
 
+
3918
 
+            if not raw:
3919
 
+                check = True
3920
 
+                checkppd = ppd
3921
 
+
3922
 
+        self.accept()
3923
 
+        self.mainapp.populateList(start_printer=name)
3924
 
+        if check:
3925
 
+            try:
3926
 
+                self.checkDriverExists (name, ppd=checkppd)
3927
 
+            except:
3928
 
+                nonfatalException()
3929
 
+
3930
 
+            # Also check to see whether the media option has become
3931
 
+            # invalid.  This can happen if it had previously been
3932
 
+            # explicitly set to a page size that is not offered with
3933
 
+            # the new PPD (see bug #441836).
3934
 
+            """
3935
 
+            try:
3936
 
+                option = self.mainapp.server_side_options['media']
3937
 
+                if option.get_current_value () == None:
3938
 
+                    debugprint ("Invalid media option: resetting")
3939
 
+                    option.reset ()
3940
 
+                    self.mainapp.changed.add (option)
3941
 
+                    self.mainapp.save_printer (self.mainapp.printer)
3942
 
+            except KeyError:
3943
 
+                pass
3944
 
+            except:
3945
 
+                print "exception in check to see whether the media option has become invalid"
3946
 
+                nonfatalException()
3947
 
+            """
3948
 
+
3949
 
+    def show_IPP_Error(self, exception, message):
3950
 
+            if exception == cups.IPP_NOT_AUTHORIZED:
3951
 
+                KMessageBox.error(self, i18n('The password may be incorrect.'), i18n('Not authorized'))
3952
 
+            else:
3953
 
+                KMessageBox.error(self, i18n("There was an error during the CUPS " "operation: '%1'.", message),
3954
 
+                                        i18n('CUPS server error'))
3955
 
+
3956
 
+    def checkDriverExists(self, name, ppd=None):
3957
 
+        """Check that the driver for an existing queue actually
3958
 
+        exists, and prompt to install the appropriate package
3959
 
+        if not.
3960
 
+
3961
 
+        ppd: cups.PPD object, if already created"""
3962
 
+
3963
 
+        # Is this queue on the local machine?  If not, we can't check
3964
 
+        # anything at all.
3965
 
+        server = cups.getServer ()
3966
 
+        if not (server == 'localhost' or server == '127.0.0.1' or
3967
 
+                server == '::1' or server[0] == '/'):
3968
 
+            return
3969
 
+
3970
 
+        # Fetch the PPD if we haven't already.
3971
 
+        if not ppd:
3972
 
+            try:
3973
 
+                filename = self.mainapp.cups.getPPD(name)
3974
 
+            except cups.IPPError, (e, msg):
3975
 
+                if e == cups.IPP_NOT_FOUND:
3976
 
+                    # This is a raw queue.  Nothing to check.
3977
 
+                    return
3978
 
+                else:
3979
 
+                    self.show_IPP_Error(e, msg)
3980
 
+                    return
3981
 
+
3982
 
+            ppd = cups.PPD(filename)
3983
 
+            os.unlink(filename)
3984
 
+
3985
 
+        (pkgs, exes) = cupshelpers.missingPackagesAndExecutables (ppd)
3986
 
+        if len (pkgs) > 0 or len (exes) > 0:
3987
 
+            # We didn't find a necessary executable.  Complain.
3988
 
+            install = "/usr/bin/system-install-packages"
3989
 
+            if len (pkgs) > 0 and os.access (install, os.X_OK):
3990
 
+                pkg = pkgs[0]
3991
 
+                install_text = ('<span weight="bold" size="larger">' +
3992
 
+                                i18n('Install driver') + '</span>\n\n' +
3993
 
+                                i18n("Printer '%1' requires the %2 package but "
3994
 
+                                  "it is not currently installed.", name, pkg))
3995
 
+                dialog = self.InstallDialog
3996
 
+                self.lblInstall.set_markup(install_text)
3997
 
+            else:
3998
 
+                error_text = ('<span weight="bold" size="larger">' +
3999
 
+                              i18n('Missing driver') + '</span>\n\n' +
4000
 
+                              i18n("Printer '%1' requires the '%2' program but "
4001
 
+                                "it is not currently installed.  Please "
4002
 
+                                "install it before using this printer.", name, (exes + pkgs)[0]))
4003
 
+                KMessageBox.error(self, error_text, "Missing Driver")
4004
 
+
4005
 
+            """
4006
 
+            if pkg and response == gtk.RESPONSE_OK:
4007
 
+                # Install the package.
4008
 
+                def wait_child (sig, stack):
4009
 
+                    (pid, status) = os.wait ()
4010
 
+
4011
 
+                signal.signal (signal.SIGCHLD, wait_child)
4012
 
+                pid = os.fork ()
4013
 
+                if pid == 0:
4014
 
+                    # Child.
4015
 
+                    try:
4016
 
+                        os.execv (install, [install, pkg])
4017
 
+                    except:
4018
 
+                        pass
4019
 
+                    sys.exit (1)
4020
 
+                elif pid == -1:
4021
 
+                    pass # should handle error
4022
 
+            """
4023
 
+
4024
 
+    #FIXME obsolete?
4025
 
+    def on_entNPTIPPQueuename_textChanged(self, ent):
4026
 
+        self.update_IPP_URI_label ()
4027
 
+
4028
 
+    #FIXME not in gnome?
4029
 
+    @pyqtSignature("")
4030
 
+    def on_btnNPCancel_clicked(self):
4031
 
+        self.hide()
4032
 
+        
4033
 
+    #copy busy and ready functions from the mainapp
4034
 
+    #since they can't be inherited from the mainapp
4035
 
+    def busy (self, win = None):
4036
 
+        try:
4037
 
+            if not win:
4038
 
+                win = self
4039
 
+            win.setCursor(Qt.WaitCursor)
4040
 
+            KApplication.processEvents()
4041
 
+        except:
4042
 
+            nonfatalException ()
4043
 
+
4044
 
+    def ready (self, win = None):
4045
 
+        try:
4046
 
+            if not win:
4047
 
+                win = self
4048
 
+            win.setCursor(Qt.ArrowCursor)
4049
 
+            KApplication.processEvents()
4050
 
+        except:
4051
 
+            nonfatalException ()
4052
 
+#end of class NewPrinterGUI
4053
 
+
4054
 
+class IPPBrowseDialog(QDialog):
4055
 
+
4056
 
+    def __init__(self, newprinter):
4057
 
+        QDialog.__init__(self, newprinter)
4058
 
+        self.newprinter = newprinter
4059
 
+        
4060
 
+        self.language = newprinter.language
4061
 
+        self.dialog_mode = ""
4062
 
+
4063
 
+        self.WaitWindow = QMessageBox(self.newprinter)
4064
 
+        self.WaitWindow.setStandardButtons(QMessageBox.NoButton)
4065
 
+        
4066
 
+        uic.loadUi(APPDIR + "/" + "ipp-browse-dialog.ui", self)
4067
 
+        
4068
 
+        self.btnIPPBrowseOk.setEnabled(False)
4069
 
+        self.show()
4070
 
+        
4071
 
+        #create an empty data model
4072
 
+        self.ippStore = self.twIPPBrowser
4073
 
+        self.twIPPBrowser.sortByColumn(0, Qt.AscendingOrder)
4074
 
+        
4075
 
+        #Set tree header labels. Takes list of strings
4076
 
+        self.ippStore.setHeaderLabels([_("Share"), _("Comment")])
4077
 
+
4078
 
+        self.browse_ipp_queues()
4079
 
+
4080
 
+    def browse_ipp_queues(self):
4081
 
+        if not self.newprinter.ipp_lock.acquire(0):
4082
 
+            return
4083
 
+        self.browse_ipp_queues_thread()
4084
 
+
4085
 
+    def browse_ipp_queues_thread(self):
4086
 
+        host = None
4087
 
+        try:
4088
 
+            store = self.ippStore
4089
 
+            store.clear ()
4090
 
+            items = QTreeWidgetItem(QStringList([_('Scanning...'), '']))
4091
 
+            store.addTopLevelItem(items)
4092
 
+
4093
 
+            host = self.newprinter.entNPTIPPHostname.text()
4094
 
+        except:
4095
 
+            nonfatalException()
4096
 
+
4097
 
+        oldserver = cups.getServer ()
4098
 
+        printers = classes = {}
4099
 
+        failed = False
4100
 
+        port = 631
4101
 
+        
4102
 
+        if host != None:
4103
 
+            #need to pass a unicode string. urllib falls over QStrings
4104
 
+            (host, port) = urllib.splitnport (unicode(host), defport=port)
4105
 
+
4106
 
+        try:
4107
 
+            c = cups.Connection (host=host, port=port)
4108
 
+            printers = c.getPrinters ()
4109
 
+            del c
4110
 
+        except cups.IPPError, (e, m):
4111
 
+            debugprint ("IPP browser: %s" % m)
4112
 
+            failed = True
4113
 
+        except:
4114
 
+            nonfatalException()
4115
 
+            failed = True
4116
 
+        cups.setServer (oldserver)
4117
 
+
4118
 
+        try:
4119
 
+            store.clear ()
4120
 
+            for printer, dict in printers.iteritems ():
4121
 
+                #only these properties seem to be used from dict so 
4122
 
+                #just store these instead of whole dict
4123
 
+                location = dict.get('printer-location', '')
4124
 
+                uri = dict.get('printer-uri-supported', 'ipp')
4125
 
+                items = QTreeWidgetItem(QStringList([printer, location, uri]))
4126
 
+                store.addTopLevelItem(items)
4127
 
+
4128
 
+            if len (printers) + len (classes) == 0:
4129
 
+                # Display 'No queues' dialog
4130
 
+                if failed:
4131
 
+                    title = _("Not possible")
4132
 
+                    text = (_("It is not possible to obtain a list of queues "
4133
 
+                              "from `%s'.") % host + '\n\n' +
4134
 
+                            _("Obtaining a list of queues is a CUPS extension "
4135
 
+                              "to IPP.  Network printers do not support it."))
4136
 
+                else:
4137
 
+                    title = _("No queues")
4138
 
+                    text = _("There are no queues available.")
4139
 
+
4140
 
+                self.hide ()
4141
 
+                KMessageBox.error (self.newprinter, text, title)
4142
 
+
4143
 
+            try:
4144
 
+                self.ready(self)
4145
 
+            except:
4146
 
+                nonfatalException()
4147
 
+
4148
 
+            self.newprinter.ipp_lock.release()
4149
 
+        except:
4150
 
+            nonfatalException()
4151
 
+
4152
 
+        
4153
 
+    def on_twIPPBrowser_itemClicked(self):
4154
 
+        self.btnIPPBrowseOk.setEnabled(True)
4155
 
+
4156
 
+    def on_btnIPPBrowseOk_clicked(self):
4157
 
+        index = self.twIPPBrowser.currentIndex()
4158
 
+        item = self.twIPPBrowser.itemFromIndex(index)
4159
 
+        queue = item.text(0)
4160
 
+        uri = unicode(item.text(2))
4161
 
+        self.hide()
4162
 
+        self.newprinter.entNPTIPPQueuename.setText (queue)
4163
 
+        self.newprinter.entNPTIPPQueuename.show()
4164
 
+        #uri = dict.get('printer-uri-supported', 'ipp')
4165
 
+        match = re.match ("(ipp|https?)://([^/]+)(.*)", uri)
4166
 
+        if match:
4167
 
+            self.newprinter.entNPTIPPHostname.setText (match.group (2))
4168
 
+            self.newprinter.entNPTIPPQueuename.setText (match.group (3))
4169
 
+
4170
 
+        self.newprinter.lblIPPURI.setText (uri)
4171
 
+        self.newprinter.lblIPPURI.show()
4172
 
+        self.newprinter.setNPButtons()
4173
 
+
4174
 
+    def on_btnIPPBrowseCancel_clicked(self):
4175
 
+        self.hide()
4176
 
+
4177
 
+    def on_btnIPPBrowseRefresh_clicked(self):
4178
 
+        self.browse_ipp_queues()
4179
 
+    
4180
 
+    #copy busy and ready functions from the mainapp
4181
 
+    #since they can't be inherited from the mainapp
4182
 
+    def busy (self, win = None):
4183
 
+        try:
4184
 
+            if not win:
4185
 
+                win = self
4186
 
+            win.setCursor(Qt.WaitCursor)
4187
 
+            KApplication.processEvents()
4188
 
+        except:
4189
 
+            nonfatalException ()
4190
 
+
4191
 
+    def ready (self, win = None):
4192
 
+        try:
4193
 
+            if not win:
4194
 
+                win = self
4195
 
+            win.setCursor(Qt.ArrowCursor)
4196
 
+            KApplication.processEvents()
4197
 
+        except:
4198
 
+            nonfatalException ()
4199
 
+#End of class IPPBrowseDialog
4200
 
+
4201
 
+#Needed to iterate over a QTreeWidgetItem for the user access
4202
 
+#list
4203
 
+class Iter(QTreeWidgetItemIterator):
4204
 
+    def __init__(self, *args):
4205
 
+        QTreeWidgetItemIterator.__init__(self, *args)
4206
 
+    def next(self):
4207
 
+        self.__iadd__(1)
4208
 
+        value = self.value()
4209
 
+        if not value:
4210
 
+            raise StopIteration
4211
 
+        else:
4212
 
+            return self.value() 
4213
 
+
4214
 
+def CreatePlugin(widget_parent, parent, component_data):
4215
 
+    u = GUI()
4216
 
+    kcm = u.makeui(component_data, widget_parent)
4217
 
+    return kcm
4218
 
+
4219
 
+#if __name__ == "__main__":
4220
 
+    #"""start the application"""
4221
 
+
4222
 
+    #appName     = "system-config-printer-kde"
4223
 
+    #catalogue   = "system-config-printer-kde"
4224
 
+    #programName = ki18n("System Config Printer KDE")
4225
 
+    #version     = "1.0"
4226
 
+    #description = ki18n("Printer configuration tool")
4227
 
+    #license     = KAboutData.License_GPL
4228
 
+    #copyright   = ki18n("2007 Tim Waugh, Red Hat Inc, 2007-2008 Canonical Ltd")
4229
 
+    #text        = KLocalizedString()
4230
 
+    #homePage    = "https://launchpad.net/system-config-printer"
4231
 
+    #bugEmail    = ""
4232
 
+
4233
 
+    #aboutData   = KAboutData (appName, catalogue, programName, version, description,
4234
 
+                                #license, copyright, text, homePage, bugEmail)
4235
 
+
4236
 
+    #aboutData.addAuthor(ki18n("Jonathan Riddell"), ki18n("Author"))
4237
 
+    #aboutData.addAuthor(ki18n("Tim Waugh/Red Hat"), ki18n("System Config Printer Author"))
4238
 
+
4239
 
+    #options = KCmdLineOptions()
4240
 
+
4241
 
+    #KCmdLineArgs.init(sys.argv, aboutData)
4242
 
+    #KCmdLineArgs.addCmdLineOptions(options)
4243
 
+
4244
 
+    #app = KApplication()
4245
 
+    #args = KCmdLineArgs.parsedArgs()
4246
 
+
4247
 
+    #applet = GUI()
4248
 
+    #sys.exit(app.exec_())
4249
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/new-printer.ui kdeadmin-4.2.2/system-config-printer-kde/new-printer.ui
4250
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/new-printer.ui        2008-11-04 17:13:05.000000000 +0000
4251
 
+++ kdeadmin-4.2.2/system-config-printer-kde/new-printer.ui     2009-04-09 22:56:08.000000000 +0100
4252
 
@@ -1,65 +1,66 @@
4253
 
-<ui version="4.0" >
4254
 
+<?xml version="1.0" encoding="UTF-8"?>
4255
 
+<ui version="4.0">
4256
 
  <class>form</class>
4257
 
- <widget class="QDialog" name="form" >
4258
 
-  <property name="geometry" >
4259
 
+ <widget class="QDialog" name="form">
4260
 
+  <property name="geometry">
4261
 
    <rect>
4262
 
     <x>0</x>
4263
 
     <y>0</y>
4264
 
     <width>707</width>
4265
 
-    <height>534</height>
4266
 
+    <height>583</height>
4267
 
    </rect>
4268
 
   </property>
4269
 
-  <property name="windowTitle" >
4270
 
+  <property name="windowTitle">
4271
 
    <string>Dialog</string>
4272
 
   </property>
4273
 
-  <property name="windowIcon" >
4274
 
+  <property name="windowIcon">
4275
 
    <iconset>
4276
 
     <normaloff>../../../../.designer/backup/printer-128.png</normaloff>../../../../.designer/backup/printer-128.png</iconset>
4277
 
   </property>
4278
 
-  <layout class="QGridLayout" >
4279
 
-   <item row="0" column="0" colspan="5" >
4280
 
-    <widget class="QStackedWidget" name="ntbkNewPrinter" >
4281
 
-     <property name="currentIndex" >
4282
 
+  <layout class="QGridLayout">
4283
 
+   <item row="0" column="0" colspan="5">
4284
 
+    <widget class="QStackedWidget" name="ntbkNewPrinter">
4285
 
+     <property name="currentIndex">
4286
 
       <number>1</number>
4287
 
      </property>
4288
 
-     <widget class="QWidget" name="page" >
4289
 
-      <layout class="QGridLayout" >
4290
 
-       <item row="0" column="0" >
4291
 
-        <widget class="QLabel" name="label" >
4292
 
-         <property name="text" >
4293
 
+     <widget class="QWidget" name="page">
4294
 
+      <layout class="QGridLayout">
4295
 
+       <item row="0" column="0">
4296
 
+        <widget class="QLabel" name="label">
4297
 
+         <property name="text">
4298
 
           <string>Printer Name</string>
4299
 
          </property>
4300
 
         </widget>
4301
 
        </item>
4302
 
-       <item row="1" column="0" >
4303
 
-        <widget class="QLineEdit" name="entNPName" />
4304
 
+       <item row="1" column="0">
4305
 
+        <widget class="QLineEdit" name="entNPName"/>
4306
 
        </item>
4307
 
-       <item row="2" column="0" >
4308
 
-        <widget class="QLabel" name="label_2" >
4309
 
-         <property name="text" >
4310
 
+       <item row="2" column="0">
4311
 
+        <widget class="QLabel" name="label_2">
4312
 
+         <property name="text">
4313
 
           <string>Description</string>
4314
 
          </property>
4315
 
         </widget>
4316
 
        </item>
4317
 
-       <item row="3" column="0" >
4318
 
-        <widget class="QLineEdit" name="entNPDescription" />
4319
 
+       <item row="3" column="0">
4320
 
+        <widget class="QLineEdit" name="entNPDescription"/>
4321
 
        </item>
4322
 
-       <item row="4" column="0" >
4323
 
-        <widget class="QLabel" name="label_3" >
4324
 
-         <property name="text" >
4325
 
+       <item row="4" column="0">
4326
 
+        <widget class="QLabel" name="label_3">
4327
 
+         <property name="text">
4328
 
           <string>Location</string>
4329
 
          </property>
4330
 
         </widget>
4331
 
        </item>
4332
 
-       <item row="5" column="0" >
4333
 
-        <widget class="QLineEdit" name="entNPLocation" />
4334
 
+       <item row="5" column="0">
4335
 
+        <widget class="QLineEdit" name="entNPLocation"/>
4336
 
        </item>
4337
 
-       <item row="6" column="0" >
4338
 
+       <item row="6" column="0">
4339
 
         <spacer>
4340
 
-         <property name="orientation" >
4341
 
+         <property name="orientation">
4342
 
           <enum>Qt::Vertical</enum>
4343
 
          </property>
4344
 
-         <property name="sizeHint" stdset="0" >
4345
 
+         <property name="sizeHint" stdset="0">
4346
 
           <size>
4347
 
            <width>691</width>
4348
 
            <height>40</height>
4349
 
@@ -69,45 +70,45 @@
4350
 
        </item>
4351
 
       </layout>
4352
 
      </widget>
4353
 
-     <widget class="QWidget" name="page_3" >
4354
 
-      <layout class="QGridLayout" >
4355
 
-       <item row="0" column="0" colspan="3" >
4356
 
-        <widget class="QLabel" name="label_7" >
4357
 
-         <property name="text" >
4358
 
+     <widget class="QWidget" name="page_3">
4359
 
+      <layout class="QGridLayout">
4360
 
+       <item row="0" column="0" colspan="3">
4361
 
+        <widget class="QLabel" name="label_7">
4362
 
+         <property name="text">
4363
 
           <string>Select Connection</string>
4364
 
          </property>
4365
 
         </widget>
4366
 
        </item>
4367
 
-       <item row="1" column="0" >
4368
 
-        <widget class="QListWidget" name="tvNPDevices" />
4369
 
+       <item row="1" column="0">
4370
 
+        <widget class="QListWidget" name="tvNPDevices"/>
4371
 
        </item>
4372
 
-       <item row="1" column="1" >
4373
 
-        <widget class="QStackedWidget" name="ntbkNPType" >
4374
 
-         <property name="currentIndex" >
4375
 
+       <item row="1" column="1">
4376
 
+        <widget class="QStackedWidget" name="ntbkNPType">
4377
 
+         <property name="currentIndex">
4378
 
           <number>7</number>
4379
 
          </property>
4380
 
-         <widget class="QWidget" name="page_4" >
4381
 
-          <layout class="QGridLayout" >
4382
 
-           <item row="0" column="0" >
4383
 
-            <widget class="QLabel" name="label_8" >
4384
 
-             <property name="text" >
4385
 
+         <widget class="QWidget" name="page_4">
4386
 
+          <layout class="QGridLayout">
4387
 
+           <item row="0" column="0">
4388
 
+            <widget class="QLabel" name="label_8">
4389
 
+             <property name="text">
4390
 
               <string>Description</string>
4391
 
              </property>
4392
 
             </widget>
4393
 
            </item>
4394
 
-           <item row="1" column="0" >
4395
 
-            <widget class="QLabel" name="lblNPDeviceDescription" >
4396
 
-             <property name="text" >
4397
 
+           <item row="1" column="0">
4398
 
+            <widget class="QLabel" name="lblNPDeviceDescription">
4399
 
+             <property name="text">
4400
 
               <string>Device Description</string>
4401
 
              </property>
4402
 
             </widget>
4403
 
            </item>
4404
 
-           <item row="2" column="0" >
4405
 
+           <item row="2" column="0">
4406
 
             <spacer>
4407
 
-             <property name="orientation" >
4408
 
+             <property name="orientation">
4409
 
               <enum>Qt::Vertical</enum>
4410
 
              </property>
4411
 
-             <property name="sizeHint" stdset="0" >
4412
 
+             <property name="sizeHint" stdset="0">
4413
 
               <size>
4414
 
                <width>20</width>
4415
 
                <height>40</height>
4416
 
@@ -117,24 +118,24 @@
4417
 
            </item>
4418
 
           </layout>
4419
 
          </widget>
4420
 
-         <widget class="QWidget" name="page_5" >
4421
 
-          <layout class="QGridLayout" >
4422
 
-           <item row="0" column="0" >
4423
 
-            <widget class="QLabel" name="label_9" >
4424
 
-             <property name="text" >
4425
 
+         <widget class="QWidget" name="page_5">
4426
 
+          <layout class="QGridLayout">
4427
 
+           <item row="0" column="0">
4428
 
+            <widget class="QLabel" name="label_9">
4429
 
+             <property name="text">
4430
 
               <string>Enter Device URI</string>
4431
 
              </property>
4432
 
             </widget>
4433
 
            </item>
4434
 
-           <item row="1" column="0" >
4435
 
-            <widget class="QLineEdit" name="entNPTDevice" />
4436
 
+           <item row="1" column="0">
4437
 
+            <widget class="QLineEdit" name="entNPTDevice"/>
4438
 
            </item>
4439
 
-           <item row="2" column="0" >
4440
 
+           <item row="2" column="0">
4441
 
             <spacer>
4442
 
-             <property name="orientation" >
4443
 
+             <property name="orientation">
4444
 
               <enum>Qt::Vertical</enum>
4445
 
              </property>
4446
 
-             <property name="sizeHint" stdset="0" >
4447
 
+             <property name="sizeHint" stdset="0">
4448
 
               <size>
4449
 
                <width>20</width>
4450
 
                <height>330</height>
4451
 
@@ -144,41 +145,41 @@
4452
 
            </item>
4453
 
           </layout>
4454
 
          </widget>
4455
 
-         <widget class="QWidget" name="page_6" >
4456
 
-          <layout class="QGridLayout" >
4457
 
-           <item row="0" column="0" colspan="2" >
4458
 
-            <widget class="QLabel" name="label_10" >
4459
 
-             <property name="text" >
4460
 
+         <widget class="QWidget" name="page_6">
4461
 
+          <layout class="QGridLayout">
4462
 
+           <item row="0" column="0" colspan="2">
4463
 
+            <widget class="QLabel" name="label_10">
4464
 
+             <property name="text">
4465
 
               <string>Location of the Network Printer</string>
4466
 
              </property>
4467
 
             </widget>
4468
 
            </item>
4469
 
-           <item row="1" column="0" >
4470
 
-            <widget class="QLabel" name="label_11" >
4471
 
-             <property name="text" >
4472
 
+           <item row="1" column="0">
4473
 
+            <widget class="QLabel" name="label_11">
4474
 
+             <property name="text">
4475
 
               <string>Host:</string>
4476
 
              </property>
4477
 
             </widget>
4478
 
            </item>
4479
 
-           <item row="1" column="1" >
4480
 
-            <widget class="QLineEdit" name="entNPTDirectJetHostname" />
4481
 
+           <item row="1" column="1">
4482
 
+            <widget class="QLineEdit" name="entNPTDirectJetHostname"/>
4483
 
            </item>
4484
 
-           <item row="2" column="0" >
4485
 
-            <widget class="QLabel" name="label_12" >
4486
 
-             <property name="text" >
4487
 
+           <item row="2" column="0">
4488
 
+            <widget class="QLabel" name="label_12">
4489
 
+             <property name="text">
4490
 
               <string>Port number:</string>
4491
 
              </property>
4492
 
             </widget>
4493
 
            </item>
4494
 
-           <item row="2" column="1" >
4495
 
-            <widget class="QLineEdit" name="entNPTDirectJetPort" />
4496
 
+           <item row="2" column="1">
4497
 
+            <widget class="QLineEdit" name="entNPTDirectJetPort"/>
4498
 
            </item>
4499
 
-           <item row="3" column="0" colspan="2" >
4500
 
+           <item row="3" column="0" colspan="2">
4501
 
             <spacer>
4502
 
-             <property name="orientation" >
4503
 
+             <property name="orientation">
4504
 
               <enum>Qt::Vertical</enum>
4505
 
              </property>
4506
 
-             <property name="sizeHint" stdset="0" >
4507
 
+             <property name="sizeHint" stdset="0">
4508
 
               <size>
4509
 
                <width>328</width>
4510
 
                <height>299</height>
4511
 
@@ -188,72 +189,72 @@
4512
 
            </item>
4513
 
           </layout>
4514
 
          </widget>
4515
 
-         <widget class="QWidget" name="page_7" >
4516
 
-          <layout class="QGridLayout" name="gridLayout" >
4517
 
-           <item row="0" column="0" colspan="4" >
4518
 
-            <widget class="QLabel" name="label_13" >
4519
 
-             <property name="text" >
4520
 
+         <widget class="QWidget" name="page_7">
4521
 
+          <layout class="QGridLayout" name="gridLayout">
4522
 
+           <item row="0" column="0" colspan="4">
4523
 
+            <widget class="QLabel" name="label_13">
4524
 
+             <property name="text">
4525
 
               <string>IPP Printer</string>
4526
 
              </property>
4527
 
             </widget>
4528
 
            </item>
4529
 
-           <item row="1" column="0" >
4530
 
-            <widget class="QLabel" name="label_14" >
4531
 
-             <property name="text" >
4532
 
+           <item row="1" column="0">
4533
 
+            <widget class="QLabel" name="label_14">
4534
 
+             <property name="text">
4535
 
               <string>Host:</string>
4536
 
              </property>
4537
 
             </widget>
4538
 
            </item>
4539
 
-           <item row="1" column="1" colspan="2" >
4540
 
-            <widget class="QLineEdit" name="entNPTIPPHostname" />
4541
 
+           <item row="1" column="1" colspan="2">
4542
 
+            <widget class="QLineEdit" name="entNPTIPPHostname"/>
4543
 
            </item>
4544
 
-           <item row="1" column="3" >
4545
 
-            <widget class="QPushButton" name="btnIPPFindQueue" >
4546
 
-             <property name="enabled" >
4547
 
+           <item row="1" column="3">
4548
 
+            <widget class="QPushButton" name="btnIPPFindQueue">
4549
 
+             <property name="enabled">
4550
 
               <bool>true</bool>
4551
 
              </property>
4552
 
-             <property name="text" >
4553
 
+             <property name="text">
4554
 
               <string>Find Queue...</string>
4555
 
              </property>
4556
 
             </widget>
4557
 
            </item>
4558
 
-           <item row="2" column="0" >
4559
 
-            <widget class="QLabel" name="label_15" >
4560
 
-             <property name="text" >
4561
 
+           <item row="2" column="0">
4562
 
+            <widget class="QLabel" name="label_15">
4563
 
+             <property name="text">
4564
 
               <string>Queue:</string>
4565
 
              </property>
4566
 
             </widget>
4567
 
            </item>
4568
 
-           <item row="2" column="1" colspan="3" >
4569
 
-            <widget class="QLineEdit" name="entNPTIPPQueuename" />
4570
 
+           <item row="2" column="1" colspan="3">
4571
 
+            <widget class="QLineEdit" name="entNPTIPPQueuename"/>
4572
 
            </item>
4573
 
-           <item row="3" column="0" >
4574
 
-            <widget class="QLabel" name="label_34" >
4575
 
-             <property name="text" >
4576
 
+           <item row="3" column="0">
4577
 
+            <widget class="QLabel" name="label_34">
4578
 
+             <property name="text">
4579
 
               <string>URI:</string>
4580
 
              </property>
4581
 
             </widget>
4582
 
            </item>
4583
 
-           <item row="3" column="1" colspan="2" >
4584
 
-            <widget class="QLabel" name="lblIPPURI" >
4585
 
-             <property name="text" >
4586
 
+           <item row="3" column="1" colspan="2">
4587
 
+            <widget class="QLabel" name="lblIPPURI">
4588
 
+             <property name="text">
4589
 
               <string>...</string>
4590
 
              </property>
4591
 
             </widget>
4592
 
            </item>
4593
 
-           <item row="4" column="0" colspan="2" >
4594
 
-            <widget class="QPushButton" name="btnIPPVerify" >
4595
 
-             <property name="text" >
4596
 
+           <item row="4" column="0" colspan="2">
4597
 
+            <widget class="QPushButton" name="btnIPPVerify">
4598
 
+             <property name="text">
4599
 
               <string>Verify...</string>
4600
 
              </property>
4601
 
             </widget>
4602
 
            </item>
4603
 
-           <item row="4" column="2" colspan="2" >
4604
 
-            <spacer name="horizontalSpacer" >
4605
 
-             <property name="orientation" >
4606
 
+           <item row="4" column="2" colspan="2">
4607
 
+            <spacer name="horizontalSpacer">
4608
 
+             <property name="orientation">
4609
 
               <enum>Qt::Horizontal</enum>
4610
 
              </property>
4611
 
-             <property name="sizeHint" stdset="0" >
4612
 
+             <property name="sizeHint" stdset="0">
4613
 
               <size>
4614
 
                <width>298</width>
4615
 
                <height>20</height>
4616
 
@@ -261,12 +262,12 @@
4617
 
              </property>
4618
 
             </spacer>
4619
 
            </item>
4620
 
-           <item row="5" column="0" colspan="4" >
4621
 
-            <spacer name="verticalSpacer" >
4622
 
-             <property name="orientation" >
4623
 
+           <item row="5" column="0" colspan="4">
4624
 
+            <spacer name="verticalSpacer">
4625
 
+             <property name="orientation">
4626
 
               <enum>Qt::Vertical</enum>
4627
 
              </property>
4628
 
-             <property name="sizeHint" stdset="0" >
4629
 
+             <property name="sizeHint" stdset="0">
4630
 
               <size>
4631
 
                <width>418</width>
4632
 
                <height>297</height>
4633
 
@@ -276,61 +277,61 @@
4634
 
            </item>
4635
 
           </layout>
4636
 
          </widget>
4637
 
-         <widget class="QWidget" name="page_8" >
4638
 
-          <layout class="QGridLayout" name="gridLayout_3" >
4639
 
-           <item row="0" column="0" colspan="3" >
4640
 
-            <widget class="QLabel" name="label_17" >
4641
 
-             <property name="text" >
4642
 
+         <widget class="QWidget" name="page_8">
4643
 
+          <layout class="QGridLayout" name="gridLayout_3">
4644
 
+           <item row="0" column="0" colspan="3">
4645
 
+            <widget class="QLabel" name="label_17">
4646
 
+             <property name="text">
4647
 
               <string>Location of the LPD network printer</string>
4648
 
              </property>
4649
 
             </widget>
4650
 
            </item>
4651
 
-           <item row="1" column="0" >
4652
 
-            <widget class="QLabel" name="label_18" >
4653
 
-             <property name="text" >
4654
 
+           <item row="1" column="0">
4655
 
+            <widget class="QLabel" name="label_18">
4656
 
+             <property name="text">
4657
 
               <string>Host:</string>
4658
 
              </property>
4659
 
             </widget>
4660
 
            </item>
4661
 
-           <item row="1" column="1" >
4662
 
-            <widget class="QComboBox" name="cmbentNPTLpdHost" >
4663
 
-             <property name="editable" >
4664
 
+           <item row="1" column="1">
4665
 
+            <widget class="QComboBox" name="cmbentNPTLpdHost">
4666
 
+             <property name="editable">
4667
 
               <bool>true</bool>
4668
 
              </property>
4669
 
              <item>
4670
 
-              <property name="text" >
4671
 
-               <string comment="KDE::DoNotExtract">localhost</string>
4672
 
+              <property name="text">
4673
 
+               <string>localhost</string>
4674
 
               </property>
4675
 
              </item>
4676
 
             </widget>
4677
 
            </item>
4678
 
-           <item row="1" column="2" >
4679
 
-            <widget class="QPushButton" name="btnNPTLpdProbe" >
4680
 
-             <property name="text" >
4681
 
+           <item row="1" column="2">
4682
 
+            <widget class="QPushButton" name="btnNPTLpdProbe">
4683
 
+             <property name="text">
4684
 
               <string comment="Try to discover network printers">Probe</string>
4685
 
              </property>
4686
 
             </widget>
4687
 
            </item>
4688
 
-           <item row="2" column="0" >
4689
 
-            <widget class="QLabel" name="label_19" >
4690
 
-             <property name="text" >
4691
 
+           <item row="2" column="0">
4692
 
+            <widget class="QLabel" name="label_19">
4693
 
+             <property name="text">
4694
 
               <string>Queue:</string>
4695
 
              </property>
4696
 
             </widget>
4697
 
            </item>
4698
 
-           <item row="2" column="1" colspan="2" >
4699
 
-            <widget class="QComboBox" name="cmbentNPTLpdQueue" >
4700
 
-             <property name="editable" >
4701
 
+           <item row="2" column="1" colspan="2">
4702
 
+            <widget class="QComboBox" name="cmbentNPTLpdQueue">
4703
 
+             <property name="editable">
4704
 
               <bool>true</bool>
4705
 
              </property>
4706
 
             </widget>
4707
 
            </item>
4708
 
-           <item row="3" column="1" colspan="2" >
4709
 
+           <item row="3" column="1" colspan="2">
4710
 
             <spacer>
4711
 
-             <property name="orientation" >
4712
 
+             <property name="orientation">
4713
 
               <enum>Qt::Vertical</enum>
4714
 
              </property>
4715
 
-             <property name="sizeHint" stdset="0" >
4716
 
+             <property name="sizeHint" stdset="0">
4717
 
               <size>
4718
 
                <width>288</width>
4719
 
                <height>295</height>
4720
 
@@ -340,9 +341,9 @@
4721
 
            </item>
4722
 
           </layout>
4723
 
          </widget>
4724
 
-         <widget class="QWidget" name="page_9" >
4725
 
-          <widget class="QLabel" name="label_20" >
4726
 
-           <property name="geometry" >
4727
 
+         <widget class="QWidget" name="page_9">
4728
 
+          <widget class="QLabel" name="label_20">
4729
 
+           <property name="geometry">
4730
 
             <rect>
4731
 
              <x>30</x>
4732
 
              <y>80</y>
4733
 
@@ -350,14 +351,14 @@
4734
 
              <height>20</height>
4735
 
             </rect>
4736
 
            </property>
4737
 
-           <property name="text" >
4738
 
+           <property name="text">
4739
 
             <string comment="KDE::DoNotExtract">TODO, SCSI</string>
4740
 
            </property>
4741
 
           </widget>
4742
 
          </widget>
4743
 
-         <widget class="QWidget" name="page_10" >
4744
 
-          <widget class="QLabel" name="label_21" >
4745
 
-           <property name="geometry" >
4746
 
+         <widget class="QWidget" name="page_10">
4747
 
+          <widget class="QLabel" name="label_21">
4748
 
+           <property name="geometry">
4749
 
             <rect>
4750
 
              <x>60</x>
4751
 
              <y>90</y>
4752
 
@@ -365,144 +366,213 @@
4753
 
              <height>20</height>
4754
 
             </rect>
4755
 
            </property>
4756
 
-           <property name="text" >
4757
 
+           <property name="text">
4758
 
             <string comment="KDE::DoNotExtract">TODO serial</string>
4759
 
            </property>
4760
 
           </widget>
4761
 
          </widget>
4762
 
-         <widget class="QWidget" name="page_11" >
4763
 
-          <layout class="QGridLayout" name="gridLayout_4" >
4764
 
-           <item row="0" column="0" colspan="4" >
4765
 
-            <widget class="QLabel" name="label_22" >
4766
 
-             <property name="text" >
4767
 
+         <widget class="QWidget" name="page_11">
4768
 
+          <layout class="QGridLayout" name="gridLayout_2">
4769
 
+           <item row="0" column="0" colspan="3">
4770
 
+            <widget class="QLabel" name="label_22">
4771
 
+             <property name="text">
4772
 
               <string>SMB Printer</string>
4773
 
              </property>
4774
 
             </widget>
4775
 
            </item>
4776
 
-           <item row="1" column="0" >
4777
 
-            <widget class="QLabel" name="label_23" >
4778
 
-             <property name="text" >
4779
 
+           <item row="1" column="0">
4780
 
+            <widget class="QLabel" name="lblSMBUri">
4781
 
+             <property name="text">
4782
 
               <string comment="KDE::DoNotExtract">smb://</string>
4783
 
              </property>
4784
 
             </widget>
4785
 
            </item>
4786
 
-           <item row="1" column="1" colspan="2" >
4787
 
-            <widget class="QLineEdit" name="entSMBURI" />
4788
 
+           <item row="1" column="1">
4789
 
+            <widget class="QLineEdit" name="entSMBURI"/>
4790
 
            </item>
4791
 
-           <item row="1" column="3" >
4792
 
-            <widget class="QPushButton" name="btnSMBBrowse" >
4793
 
-             <property name="text" >
4794
 
+           <item row="1" column="2">
4795
 
+            <widget class="QPushButton" name="btnSMBBrowse">
4796
 
+             <property name="text">
4797
 
               <string>Browse</string>
4798
 
              </property>
4799
 
             </widget>
4800
 
            </item>
4801
 
-           <item row="2" column="0" colspan="4" >
4802
 
-            <widget class="QLabel" name="lblSMBHint" >
4803
 
-             <property name="text" >
4804
 
-              <string>&lt;i>smb://[workgroup/]server[:port]/printer&lt;/i></string>
4805
 
+           <item row="2" column="0" colspan="3">
4806
 
+            <widget class="QLabel" name="lblSMBHint">
4807
 
+             <property name="text">
4808
 
+              <string>&lt;i&gt;smb://[workgroup/]server[:port]/printer&lt;/i&gt;</string>
4809
 
              </property>
4810
 
             </widget>
4811
 
            </item>
4812
 
-           <item row="3" column="0" colspan="4" >
4813
 
-            <widget class="QLabel" name="label_16" >
4814
 
-             <property name="text" >
4815
 
+           <item row="3" column="0" colspan="3">
4816
 
+            <widget class="QLabel" name="label_16">
4817
 
+             <property name="text">
4818
 
               <string>Authentication</string>
4819
 
              </property>
4820
 
             </widget>
4821
 
            </item>
4822
 
-           <item row="4" column="0" colspan="4" >
4823
 
-            <widget class="QRadioButton" name="rbtnSMBAuthPrompt" >
4824
 
-             <property name="text" >
4825
 
+           <item row="4" column="0" colspan="3">
4826
 
+            <widget class="QRadioButton" name="rbtnSMBAuthPrompt">
4827
 
+             <property name="text">
4828
 
               <string>Prompt user if authentication is required</string>
4829
 
              </property>
4830
 
             </widget>
4831
 
            </item>
4832
 
-           <item row="5" column="0" colspan="4" >
4833
 
-            <widget class="QRadioButton" name="rbtnSMBAuthSet" >
4834
 
-             <property name="text" >
4835
 
+           <item row="5" column="0" colspan="3">
4836
 
+            <widget class="QRadioButton" name="rbtnSMBAuthSet">
4837
 
+             <property name="text">
4838
 
               <string>Set authentication details now</string>
4839
 
              </property>
4840
 
             </widget>
4841
 
            </item>
4842
 
-           <item row="6" column="0" colspan="2" >
4843
 
-            <spacer name="horizontalSpacer_2" >
4844
 
-             <property name="orientation" >
4845
 
-              <enum>Qt::Horizontal</enum>
4846
 
-             </property>
4847
 
-             <property name="sizeHint" stdset="0" >
4848
 
-              <size>
4849
 
-               <width>169</width>
4850
 
-               <height>68</height>
4851
 
-              </size>
4852
 
-             </property>
4853
 
-            </spacer>
4854
 
-           </item>
4855
 
-           <item row="6" column="2" colspan="2" >
4856
 
-            <widget class="QWidget" native="1" name="tblSMBAuth" >
4857
 
-             <layout class="QGridLayout" name="gridLayout_2" >
4858
 
-              <item row="1" column="1" >
4859
 
-               <widget class="QLineEdit" name="entSMBPassword" >
4860
 
-                <property name="echoMode" >
4861
 
-                 <enum>QLineEdit::Password</enum>
4862
 
-                </property>
4863
 
-               </widget>
4864
 
-              </item>
4865
 
-              <item row="1" column="0" >
4866
 
-               <widget class="QLabel" name="label_26" >
4867
 
-                <property name="text" >
4868
 
-                 <string>Password:</string>
4869
 
-                </property>
4870
 
-               </widget>
4871
 
-              </item>
4872
 
-              <item row="0" column="1" >
4873
 
-               <widget class="QLineEdit" name="entSMBUsername" />
4874
 
-              </item>
4875
 
-              <item row="0" column="0" >
4876
 
-               <widget class="QLabel" name="label_25" >
4877
 
-                <property name="text" >
4878
 
-                 <string>Username:</string>
4879
 
-                </property>
4880
 
-               </widget>
4881
 
-              </item>
4882
 
-             </layout>
4883
 
-             <zorder>entSMBPassword</zorder>
4884
 
-             <zorder>label_26</zorder>
4885
 
-             <zorder>entSMBUsername</zorder>
4886
 
-             <zorder>label_25</zorder>
4887
 
-            </widget>
4888
 
-           </item>
4889
 
-           <item row="7" column="0" colspan="2" >
4890
 
-            <widget class="QPushButton" name="btnSMBVerify" >
4891
 
-             <property name="text" >
4892
 
-              <string>Verify</string>
4893
 
-             </property>
4894
 
-            </widget>
4895
 
-           </item>
4896
 
-           <item row="7" column="2" colspan="2" >
4897
 
-            <spacer>
4898
 
-             <property name="orientation" >
4899
 
-              <enum>Qt::Horizontal</enum>
4900
 
-             </property>
4901
 
-             <property name="sizeHint" stdset="0" >
4902
 
-              <size>
4903
 
-               <width>188</width>
4904
 
-               <height>28</height>
4905
 
-              </size>
4906
 
-             </property>
4907
 
-            </spacer>
4908
 
-           </item>
4909
 
-           <item row="8" column="0" colspan="4" >
4910
 
-            <spacer>
4911
 
-             <property name="orientation" >
4912
 
-              <enum>Qt::Vertical</enum>
4913
 
-             </property>
4914
 
-             <property name="sizeHint" stdset="0" >
4915
 
-              <size>
4916
 
-               <width>404</width>
4917
 
-               <height>216</height>
4918
 
-              </size>
4919
 
-             </property>
4920
 
-            </spacer>
4921
 
+           <item row="6" column="0" colspan="3">
4922
 
+            <layout class="QVBoxLayout" name="verticalLayout">
4923
 
+             <item>
4924
 
+              <layout class="QHBoxLayout" name="horizontalLayout_2">
4925
 
+               <item>
4926
 
+                <spacer name="horizontalSpacer_2">
4927
 
+                 <property name="orientation">
4928
 
+                  <enum>Qt::Horizontal</enum>
4929
 
+                 </property>
4930
 
+                 <property name="sizeType">
4931
 
+                  <enum>QSizePolicy::Fixed</enum>
4932
 
+                 </property>
4933
 
+                 <property name="sizeHint" stdset="0">
4934
 
+                  <size>
4935
 
+                   <width>128</width>
4936
 
+                   <height>62</height>
4937
 
+                  </size>
4938
 
+                 </property>
4939
 
+                </spacer>
4940
 
+               </item>
4941
 
+               <item>
4942
 
+                <widget class="QWidget" name="tblSMBAuth" native="true">
4943
 
+                 <widget class="QLineEdit" name="entSMBPassword">
4944
 
+                  <property name="geometry">
4945
 
+                   <rect>
4946
 
+                    <x>76</x>
4947
 
+                    <y>35</y>
4948
 
+                    <width>115</width>
4949
 
+                    <height>27</height>
4950
 
+                   </rect>
4951
 
+                  </property>
4952
 
+                  <property name="echoMode">
4953
 
+                   <enum>QLineEdit::Password</enum>
4954
 
+                  </property>
4955
 
+                 </widget>
4956
 
+                 <widget class="QLabel" name="label_26">
4957
 
+                  <property name="geometry">
4958
 
+                   <rect>
4959
 
+                    <x>4</x>
4960
 
+                    <y>35</y>
4961
 
+                    <width>68</width>
4962
 
+                    <height>27</height>
4963
 
+                   </rect>
4964
 
+                  </property>
4965
 
+                  <property name="text">
4966
 
+                   <string>Password:</string>
4967
 
+                  </property>
4968
 
+                 </widget>
4969
 
+                 <widget class="QLineEdit" name="entSMBUsername">
4970
 
+                  <property name="geometry">
4971
 
+                   <rect>
4972
 
+                    <x>76</x>
4973
 
+                    <y>4</y>
4974
 
+                    <width>115</width>
4975
 
+                    <height>27</height>
4976
 
+                   </rect>
4977
 
+                  </property>
4978
 
+                 </widget>
4979
 
+                 <widget class="QLabel" name="label_25">
4980
 
+                  <property name="geometry">
4981
 
+                   <rect>
4982
 
+                    <x>4</x>
4983
 
+                    <y>4</y>
4984
 
+                    <width>68</width>
4985
 
+                    <height>27</height>
4986
 
+                   </rect>
4987
 
+                  </property>
4988
 
+                  <property name="text">
4989
 
+                   <string>Username:</string>
4990
 
+                  </property>
4991
 
+                 </widget>
4992
 
+                </widget>
4993
 
+               </item>
4994
 
+               <item>
4995
 
+                <spacer name="horizontalSpacer_3">
4996
 
+                 <property name="orientation">
4997
 
+                  <enum>Qt::Horizontal</enum>
4998
 
+                 </property>
4999
 
+                 <property name="sizeType">
5000
 
+                  <enum>QSizePolicy::Fixed</enum>
5001
 
+                 </property>
5002
 
+                 <property name="sizeHint" stdset="0">
5003
 
+                  <size>
5004
 
+                   <width>68</width>
5005
 
+                   <height>17</height>
5006
 
+                  </size>
5007
 
+                 </property>
5008
 
+                </spacer>
5009
 
+               </item>
5010
 
+              </layout>
5011
 
+             </item>
5012
 
+             <item>
5013
 
+              <layout class="QHBoxLayout" name="horizontalLayout">
5014
 
+               <item>
5015
 
+                <spacer>
5016
 
+                 <property name="orientation">
5017
 
+                  <enum>Qt::Horizontal</enum>
5018
 
+                 </property>
5019
 
+                 <property name="sizeType">
5020
 
+                  <enum>QSizePolicy::Minimum</enum>
5021
 
+                 </property>
5022
 
+                 <property name="sizeHint" stdset="0">
5023
 
+                  <size>
5024
 
+                   <width>198</width>
5025
 
+                   <height>22</height>
5026
 
+                  </size>
5027
 
+                 </property>
5028
 
+                </spacer>
5029
 
+               </item>
5030
 
+               <item>
5031
 
+                <widget class="QPushButton" name="btnSMBVerify">
5032
 
+                 <property name="text">
5033
 
+                  <string>Verify</string>
5034
 
+                 </property>
5035
 
+                </widget>
5036
 
+               </item>
5037
 
+               <item>
5038
 
+                <spacer name="horizontalSpacer_4">
5039
 
+                 <property name="orientation">
5040
 
+                  <enum>Qt::Horizontal</enum>
5041
 
+                 </property>
5042
 
+                 <property name="sizeType">
5043
 
+                  <enum>QSizePolicy::Fixed</enum>
5044
 
+                 </property>
5045
 
+                 <property name="sizeHint" stdset="0">
5046
 
+                  <size>
5047
 
+                   <width>78</width>
5048
 
+                   <height>20</height>
5049
 
+                  </size>
5050
 
+                 </property>
5051
 
+                </spacer>
5052
 
+               </item>
5053
 
+              </layout>
5054
 
+             </item>
5055
 
+             <item>
5056
 
+              <spacer>
5057
 
+               <property name="orientation">
5058
 
+                <enum>Qt::Vertical</enum>
5059
 
+               </property>
5060
 
+               <property name="sizeHint" stdset="0">
5061
 
+                <size>
5062
 
+                 <width>415</width>
5063
 
+                 <height>208</height>
5064
 
+                </size>
5065
 
+               </property>
5066
 
+              </spacer>
5067
 
+             </item>
5068
 
+            </layout>
5069
 
            </item>
5070
 
           </layout>
5071
 
          </widget>
5072
 
@@ -510,118 +580,118 @@
5073
 
        </item>
5074
 
       </layout>
5075
 
      </widget>
5076
 
-     <widget class="QWidget" name="page_12" >
5077
 
-      <layout class="QGridLayout" >
5078
 
-       <item row="0" column="0" colspan="2" >
5079
 
-        <widget class="QRadioButton" name="rbtnNPFoomatic" >
5080
 
-         <property name="text" >
5081
 
+     <widget class="QWidget" name="page_12">
5082
 
+      <layout class="QGridLayout">
5083
 
+       <item row="0" column="0" colspan="2">
5084
 
+        <widget class="QRadioButton" name="rbtnNPFoomatic">
5085
 
+         <property name="text">
5086
 
           <string>Select printer from database</string>
5087
 
          </property>
5088
 
         </widget>
5089
 
        </item>
5090
 
-       <item row="1" column="0" colspan="2" >
5091
 
-        <widget class="QLabel" name="label_27" >
5092
 
-         <property name="text" >
5093
 
+       <item row="1" column="0" colspan="2">
5094
 
+        <widget class="QLabel" name="label_27">
5095
 
+         <property name="text">
5096
 
           <string>The foomatic printer database contains various manufacturer provided PostScript Printer Description (PPD) files and also can generate PPD files for a large number of (non PostScript) printers. But in general manufacturer provided PPD files provide better access to the specific features of the printer.</string>
5097
 
          </property>
5098
 
-         <property name="wordWrap" >
5099
 
+         <property name="wordWrap">
5100
 
           <bool>true</bool>
5101
 
          </property>
5102
 
         </widget>
5103
 
        </item>
5104
 
-       <item row="2" column="0" colspan="2" >
5105
 
-        <widget class="QListWidget" name="tvNPMakes" />
5106
 
+       <item row="2" column="0" colspan="2">
5107
 
+        <widget class="QListWidget" name="tvNPMakes"/>
5108
 
        </item>
5109
 
-       <item row="3" column="0" colspan="2" >
5110
 
-        <widget class="QRadioButton" name="rbtnNPPPD" >
5111
 
-         <property name="text" >
5112
 
+       <item row="3" column="0" colspan="2">
5113
 
+        <widget class="QRadioButton" name="rbtnNPPPD">
5114
 
+         <property name="text">
5115
 
           <string>Provide PPD file</string>
5116
 
          </property>
5117
 
         </widget>
5118
 
        </item>
5119
 
-       <item row="4" column="0" colspan="2" >
5120
 
-        <widget class="QLabel" name="label_28" >
5121
 
-         <property name="text" >
5122
 
-          <string>&lt;qt>PostScript Printer Description (PPD) files can often be found on the driver disk that comes with the printer. For PostScript printers they are often part of the Windows&lt;sup>®&lt;/sup> driver.&lt;/qt></string>
5123
 
+       <item row="4" column="0" colspan="2">
5124
 
+        <widget class="QLabel" name="label_28">
5125
 
+         <property name="text">
5126
 
+          <string>&lt;qt&gt;PostScript Printer Description (PPD) files can often be found on the driver disk that comes with the printer. For PostScript printers they are often part of the Windows&lt;sup&gt;®&lt;/sup&gt; driver.&lt;/qt&gt;</string>
5127
 
          </property>
5128
 
-         <property name="wordWrap" >
5129
 
+         <property name="wordWrap">
5130
 
           <bool>true</bool>
5131
 
          </property>
5132
 
         </widget>
5133
 
        </item>
5134
 
-       <item row="5" column="0" >
5135
 
-        <widget class="QLineEdit" name="filechooserPPD" />
5136
 
+       <item row="5" column="0">
5137
 
+        <widget class="QLineEdit" name="filechooserPPD"/>
5138
 
        </item>
5139
 
-       <item row="5" column="1" >
5140
 
-        <widget class="QPushButton" name="filechooserPPDButton" >
5141
 
-         <property name="text" >
5142
 
+       <item row="5" column="1">
5143
 
+        <widget class="QPushButton" name="filechooserPPDButton">
5144
 
+         <property name="text">
5145
 
           <string>Browse</string>
5146
 
          </property>
5147
 
         </widget>
5148
 
        </item>
5149
 
-       <item row="6" column="0" colspan="2" >
5150
 
-        <widget class="QWidget" native="1" name="downloadableDriverSearchFrame" >
5151
 
-         <layout class="QGridLayout" >
5152
 
-          <item row="0" column="0" colspan="3" >
5153
 
-           <widget class="QRadioButton" name="rbtnNPDownloadableDriverSearch" >
5154
 
-            <property name="text" >
5155
 
+       <item row="6" column="0" colspan="2">
5156
 
+        <widget class="QWidget" name="downloadableDriverSearchFrame" native="true">
5157
 
+         <layout class="QGridLayout">
5158
 
+          <item row="0" column="0" colspan="3">
5159
 
+           <widget class="QRadioButton" name="rbtnNPDownloadableDriverSearch">
5160
 
+            <property name="text">
5161
 
              <string>Search for a printer driver to download</string>
5162
 
             </property>
5163
 
            </widget>
5164
 
           </item>
5165
 
-          <item row="1" column="0" colspan="3" >
5166
 
-           <widget class="QLabel" name="label_29" >
5167
 
-            <property name="text" >
5168
 
+          <item row="1" column="0" colspan="3">
5169
 
+           <widget class="QLabel" name="label_29">
5170
 
+            <property name="text">
5171
 
              <string>Enter some search terms for the model of your printer.</string>
5172
 
             </property>
5173
 
            </widget>
5174
 
           </item>
5175
 
-          <item row="2" column="0" >
5176
 
-           <widget class="QLabel" name="label_30" >
5177
 
-            <property name="text" >
5178
 
+          <item row="2" column="0">
5179
 
+           <widget class="QLabel" name="label_30">
5180
 
+            <property name="text">
5181
 
              <string>Search terms:</string>
5182
 
             </property>
5183
 
            </widget>
5184
 
           </item>
5185
 
-          <item row="2" column="1" >
5186
 
-           <widget class="QLineEdit" name="entNPDownloadableDriverSearch" />
5187
 
+          <item row="2" column="1">
5188
 
+           <widget class="QLineEdit" name="entNPDownloadableDriverSearch"/>
5189
 
           </item>
5190
 
-          <item row="2" column="2" >
5191
 
-           <widget class="QPushButton" name="btnNPDownloadableDriverSearch" >
5192
 
-            <property name="text" >
5193
 
+          <item row="2" column="2">
5194
 
+           <widget class="QPushButton" name="btnNPDownloadableDriverSearch">
5195
 
+            <property name="text">
5196
 
              <string>Search</string>
5197
 
             </property>
5198
 
            </widget>
5199
 
           </item>
5200
 
-          <item row="3" column="0" >
5201
 
-           <widget class="QLabel" name="label_31" >
5202
 
-            <property name="text" >
5203
 
+          <item row="3" column="0">
5204
 
+           <widget class="QLabel" name="label_31">
5205
 
+            <property name="text">
5206
 
              <string>Printer model:</string>
5207
 
             </property>
5208
 
            </widget>
5209
 
           </item>
5210
 
-          <item row="3" column="1" colspan="2" >
5211
 
-           <widget class="QComboBox" name="cmbNPDownloadableDriverFoundPrinters" />
5212
 
+          <item row="3" column="1" colspan="2">
5213
 
+           <widget class="QComboBox" name="cmbNPDownloadableDriverFoundPrinters"/>
5214
 
           </item>
5215
 
          </layout>
5216
 
         </widget>
5217
 
        </item>
5218
 
       </layout>
5219
 
      </widget>
5220
 
-     <widget class="QWidget" name="page_13" >
5221
 
-      <layout class="QGridLayout" >
5222
 
-       <item rowspan="2" row="1" column="0" >
5223
 
-        <widget class="QListWidget" name="tvNPModels" />
5224
 
+     <widget class="QWidget" name="page_13">
5225
 
+      <layout class="QGridLayout">
5226
 
+       <item row="1" column="0" rowspan="2">
5227
 
+        <widget class="QListWidget" name="tvNPModels"/>
5228
 
        </item>
5229
 
-       <item row="1" column="1" colspan="2" >
5230
 
-        <widget class="QListWidget" name="tvNPDrivers" />
5231
 
+       <item row="1" column="1" colspan="2">
5232
 
+        <widget class="QListWidget" name="tvNPDrivers"/>
5233
 
        </item>
5234
 
-       <item row="2" column="1" >
5235
 
+       <item row="2" column="1">
5236
 
         <spacer>
5237
 
-         <property name="orientation" >
5238
 
+         <property name="orientation">
5239
 
           <enum>Qt::Horizontal</enum>
5240
 
          </property>
5241
 
-         <property name="sizeHint" stdset="0" >
5242
 
+         <property name="sizeHint" stdset="0">
5243
 
           <size>
5244
 
            <width>296</width>
5245
 
            <height>28</height>
5246
 
@@ -629,55 +699,55 @@
5247
 
          </property>
5248
 
         </spacer>
5249
 
        </item>
5250
 
-       <item row="2" column="2" >
5251
 
-        <widget class="QPushButton" name="btnNPPDComments" >
5252
 
-         <property name="text" >
5253
 
+       <item row="2" column="2">
5254
 
+        <widget class="QPushButton" name="btnNPPDComments">
5255
 
+         <property name="text">
5256
 
           <string>Comments</string>
5257
 
          </property>
5258
 
         </widget>
5259
 
        </item>
5260
 
-       <item row="0" column="0" >
5261
 
-        <widget class="QLabel" name="label_32" >
5262
 
-         <property name="text" >
5263
 
+       <item row="0" column="0">
5264
 
+        <widget class="QLabel" name="label_32">
5265
 
+         <property name="text">
5266
 
           <string>Models:</string>
5267
 
          </property>
5268
 
         </widget>
5269
 
        </item>
5270
 
-       <item row="0" column="1" >
5271
 
-        <widget class="QLabel" name="label_33" >
5272
 
-         <property name="text" >
5273
 
+       <item row="0" column="1">
5274
 
+        <widget class="QLabel" name="label_33">
5275
 
+         <property name="text">
5276
 
           <string>Driver:</string>
5277
 
          </property>
5278
 
         </widget>
5279
 
        </item>
5280
 
       </layout>
5281
 
      </widget>
5282
 
-     <widget class="QWidget" name="page_2" >
5283
 
-      <layout class="QGridLayout" >
5284
 
-       <item row="0" column="0" >
5285
 
-        <widget class="QLabel" name="label_4" >
5286
 
-         <property name="text" >
5287
 
+     <widget class="QWidget" name="page_2">
5288
 
+      <layout class="QGridLayout">
5289
 
+       <item row="0" column="0">
5290
 
+        <widget class="QLabel" name="label_4">
5291
 
+         <property name="text">
5292
 
           <string>Printers to be members of this class</string>
5293
 
          </property>
5294
 
         </widget>
5295
 
        </item>
5296
 
-       <item row="1" column="0" >
5297
 
-        <layout class="QGridLayout" >
5298
 
-         <item row="0" column="0" >
5299
 
-          <widget class="QLabel" name="label_6" >
5300
 
-           <property name="text" >
5301
 
+       <item row="1" column="0">
5302
 
+        <layout class="QGridLayout">
5303
 
+         <item row="0" column="0">
5304
 
+          <widget class="QLabel" name="label_6">
5305
 
+           <property name="text">
5306
 
             <string>Members of this class</string>
5307
 
            </property>
5308
 
           </widget>
5309
 
          </item>
5310
 
-         <item rowspan="2" row="0" column="1" >
5311
 
-          <layout class="QVBoxLayout" >
5312
 
+         <item row="0" column="1" rowspan="2">
5313
 
+          <layout class="QVBoxLayout">
5314
 
            <item>
5315
 
             <spacer>
5316
 
-             <property name="orientation" >
5317
 
+             <property name="orientation">
5318
 
               <enum>Qt::Vertical</enum>
5319
 
              </property>
5320
 
-             <property name="sizeHint" stdset="0" >
5321
 
+             <property name="sizeHint" stdset="0">
5322
 
               <size>
5323
 
                <width>20</width>
5324
 
                <height>40</height>
5325
 
@@ -686,25 +756,25 @@
5326
 
             </spacer>
5327
 
            </item>
5328
 
            <item>
5329
 
-            <widget class="QPushButton" name="btnNCAddMember" >
5330
 
-             <property name="text" >
5331
 
-              <string>&lt;</string>
5332
 
+            <widget class="QPushButton" name="btnNCAddMember">
5333
 
+             <property name="text">
5334
 
+              <string/>
5335
 
              </property>
5336
 
             </widget>
5337
 
            </item>
5338
 
            <item>
5339
 
-            <widget class="QPushButton" name="btnNCDelMember" >
5340
 
-             <property name="text" >
5341
 
-              <string>></string>
5342
 
+            <widget class="QPushButton" name="btnNCDelMember">
5343
 
+             <property name="text">
5344
 
+              <string/>
5345
 
              </property>
5346
 
             </widget>
5347
 
            </item>
5348
 
            <item>
5349
 
             <spacer>
5350
 
-             <property name="orientation" >
5351
 
+             <property name="orientation">
5352
 
               <enum>Qt::Vertical</enum>
5353
 
              </property>
5354
 
-             <property name="sizeHint" stdset="0" >
5355
 
+             <property name="sizeHint" stdset="0">
5356
 
               <size>
5357
 
                <width>20</width>
5358
 
                <height>291</height>
5359
 
@@ -714,72 +784,72 @@
5360
 
            </item>
5361
 
           </layout>
5362
 
          </item>
5363
 
-         <item row="0" column="2" >
5364
 
-          <widget class="QLabel" name="label_5" >
5365
 
-           <property name="text" >
5366
 
+         <item row="0" column="2">
5367
 
+          <widget class="QLabel" name="label_5">
5368
 
+           <property name="text">
5369
 
             <string>Others</string>
5370
 
            </property>
5371
 
           </widget>
5372
 
          </item>
5373
 
-         <item row="1" column="0" >
5374
 
-          <widget class="QListWidget" name="tvNCMembers" />
5375
 
+         <item row="1" column="0">
5376
 
+          <widget class="QListWidget" name="tvNCMembers"/>
5377
 
          </item>
5378
 
-         <item row="1" column="2" >
5379
 
-          <widget class="QListWidget" name="tvNCNotMembers" />
5380
 
+         <item row="1" column="2">
5381
 
+          <widget class="QListWidget" name="tvNCNotMembers"/>
5382
 
          </item>
5383
 
         </layout>
5384
 
        </item>
5385
 
       </layout>
5386
 
      </widget>
5387
 
-     <widget class="QWidget" name="page_14" >
5388
 
-      <layout class="QGridLayout" name="gridLayout_5" >
5389
 
-       <item row="0" column="0" >
5390
 
-        <widget class="QLabel" name="label_24" >
5391
 
-         <property name="text" >
5392
 
+     <widget class="QWidget" name="page_14">
5393
 
+      <layout class="QGridLayout" name="gridLayout_5">
5394
 
+       <item row="0" column="0">
5395
 
+        <widget class="QLabel" name="label_24">
5396
 
+         <property name="text">
5397
 
           <string>Try to transfer the current settings</string>
5398
 
          </property>
5399
 
         </widget>
5400
 
        </item>
5401
 
-       <item row="1" column="0" >
5402
 
-        <widget class="QRadioButton" name="rbtnChangePPDasIs" >
5403
 
-         <property name="text" >
5404
 
+       <item row="1" column="0">
5405
 
+        <widget class="QRadioButton" name="rbtnChangePPDasIs">
5406
 
+         <property name="text">
5407
 
           <string>Use the new PPD (Postscript Printer Description) as is.</string>
5408
 
          </property>
5409
 
         </widget>
5410
 
        </item>
5411
 
-       <item row="2" column="0" >
5412
 
-        <widget class="QLabel" name="label_37" >
5413
 
-         <property name="text" >
5414
 
-          <string>This way all current option settings will be lost. The default settings of the new PPD will be used.</string>
5415
 
+       <item row="2" column="0">
5416
 
+        <widget class="QLabel" name="label_37">
5417
 
+         <property name="text">
5418
 
+          <string>This way all current option settings will be lost. The default settings of the new PPD will be used. </string>
5419
 
          </property>
5420
 
-         <property name="wordWrap" >
5421
 
+         <property name="wordWrap">
5422
 
           <bool>true</bool>
5423
 
          </property>
5424
 
         </widget>
5425
 
        </item>
5426
 
-       <item row="3" column="0" >
5427
 
-        <widget class="QRadioButton" name="rbtnChangePPDKeepSettings" >
5428
 
-         <property name="text" >
5429
 
-          <string>Try to copy the option settings over from the old PPD.</string>
5430
 
+       <item row="3" column="0">
5431
 
+        <widget class="QRadioButton" name="rbtnChangePPDKeepSettings">
5432
 
+         <property name="text">
5433
 
+          <string>Try to copy the option settings over from the old PPD. </string>
5434
 
          </property>
5435
 
         </widget>
5436
 
        </item>
5437
 
-       <item row="4" column="0" >
5438
 
-        <widget class="QLabel" name="label_38" >
5439
 
-         <property name="text" >
5440
 
+       <item row="4" column="0">
5441
 
+        <widget class="QLabel" name="label_38">
5442
 
+         <property name="text">
5443
 
           <string>This is done by assuming that options with the same name do have the same meaning. Settings of options that are not present in the new PPD will be lost and options only present in the new PPD will be set to default.</string>
5444
 
          </property>
5445
 
-         <property name="wordWrap" >
5446
 
+         <property name="wordWrap">
5447
 
           <bool>true</bool>
5448
 
          </property>
5449
 
         </widget>
5450
 
        </item>
5451
 
-       <item row="6" column="0" >
5452
 
-        <spacer name="verticalSpacer_2" >
5453
 
-         <property name="orientation" >
5454
 
+       <item row="6" column="0">
5455
 
+        <spacer name="verticalSpacer_2">
5456
 
+         <property name="orientation">
5457
 
           <enum>Qt::Vertical</enum>
5458
 
          </property>
5459
 
-         <property name="sizeHint" stdset="0" >
5460
 
+         <property name="sizeHint" stdset="0">
5461
 
           <size>
5462
 
            <width>638</width>
5463
 
            <height>317</height>
5464
 
@@ -787,14 +857,14 @@
5465
 
          </property>
5466
 
         </spacer>
5467
 
        </item>
5468
 
-       <item row="5" column="0" >
5469
 
-        <layout class="QFormLayout" name="formLayout" />
5470
 
+       <item row="5" column="0">
5471
 
+        <layout class="QFormLayout" name="formLayout"/>
5472
 
        </item>
5473
 
       </layout>
5474
 
      </widget>
5475
 
-     <widget class="QWidget" name="page_15" >
5476
 
-      <widget class="QLabel" name="label_35" >
5477
 
-       <property name="geometry" >
5478
 
+     <widget class="QWidget" name="page_15">
5479
 
+      <widget class="QLabel" name="label_35">
5480
 
+       <property name="geometry">
5481
 
         <rect>
5482
 
          <x>60</x>
5483
 
          <y>50</y>
5484
 
@@ -802,14 +872,14 @@
5485
 
          <height>20</height>
5486
 
         </rect>
5487
 
        </property>
5488
 
-       <property name="text" >
5489
 
+       <property name="text">
5490
 
         <string comment="KDE::DoNotExtract">TODO: Installed Options page</string>
5491
 
        </property>
5492
 
       </widget>
5493
 
      </widget>
5494
 
-     <widget class="QWidget" name="page_16" >
5495
 
-      <widget class="QLabel" name="label_36" >
5496
 
-       <property name="geometry" >
5497
 
+     <widget class="QWidget" name="page_16">
5498
 
+      <widget class="QLabel" name="label_36">
5499
 
+       <property name="geometry">
5500
 
         <rect>
5501
 
          <x>30</x>
5502
 
          <y>60</y>
5503
 
@@ -817,19 +887,19 @@
5504
 
          <height>20</height>
5505
 
         </rect>
5506
 
        </property>
5507
 
-       <property name="text" >
5508
 
+       <property name="text">
5509
 
         <string comment="KDE::DoNotExtract">TODO: Downloadable Driver page</string>
5510
 
        </property>
5511
 
       </widget>
5512
 
      </widget>
5513
 
     </widget>
5514
 
    </item>
5515
 
-   <item row="1" column="0" >
5516
 
+   <item row="1" column="0">
5517
 
     <spacer>
5518
 
-     <property name="orientation" >
5519
 
+     <property name="orientation">
5520
 
       <enum>Qt::Horizontal</enum>
5521
 
      </property>
5522
 
-     <property name="sizeHint" stdset="0" >
5523
 
+     <property name="sizeHint" stdset="0">
5524
 
       <size>
5525
 
        <width>121</width>
5526
 
        <height>20</height>
5527
 
@@ -837,30 +907,30 @@
5528
 
      </property>
5529
 
     </spacer>
5530
 
    </item>
5531
 
-   <item row="1" column="1" >
5532
 
-    <widget class="QPushButton" name="btnNPBack" >
5533
 
-     <property name="text" >
5534
 
-      <string>&lt; Back</string>
5535
 
+   <item row="1" column="1">
5536
 
+    <widget class="QPushButton" name="btnNPBack">
5537
 
+     <property name="text">
5538
 
+      <string>Back</string>
5539
 
      </property>
5540
 
     </widget>
5541
 
    </item>
5542
 
-   <item row="1" column="2" >
5543
 
-    <widget class="QPushButton" name="btnNPForward" >
5544
 
-     <property name="text" >
5545
 
-      <string>Forward ></string>
5546
 
+   <item row="1" column="2">
5547
 
+    <widget class="QPushButton" name="btnNPForward">
5548
 
+     <property name="text">
5549
 
+      <string>Forward</string>
5550
 
      </property>
5551
 
     </widget>
5552
 
    </item>
5553
 
-   <item row="1" column="3" >
5554
 
-    <widget class="QPushButton" name="btnNPApply" >
5555
 
-     <property name="text" >
5556
 
+   <item row="1" column="3">
5557
 
+    <widget class="QPushButton" name="btnNPApply">
5558
 
+     <property name="text">
5559
 
       <string>OK</string>
5560
 
      </property>
5561
 
     </widget>
5562
 
    </item>
5563
 
-   <item row="1" column="4" >
5564
 
-    <widget class="QPushButton" name="btnNPCancel" >
5565
 
-     <property name="text" >
5566
 
+   <item row="1" column="4">
5567
 
+    <widget class="QPushButton" name="btnNPCancel">
5568
 
+     <property name="text">
5569
 
       <string>Cancel</string>
5570
 
      </property>
5571
 
     </widget>
5572
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/options.py kdeadmin-4.2.2/system-config-printer-kde/options.py
5573
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/options.py    1970-01-01 01:00:00.000000000 +0100
5574
 
+++ kdeadmin-4.2.2/system-config-printer-kde/options.py 2009-04-09 22:56:08.000000000 +0100
5575
 
@@ -0,0 +1,398 @@
5576
 
+# -*- coding: utf-8 -*-
5577
 
+## system-config-printer
5578
 
+
5579
 
+#############################################################################
5580
 
+##
5581
 
+## Copyright 2007-2009 Canonical Ltd
5582
 
+## Copyright 2008-2009 Richard Birnie <arbyuk@googlemail.com>
5583
 
+## Author: Jonathan Riddell <jriddell@ubuntu.com>
5584
 
+##         Richard Birnie <arbyuk@googlemail.com>
5585
 
+##
5586
 
+## Includes code from System Config Printer:
5587
 
+## Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
5588
 
+## Copyright (C) 2006, 2007 Florian Festi <ffesti@redhat.com>
5589
 
+## Copyright (C) 2006, 2007, 2008 Tim Waugh <twaugh@redhat.com>
5590
 
+##
5591
 
+## This program is free software; you can redistribute it and/or
5592
 
+## modify it under the terms of the GNU General Public License as
5593
 
+## published by the Free Software Foundation; either version 2 of
5594
 
+## the License, or (at your option) any later version.
5595
 
+##
5596
 
+## This program is distributed in the hope that it will be useful,
5597
 
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
5598
 
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5599
 
+## GNU General Public License for more details.
5600
 
+##
5601
 
+## You should have received a copy of the GNU General Public License
5602
 
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
5603
 
+##
5604
 
+#############################################################################
5605
 
+
5606
 
+from PyQt4.QtCore import *
5607
 
+from PyQt4.QtGui import *
5608
 
+
5609
 
+"""
5610
 
+These classes are used in the Job Options tab of the printer config dialogue
5611
 
+"""
5612
 
+
5613
 
+def OptionWidget(name, v, s, on_change):
5614
 
+    if isinstance(v, list):
5615
 
+        # XXX
5616
 
+        if isinstance(s, list):
5617
 
+            for vv in v + s:
5618
 
+                if not isinstance(vv, str): raise ValueError
5619
 
+            return OptionSelectMany(name, v, s, on_change)
5620
 
+        print v, s
5621
 
+        raise NotImplemented
5622
 
+    else:
5623
 
+        if (isinstance(s, int) or
5624
 
+            isinstance(s, float) or
5625
 
+            (isinstance(s, tuple) and
5626
 
+             len(s) == 2 and
5627
 
+             ((isinstance(s[0], int) and isinstance(s[1], int)) or
5628
 
+              (isinstance(s[0], float) and isinstance(s[1], float))))):
5629
 
+            try:
5630
 
+                if (isinstance(s, int) or
5631
 
+                    isinstance(s, tuple) and isinstance(s[0], int)):
5632
 
+                    v = int(v)
5633
 
+                else:
5634
 
+                    v = float(v)
5635
 
+            except ValueError:
5636
 
+                return OptionText(name, v, "", on_change)
5637
 
+            return OptionNumeric(name, v, s, on_change)
5638
 
+        elif isinstance(s, list):
5639
 
+            for sv in s:
5640
 
+                if not isinstance(sv, int):
5641
 
+                    return OptionSelectOne(name, v, s, on_change)
5642
 
+            try:
5643
 
+                v = int(v)
5644
 
+            except ValueError:
5645
 
+                return OptionSelectOne(name, v, s, on_change)
5646
 
+            return OptionSelectOneNumber(name, v, s, on_change)
5647
 
+        elif isinstance(s, str):
5648
 
+            return OptionText(name, v, s, on_change)
5649
 
+        else:
5650
 
+            raise ValueError
5651
 
+
5652
 
+# ---------------------------------------------------------------------------
5653
 
+
5654
 
+class OptionInterface:
5655
 
+    def get_current_value(self):
5656
 
+        raise NotImplemented
5657
 
+
5658
 
+    def is_changed(self):
5659
 
+        raise NotImplemented
5660
 
+
5661
 
+class OptionAlwaysShown(OptionInterface):
5662
 
+    # States
5663
 
+    STATE_UNCHANGED=0
5664
 
+    STATE_RESET=1
5665
 
+    STATE_ADJUSTED=2
5666
 
+
5667
 
+    def __init__(self, name, ipp_type, system_default,
5668
 
+                 widget, button, combobox_map = None, use_supported = False):
5669
 
+        self.name = name
5670
 
+        self.widget = widget
5671
 
+        self.button = button
5672
 
+        if ipp_type == bool:
5673
 
+            def bool_type (x):
5674
 
+                if type (x) == str:
5675
 
+                    if x.lower () in ("false", "no", "off"):
5676
 
+                        return False
5677
 
+                    # Even the empty string is true.
5678
 
+                    return True
5679
 
+                return bool (x)
5680
 
+            ipp_type = bool_type
5681
 
+        self.ipp_type = ipp_type
5682
 
+        self.set_default (system_default)
5683
 
+        self.combobox_map = combobox_map
5684
 
+        if combobox_map != None and ipp_type == int:
5685
 
+            i = 0
5686
 
+            dict = {}
5687
 
+            while i < self.widget.count():
5688
 
+                dict[combobox_map[i]] = self.widget.itemText(i)
5689
 
+                i += 1
5690
 
+            self.combobox_dict = dict
5691
 
+        self.use_supported = use_supported
5692
 
+        self.reinit (None)
5693
 
+
5694
 
+    def set_default(self, system_default):
5695
 
+        # For the media option, the system default depends on the printer's
5696
 
+        # PageSize setting.  This method allows the main module to tell us
5697
 
+        # what that is.
5698
 
+        self.system_default = self.ipp_type (system_default)
5699
 
+
5700
 
+    def reinit(self, original_value, supported=None):
5701
 
+        """Set the original value of the option and the supported choices.
5702
 
+        The special value None for original_value resets the option to the
5703
 
+        system default."""
5704
 
+        if (supported != None and
5705
 
+            self.use_supported):
5706
 
+            if (type(self.widget) == QComboBox and
5707
 
+                self.ipp_type == str):
5708
 
+                self.widget.clear()
5709
 
+                for each in supported:
5710
 
+                    self.widget.addItem(each)
5711
 
+            elif (type(self.widget) == QComboBox and
5712
 
+                  self.ipp_type == int and
5713
 
+                  self.combobox_map != None):
5714
 
+                self.widget.clear()
5715
 
+                for each in supported:
5716
 
+                    self.widget.addItem(self.combobox_dict[each])
5717
 
+        if original_value != None:
5718
 
+            self.original_value = self.ipp_type (original_value)
5719
 
+            self.set_widget_value (self.original_value)
5720
 
+            if original_value != self.get_widget_value():
5721
 
+                self.button.setEnabled(True)
5722
 
+        else:
5723
 
+            self.original_value = None
5724
 
+            self.set_widget_value (self.system_default)
5725
 
+            self.button.setEnabled(False)
5726
 
+        self.state = self.STATE_UNCHANGED
5727
 
+
5728
 
+    def set_widget_value(self, ipp_value):
5729
 
+        t = type(self.widget)
5730
 
+        if t == QSpinBox:
5731
 
+            return self.widget.setValue(ipp_value)
5732
 
+        elif t == QComboBox:
5733
 
+            if self.ipp_type == str and self.combobox_map == None:
5734
 
+                index = self.widget.findText(ipp_value)
5735
 
+                if index != -1:
5736
 
+                    self.widget.setCurrentIndex(index)
5737
 
+            else:
5738
 
+                # It's an int.
5739
 
+                if self.combobox_map:
5740
 
+                    index = self.combobox_map.index (ipp_value)
5741
 
+                else:
5742
 
+                    index = ipp_value
5743
 
+                return self.widget.setCurrentIndex(index)
5744
 
+        elif t == QCheckBox:
5745
 
+            return self.widget.setChecked(ipp_value)
5746
 
+        else:
5747
 
+            raise NotImplemented
5748
 
+
5749
 
+    def get_widget_value(self):
5750
 
+        t = type(self.widget)
5751
 
+        if t == QSpinBox:
5752
 
+            # Ideally we would use self.widget.get_value() here, but
5753
 
+            # it doesn't work if the value has been typed in and then
5754
 
+            # the Apply button immediately clicked.  To handle this,
5755
 
+            # we use self.widget.get_text() and fall back to
5756
 
+            # get_value() if the result cannot be interpreted as the
5757
 
+            # type we expect.
5758
 
+            try:
5759
 
+                return self.ipp_type (self.widget.value ())
5760
 
+            except ValueError:
5761
 
+                # Can't convert result of get_text() to ipp_type.
5762
 
+                return self.ipp_type (self.widget.value ())
5763
 
+        elif t == QComboBox:
5764
 
+            if self.combobox_map:
5765
 
+                return self.combobox_map[self.widget.currentIndex()]
5766
 
+            if self.ipp_type == str:
5767
 
+                return self.widget.currentText()
5768
 
+            return self.ipp_type (unicode(self.widget.currentText()))
5769
 
+        elif t == QCheckBox:
5770
 
+            return self.ipp_type (self.widget.isChecked())
5771
 
+
5772
 
+        raise NotImplemented
5773
 
+
5774
 
+    def get_current_value(self):
5775
 
+        return self.get_widget_value ()
5776
 
+
5777
 
+    def is_changed(self):
5778
 
+        if self.original_value != None:
5779
 
+            # There was a value set previously.
5780
 
+            if self.state == self.STATE_RESET:
5781
 
+                # It's been removed.
5782
 
+                return True
5783
 
+            if self.state == self.STATE_ADJUSTED:
5784
 
+                if self.get_current_value () != self.original_value:
5785
 
+                    return True
5786
 
+                return False
5787
 
+
5788
 
+            # The value is the same as before, and not reset.
5789
 
+            return False
5790
 
+
5791
 
+        # There was no original value set.
5792
 
+        if self.state == self.STATE_ADJUSTED:
5793
 
+            # It's been adjusted.
5794
 
+            return True
5795
 
+
5796
 
+        # It's been left alone, or possible adjusted and then reset.
5797
 
+        return False
5798
 
+
5799
 
+    def reset(self):
5800
 
+        self.set_widget_value (self.system_default)
5801
 
+        self.state = self.STATE_RESET
5802
 
+        self.button.setEnabled(False)
5803
 
+
5804
 
+    def changed(self):
5805
 
+        self.state = self.STATE_ADJUSTED
5806
 
+        self.button.setEnabled(True)
5807
 
+
5808
 
+class OptionAlwaysShownSpecial(OptionAlwaysShown):
5809
 
+    def __init__(self, name, ipp_type, system_default,
5810
 
+                 widget, button, combobox_map = None, use_supported = False,
5811
 
+                 special_choice = "System default"):
5812
 
+        self.special_choice = special_choice
5813
 
+        self.special_choice_shown = False
5814
 
+        OptionAlwaysShown.__init__ (self, name, ipp_type, system_default,
5815
 
+                                    widget, button,
5816
 
+                                    combobox_map=combobox_map,
5817
 
+                                    use_supported=use_supported)
5818
 
+
5819
 
+    def show_special_choice (self):
5820
 
+        if self.special_choice_shown:
5821
 
+            return
5822
 
+
5823
 
+        self.special_choice_shown = True
5824
 
+        # Only works for ComboBox widgets
5825
 
+        self.widget.insertItem(0, self.special_choice)
5826
 
+        self.widget.setCurrentIndex(0)
5827
 
+        ##model = self.widget.get_model ()
5828
 
+        ##iter = model.insert (0)
5829
 
+        ##model.set_value (iter, 0, self.special_choice)
5830
 
+        ##self.widget.set_active_iter (model.get_iter_first ())
5831
 
+
5832
 
+    def hide_special_choice (self):
5833
 
+        if not self.special_choice_shown:
5834
 
+            return
5835
 
+
5836
 
+        self.special_choice_shown = False
5837
 
+        # Only works for ComboBox widgets
5838
 
+        self.widget.removeItem(0)
5839
 
+
5840
 
+    def reinit(self, original_value, supported=None):
5841
 
+        if original_value != None:
5842
 
+            self.hide_special_choice ()
5843
 
+        else:
5844
 
+            self.show_special_choice ()
5845
 
+
5846
 
+        OptionAlwaysShown.reinit (self, original_value, supported=supported)
5847
 
+
5848
 
+    def reset(self):
5849
 
+        self.show_special_choice ()
5850
 
+        OptionAlwaysShown.reset (self)
5851
 
+
5852
 
+    def changed(self):
5853
 
+        OptionAlwaysShown.changed (self)
5854
 
+        if self.widget.currentIndex() > 0:
5855
 
+            self.hide_special_choice ()
5856
 
+
5857
 
+class Option(OptionInterface):
5858
 
+
5859
 
+    conflicts = None
5860
 
+
5861
 
+    def __init__(self, name, value, supported, on_change):
5862
 
+        self.name = name
5863
 
+        self.value = value
5864
 
+        self.supported = supported
5865
 
+        self.on_change = on_change
5866
 
+        self.is_new = False
5867
 
+
5868
 
+        label = unicode(name)
5869
 
+        if not label.endswith (':'):
5870
 
+            label += ':'
5871
 
+        self.label = QLabel(label)
5872
 
+
5873
 
+    def get_current_value(self):
5874
 
+        raise NotImplemented
5875
 
+
5876
 
+    def is_changed(self):
5877
 
+        return (self.is_new or
5878
 
+                str (self.get_current_value()) != str (self.value))
5879
 
+
5880
 
+    def changed(self, widget, *args):
5881
 
+        self.on_change(self)
5882
 
+    
5883
 
+# ---------------------------------------------------------------------------
5884
 
+
5885
 
+class OptionSelectOne(Option):
5886
 
+
5887
 
+    def __init__(self, name, value, supported, on_change):
5888
 
+        Option.__init__(self, name, value, supported, on_change)
5889
 
+
5890
 
+        self.selector = gtk.combo_box_new_text()
5891
 
+        
5892
 
+        
5893
 
+        selected = None
5894
 
+        for nr, choice in enumerate(supported):
5895
 
+            self.selector.append_text(str(choice))
5896
 
+            if str (value) == str (choice):
5897
 
+                selected = nr
5898
 
+        if selected is not None:
5899
 
+            self.selector.set_active(selected)
5900
 
+        else:
5901
 
+            print "Unknown value for %s: %s" % (name, value)
5902
 
+            print "Choices:", supported
5903
 
+        self.selector.connect("changed", self.changed)
5904
 
+
5905
 
+    def get_current_value(self):
5906
 
+        return self.selector.get_active_text()
5907
 
+
5908
 
+# ---------------------------------------------------------------------------
5909
 
+
5910
 
+class OptionSelectOneNumber(OptionSelectOne):
5911
 
+
5912
 
+    def get_current_value(self):
5913
 
+        return int(self.selector.get_active_text())
5914
 
+
5915
 
+# ---------------------------------------------------------------------------
5916
 
+
5917
 
+class OptionSelectMany(Option):
5918
 
+
5919
 
+    def __init__(self, name, value, supported, on_change):
5920
 
+        Option.__init__(self, name, value, supported, on_change)
5921
 
+        self.checkboxes = []
5922
 
+        vbox = gtk.VBox()
5923
 
+
5924
 
+        for s in supported:
5925
 
+            checkbox = gtk.CheckButton(label=s)
5926
 
+            checkbox.set_active(s in value)
5927
 
+            vbox.add(checkbox)
5928
 
+            checkbox.connect("toggled", self.changed)
5929
 
+            self.checkboxes.append(checkbox)
5930
 
+        self.selector = vbox
5931
 
+            
5932
 
+    def get_current_value(self):
5933
 
+        return[s for s, chk in zip(self.supported, self.checkboxes)
5934
 
+               if chk.get_active()]
5935
 
+
5936
 
+# ---------------------------------------------------------------------------
5937
 
+
5938
 
+class OptionNumeric(Option):
5939
 
+    def __init__(self, name, value, supported, on_change):
5940
 
+        self.is_float = (isinstance(supported, float) or
5941
 
+                         (isinstance(supported, tuple) and
5942
 
+                          isinstance(supported[0], float)))
5943
 
+        if self.is_float:
5944
 
+            digits = 2
5945
 
+        else:
5946
 
+            digits = 0
5947
 
+
5948
 
+        if not isinstance(supported, tuple):
5949
 
+            supported = (0, supported)
5950
 
+        Option.__init__(self, name, value, supported, on_change)
5951
 
+        adj = gtk.Adjustment(value, supported[0], supported[1], 1.0, 5.0, 0.0)
5952
 
+        self.selector = gtk.SpinButton(adj, climb_rate=1.0, digits=digits)
5953
 
+        if not self.is_float:
5954
 
+            self.selector.set_numeric(True)
5955
 
+        self.selector.connect("changed", self.changed)
5956
 
+
5957
 
+    def get_current_value(self):
5958
 
+        if self.is_float:
5959
 
+            return self.selector.get_value()
5960
 
+        return self.selector.get_value_as_int()
5961
 
+
5962
 
+# ---------------------------------------------------------------------------
5963
 
+
5964
 
+class OptionText(Option):
5965
 
+    def __init__(self, name, value, supported, on_change):
5966
 
+        Option.__init__(self, name, value, supported, on_change)
5967
 
+
5968
 
+        self.selector = QLineEdit()
5969
 
+        self.selector.setText(value)
5970
 
+        self.selector.connect(self.selector, SIGNAL("textChanged(QString)"), self.changed)
5971
 
+
5972
 
+    def get_current_value(self):
5973
 
+        return self.selector.text()
5974
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/optionwidgets.py kdeadmin-4.2.2/system-config-printer-kde/optionwidgets.py
5975
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/optionwidgets.py      1970-01-01 01:00:00.000000000 +0100
5976
 
+++ kdeadmin-4.2.2/system-config-printer-kde/optionwidgets.py   2009-04-09 22:56:08.000000000 +0100
5977
 
@@ -0,0 +1,221 @@
5978
 
+# -*- coding: utf-8 -*-
5979
 
+## system-config-printer
5980
 
+
5981
 
+#############################################################################
5982
 
+##
5983
 
+## Copyright 2007-2009 Canonical Ltd
5984
 
+## Copyright 2008-2009 Richard Birnie <arbyuk@googlemail.com>
5985
 
+## Author: Jonathan Riddell <jriddell@ubuntu.com>
5986
 
+##         Richard Birnie <arbyuk@googlemail.com>
5987
 
+##
5988
 
+## Includes code from System Config Printer:
5989
 
+## Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
5990
 
+## Copyright (C) 2006, 2007 Florian Festi <ffesti@redhat.com>
5991
 
+## Copyright (C) 2006, 2007, 2008 Tim Waugh <twaugh@redhat.com>
5992
 
+##
5993
 
+## This program is free software; you can redistribute it and/or
5994
 
+## modify it under the terms of the GNU General Public License as
5995
 
+## published by the Free Software Foundation; either version 2 of
5996
 
+## the License, or (at your option) any later version.
5997
 
+##
5998
 
+## This program is distributed in the hope that it will be useful,
5999
 
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
6000
 
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6001
 
+## GNU General Public License for more details.
6002
 
+##
6003
 
+## You should have received a copy of the GNU General Public License
6004
 
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
6005
 
+##
6006
 
+#############################################################################
6007
 
+
6008
 
+import cups
6009
 
+from PyQt4.QtCore import *
6010
 
+from PyQt4.QtGui import *
6011
 
+from PyKDE4.kdecore import i18n
6012
 
+
6013
 
+"""
6014
 
+These classes are used to dynamically generate the UI on the Options tab of the printer config dialogue
6015
 
+"""
6016
 
+
6017
 
+def OptionWidget(option, ppd, gui, tab_label=None):
6018
 
+    """Factory function"""
6019
 
+    ui = option.ui
6020
 
+    if (ui == cups.PPD_UI_BOOLEAN and
6021
 
+        len (option.choices) != 2):
6022
 
+        # This option is advertised as a Boolean but in fact has more
6023
 
+        # than two choices.
6024
 
+        print "Treating Boolean option %s as PickOne" % option.keyword
6025
 
+        ui = cups.PPD_UI_PICKONE
6026
 
+
6027
 
+    if ui == cups.PPD_UI_BOOLEAN:
6028
 
+        return OptionBool(option, ppd, gui, tab_label=tab_label)
6029
 
+        pass
6030
 
+    elif ui == cups.PPD_UI_PICKONE:
6031
 
+        return OptionPickOne(option, ppd, gui, tab_label=tab_label)
6032
 
+    elif ui == cups.PPD_UI_PICKMANY:
6033
 
+        ##return OptionPickMany(option, ppd, gui, tab_label=tab_label)
6034
 
+        pass
6035
 
+
6036
 
+# ---------------------------------------------------------------------------
6037
 
+class Option(QObject):
6038
 
+    
6039
 
+    def __init__(self, option, ppd, gui, tab_label=None):
6040
 
+        QObject.__init__(self)
6041
 
+        self.option = option
6042
 
+        self.ppd = ppd
6043
 
+        self.gui = gui
6044
 
+        self.enabled = True
6045
 
+        self.tab_label = tab_label
6046
 
+
6047
 
+        ##vbox = gtk.VBox()
6048
 
+        
6049
 
+        #self.btnConflict = gtk.Button()
6050
 
+        #icon = gtk.image_new_from_stock(gtk.STOCK_DIALOG_WARNING,
6051
 
+        #                                gtk.ICON_SIZE_SMALL_TOOLBAR)
6052
 
+        #self.btnConflict.add(icon)
6053
 
+        #self.btnConflict.set_no_show_all(True) #avoid the button taking
6054
 
+                                               # over control again
6055
 
+        #vbox.add(self.btnConflict)    # vbox reserves space while button
6056
 
+        #vbox.set_size_request(32, 28) # is hidden
6057
 
+        #self.conflictIcon = vbox
6058
 
+
6059
 
+        #self.btnConflict.connect("clicked", self.on_btnConflict_clicked)
6060
 
+        #icon.show()
6061
 
+
6062
 
+        self.constraints = [c for c in ppd.constraints
6063
 
+                            if c.option1 == option.keyword]
6064
 
+        #for c in self.constraints:
6065
 
+        #    if not c.choice1 or not c.choice2:
6066
 
+        #        print c.option1, repr(c.choice1), c.option2, repr(c.choice2)
6067
 
+        self.conflicts = set()
6068
 
+        self.conflict_message = ""
6069
 
+
6070
 
+    def enable(self, enabled=True):
6071
 
+        self.selector.setEnabled(enabled)
6072
 
+        self.enabled = enabled
6073
 
+
6074
 
+    def disable(self):
6075
 
+        self.enable (False)
6076
 
+
6077
 
+    def is_enabled(self):
6078
 
+        return self.enabled
6079
 
+
6080
 
+    def get_current_value(self):
6081
 
+        raise NotImplemented
6082
 
+
6083
 
+    def is_changed(self):
6084
 
+        return self.get_current_value()!= self.option.defchoice
6085
 
+    
6086
 
+    def writeback(self):
6087
 
+        if self.enabled:
6088
 
+            self.ppd.markOption(self.option.keyword, self.get_current_value())
6089
 
+
6090
 
+    def checkConflicts(self, update_others=True):
6091
 
+        value = self.get_current_value()
6092
 
+        for constraint in self.constraints:
6093
 
+            option2 = self.gui.options.get(constraint.option2, None)
6094
 
+            if option2 is None: continue
6095
 
+
6096
 
+            if (constraint.choice1==value and
6097
 
+                option2.get_current_value() == constraint.choice2):
6098
 
+                # conflict
6099
 
+                self.conflicts.add(constraint)
6100
 
+                if update_others:
6101
 
+                    option2.checkConflicts(update_others=False)
6102
 
+            elif constraint in self.conflicts:
6103
 
+                # remove conflict
6104
 
+                self.conflicts.remove(constraint)
6105
 
+                option2.checkConflicts(update_others=False)
6106
 
+
6107
 
+
6108
 
+        tooltip = [unicode(i18n("Conflicts with:"))]
6109
 
+        for c in self.conflicts:
6110
 
+            option = self.gui.options.get(c.option2)
6111
 
+            tooltip.append(option.option.text)
6112
 
+            
6113
 
+        tooltip = "\n".join(tooltip)
6114
 
+
6115
 
+        self.conflict_message = tooltip # XXX more verbose
6116
 
+            
6117
 
+        if self.conflicts:
6118
 
+            #FIXME: btnConflict not impemented yet
6119
 
+            #self.gui.btnConflict.setTooltip(tooltip + "OPTION-" + self.option.keyword)
6120
 
+            #self.btnConflict.show()
6121
 
+            pass
6122
 
+        else:
6123
 
+            #self.btnConflict.hide()
6124
 
+            pass
6125
 
+
6126
 
+        self.gui.option_changed(self)
6127
 
+        return self.conflicts
6128
 
+
6129
 
+    def on_change(self, index):
6130
 
+        self.checkConflicts()
6131
 
+
6132
 
+"""
6133
 
+    def on_btnConflict_clicked(self, button):
6134
 
+        self.dialog.set_markup(self.conflict_message)
6135
 
+        self.dialog.run()
6136
 
+        self.dialog.hide()
6137
 
+        
6138
 
+# ---------------------------------------------------------------------------
6139
 
+"""
6140
 
+
6141
 
+
6142
 
+class OptionBool(Option):
6143
 
+
6144
 
+    def __init__(self, option, ppd, gui, tab_label=None):
6145
 
+        self.selector = QCheckBox(option.text, gui)
6146
 
+        self.label = None
6147
 
+        self.false = u"False" # hack to allow "None" instead of "False"
6148
 
+        self.true = u"True"
6149
 
+        for c in option.choices:
6150
 
+            if c["choice"] in ("None", "False", "Off"):
6151
 
+                self.false = c["choice"]
6152
 
+            if c["choice"] in ("True", "On"):
6153
 
+                self.true = c["choice"]
6154
 
+        self.selector.setChecked(option.defchoice == self.true)
6155
 
+        #self.selector.set_alignment(0.0, 0.5)
6156
 
+        self.connect(self.selector, SIGNAL("toggled(bool)"), self.on_change)
6157
 
+        Option.__init__(self, option, ppd, gui, tab_label=tab_label)
6158
 
+
6159
 
+    def get_current_value(self):
6160
 
+        return (self.false, self.true)[self.selector.isChecked()]
6161
 
+
6162
 
+# ---------------------------------------------------------------------------
6163
 
+
6164
 
+class OptionPickOne(Option):
6165
 
+    widget_name = "OptionPickOne"
6166
 
+
6167
 
+    def __init__(self, option, ppd, gui, tab_label=None):
6168
 
+        self.selector = QComboBox(gui)
6169
 
+        
6170
 
+        label = option.text
6171
 
+        if not label.endswith (':'):
6172
 
+            label += ':'
6173
 
+        self.label = QLabel(label, gui)
6174
 
+        
6175
 
+        selected = None
6176
 
+        for nr, choice in enumerate(option.choices):
6177
 
+            self.selector.addItem(choice['text'])
6178
 
+            if option.defchoice == choice['choice']:
6179
 
+                selected = self.selector.count() - 1
6180
 
+        if selected is not None:
6181
 
+            self.selector.setCurrentIndex(selected)
6182
 
+        else:
6183
 
+            print option.text, "unknown value:", option.defchoice
6184
 
+        self.connect(self.selector, SIGNAL("currentIndexChanged(int)"), self.on_change)
6185
 
+
6186
 
+        Option.__init__(self, option, ppd, gui, tab_label=tab_label)
6187
 
+
6188
 
+    def get_current_value(self):
6189
 
+        return self.option.choices[self.selector.currentIndex()]['choice']
6190
 
+
6191
 
+# ---------------------------------------------------------------------------
6192
 
+
6193
 
+class OptionPickMany(OptionPickOne):
6194
 
+    widget_name = "OptionPickMany"
6195
 
+
6196
 
+    def __init__(self, option, ppd, gui, tab_label=None):
6197
 
+        raise NotImplemented
6198
 
+        Option.__init__(self, option, ppd, gui, tab_label=tab_label)
6199
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/smb-browse-dialog.ui kdeadmin-4.2.2/system-config-printer-kde/smb-browse-dialog.ui
6200
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/smb-browse-dialog.ui  1970-01-01 01:00:00.000000000 +0100
6201
 
+++ kdeadmin-4.2.2/system-config-printer-kde/smb-browse-dialog.ui       2009-04-09 22:56:08.000000000 +0100
6202
 
@@ -0,0 +1,124 @@
6203
 
+<ui version="4.0" >
6204
 
+ <class>SMBBrowseDialog</class>
6205
 
+ <widget class="QDialog" name="SMBBrowseDialog" >
6206
 
+  <property name="windowModality" >
6207
 
+   <enum>Qt::NonModal</enum>
6208
 
+  </property>
6209
 
+  <property name="geometry" >
6210
 
+   <rect>
6211
 
+    <x>0</x>
6212
 
+    <y>0</y>
6213
 
+    <width>400</width>
6214
 
+    <height>300</height>
6215
 
+   </rect>
6216
 
+  </property>
6217
 
+  <property name="font" >
6218
 
+   <font>
6219
 
+    <weight>50</weight>
6220
 
+    <bold>false</bold>
6221
 
+   </font>
6222
 
+  </property>
6223
 
+  <property name="focusPolicy" >
6224
 
+   <enum>Qt::StrongFocus</enum>
6225
 
+  </property>
6226
 
+  <property name="windowTitle" >
6227
 
+   <string>SMB Browser</string>
6228
 
+  </property>
6229
 
+  <property name="modal" >
6230
 
+   <bool>true</bool>
6231
 
+  </property>
6232
 
+  <widget class="QWidget" name="layoutWidget" >
6233
 
+   <property name="geometry" >
6234
 
+    <rect>
6235
 
+     <x>21</x>
6236
 
+     <y>250</y>
6237
 
+     <width>361</width>
6238
 
+     <height>41</height>
6239
 
+    </rect>
6240
 
+   </property>
6241
 
+   <layout class="QHBoxLayout" name="horizontalLayout" >
6242
 
+    <item>
6243
 
+     <widget class="KPushButton" name="btnSMBBrowseRefresh" >
6244
 
+      <property name="text" >
6245
 
+       <string>Refresh</string>
6246
 
+      </property>
6247
 
+     </widget>
6248
 
+    </item>
6249
 
+    <item>
6250
 
+     <spacer name="horizontalSpacer" >
6251
 
+      <property name="orientation" >
6252
 
+       <enum>Qt::Horizontal</enum>
6253
 
+      </property>
6254
 
+      <property name="sizeHint" stdset="0" >
6255
 
+       <size>
6256
 
+        <width>40</width>
6257
 
+        <height>20</height>
6258
 
+       </size>
6259
 
+      </property>
6260
 
+     </spacer>
6261
 
+    </item>
6262
 
+    <item>
6263
 
+     <widget class="KPushButton" name="btnSMBBrowseOk" >
6264
 
+      <property name="text" >
6265
 
+       <string>Ok</string>
6266
 
+      </property>
6267
 
+      <property name="shortcut" >
6268
 
+       <string>Ctrl+O</string>
6269
 
+      </property>
6270
 
+     </widget>
6271
 
+    </item>
6272
 
+    <item>
6273
 
+     <widget class="KPushButton" name="btnSMBBrowseCancel" >
6274
 
+      <property name="text" >
6275
 
+       <string>Cancel</string>
6276
 
+      </property>
6277
 
+     </widget>
6278
 
+    </item>
6279
 
+   </layout>
6280
 
+  </widget>
6281
 
+  <widget class="QTreeWidget" name="twSMBBrowser" >
6282
 
+   <property name="geometry" >
6283
 
+    <rect>
6284
 
+     <x>30</x>
6285
 
+     <y>10</y>
6286
 
+     <width>341</width>
6287
 
+     <height>221</height>
6288
 
+    </rect>
6289
 
+   </property>
6290
 
+   <property name="sizePolicy" >
6291
 
+    <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
6292
 
+     <horstretch>0</horstretch>
6293
 
+     <verstretch>0</verstretch>
6294
 
+    </sizepolicy>
6295
 
+   </property>
6296
 
+   <property name="sortingEnabled" >
6297
 
+    <bool>true</bool>
6298
 
+   </property>
6299
 
+   <property name="allColumnsShowFocus" >
6300
 
+    <bool>true</bool>
6301
 
+   </property>
6302
 
+   <property name="columnCount" >
6303
 
+    <number>2</number>
6304
 
+   </property>
6305
 
+   <column>
6306
 
+    <property name="text" >
6307
 
+     <string>1</string>
6308
 
+    </property>
6309
 
+   </column>
6310
 
+   <column>
6311
 
+    <property name="text" >
6312
 
+     <string>1</string>
6313
 
+    </property>
6314
 
+   </column>
6315
 
+  </widget>
6316
 
+ </widget>
6317
 
+ <customwidgets>
6318
 
+  <customwidget>
6319
 
+   <class>KPushButton</class>
6320
 
+   <extends>QPushButton</extends>
6321
 
+   <header>kpushbutton.h</header>
6322
 
+  </customwidget>
6323
 
+ </customwidgets>
6324
 
+ <resources/>
6325
 
+ <connections/>
6326
 
+</ui>
6327
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.desktop kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.desktop
6328
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.desktop     2009-03-26 14:43:48.000000000 +0000
6329
 
+++ kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.desktop  2009-04-09 22:56:08.000000000 +0100
6330
 
@@ -1,31 +1,12 @@
6331
 
 [Desktop Entry]
6332
 
 Name=Printing
6333
 
-Name[ca]=Impressió
6334
 
-Name[cs]=Tisk
6335
 
-Name[da]=Udskrift
6336
 
-Name[de]=Drucken
6337
 
 Name[el]=Εκτύπωση
6338
 
-Name[es]=Imprimiendo
6339
 
-Name[et]=Trükkimine
6340
 
-Name[fr]=Impression
6341
 
-Name[ga]=Priontáil
6342
 
 Name[gl]=Impresión
6343
 
-Name[hne]=छपाई
6344
 
-Name[hu]=Nyomtatás
6345
 
-Name[is]=Prentun
6346
 
-Name[it]=Stampa
6347
 
-Name[ja]=印刷
6348
 
-Name[lt]=Spausdinimas
6349
 
 Name[lv]=Drukāšana
6350
 
-Name[nb]=Utskrift
6351
 
 Name[nds]=Drucken
6352
 
 Name[nl]=Printers
6353
 
-Name[nn]=Utskrift
6354
 
-Name[pa]=ਪਰਿੰਟਿੰਗ
6355
 
-Name[pl]=Drukowanie
6356
 
 Name[pt]=Impressão
6357
 
 Name[pt_BR]=Imprimindo
6358
 
-Name[ro]=Imprimare
6359
 
 Name[ru]=Печать
6360
 
 Name[sv]=Utskrift
6361
 
 Name[tr]=Yazdırma
6362
 
@@ -34,32 +15,13 @@
6363
 
 Name[zh_CN]=打印
6364
 
 Name[zh_TW]=列印
6365
 
 Comment=Configure printers
6366
 
-Comment[ca]=Configura les impressores
6367
 
-Comment[cs]=Nastavení tisku
6368
 
-Comment[da]=Indstil printere
6369
 
-Comment[de]=Drucker einrichten
6370
 
 Comment[el]=Ρύθμιση εκτυπωτών
6371
 
-Comment[es]=Configurar impresoras
6372
 
-Comment[et]=Printerite seadistamine
6373
 
-Comment[fr]=Configurer les imprimantes
6374
 
-Comment[ga]=Cumraigh printéirí
6375
 
 Comment[gl]=Configuración das impresoras
6376
 
-Comment[hne]=प्रिंटर मन ल कान्फिगर करव
6377
 
-Comment[hu]=Nyomtatóbeállítás
6378
 
-Comment[is]=Stilla prentara
6379
 
-Comment[it]=Configura le stampanti
6380
 
-Comment[ja]=プリンタの設定
6381
 
-Comment[lt]=Konfigūruoti spausdintuvus
6382
 
 Comment[lv]=Konfigurēt drukas ierīces
6383
 
-Comment[nb]=Sett opp skrivere
6384
 
 Comment[nds]=Druckers instellen
6385
 
 Comment[nl]=Printers instellen
6386
 
-Comment[nn]=Set opp skrivarar
6387
 
-Comment[pa]=ਪਰਿੰਟਿੰਗ ਸੰਰਚਨਾ
6388
 
-Comment[pl]=Konfiguracja drukarek
6389
 
 Comment[pt]=Configurar as impressoras
6390
 
 Comment[pt_BR]=Configurar impressoras
6391
 
-Comment[ro]=Configurează imprimantele
6392
 
 Comment[ru]=Настройка принтеров
6393
 
 Comment[sv]=Anpassa skrivare
6394
 
 Comment[tr]=Yazıcıları yapılandır
6395
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.py kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.py
6396
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.py  2008-12-21 20:20:45.000000000 +0000
6397
 
+++ kdeadmin-4.2.2/system-config-printer-kde/system-config-printer-kde.py       1970-01-01 01:00:00.000000000 +0100
6398
 
@@ -1,3250 +0,0 @@
6399
 
-#!/usr/bin/env python
6400
 
-# -*- coding: utf-8 -*-
6401
 
-
6402
 
-#############################################################################
6403
 
-##
6404
 
-## Copyright (C) 2007 Canonical Ltd
6405
 
-## Author: Jonathan Riddell <jriddell@ubuntu.com>
6406
 
-##
6407
 
-## Includes code from System Config Printer
6408
 
-## Copyright (C) 2007 Tim Waugh <twaugh@redhat.com>
6409
 
-## Copyright (C) 2007 Red Hat, Inc.
6410
 
-##
6411
 
-## This program is free software; you can redistribute it and/or
6412
 
-## modify it under the terms of the GNU General Public License as
6413
 
-## published by the Free Software Foundation; either version 2 of
6414
 
-## the License, or (at your option) any later version.
6415
 
-##
6416
 
-## This program is distributed in the hope that it will be useful,
6417
 
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
6418
 
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6419
 
-## GNU General Public License for more details.
6420
 
-##
6421
 
-## You should have received a copy of the GNU General Public License
6422
 
-## along with this program.  If not, see <http://www.gnu.org/licenses/>.
6423
 
-##
6424
 
-#############################################################################
6425
 
-
6426
 
-MIN_REFRESH_INTERVAL = 1 # seconds
6427
 
-import locale
6428
 
-
6429
 
-import sys, os, time, traceback, re, tempfile, httplib
6430
 
-#tempfile
6431
 
-import thread
6432
 
-
6433
 
-#load modules from system-config-printer-common (debug, smburi), change path here if you have it installed elsewhere
6434
 
-SYSTEM_CONFIG_PRINTER_DIR = "/usr/share/system-config-printer"
6435
 
-if os.path.exists(SYSTEM_CONFIG_PRINTER_DIR + "/debug.py"):
6436
 
-    sys.path.append(SYSTEM_CONFIG_PRINTER_DIR)
6437
 
-
6438
 
-from PyQt4.QtCore import *
6439
 
-from PyQt4.QtGui import *
6440
 
-from PyQt4 import uic
6441
 
-
6442
 
-from PyKDE4.kdecore import *
6443
 
-from PyKDE4.kdeui import *
6444
 
-
6445
 
-#use _() to keep code the same as gnome system-config-printer
6446
 
-def _(string):
6447
 
-    return unicode(i18n(string), "utf-8")
6448
 
-
6449
 
-def translate(self, prop):
6450
 
-    """reimplement method from uic to change it to use gettext"""
6451
 
-    if prop.get("notr", None) == "true":
6452
 
-        return self._cstring(prop)
6453
 
-    else:
6454
 
-        if prop.text is None:
6455
 
-            return ""
6456
 
-        text = prop.text.encode("UTF-8")
6457
 
-        return i18n(text)
6458
 
-
6459
 
-uic.properties.Properties._string = translate
6460
 
-
6461
 
-import cups
6462
 
-cups.require ("1.9.27")
6463
 
-
6464
 
-# These come from system-config-printer
6465
 
-import config
6466
 
-import cupshelpers  #, options
6467
 
-from smburi import SMBURI
6468
 
-from debug import *
6469
 
-
6470
 
-import dbus
6471
 
-import dbus.mainloop.qt
6472
 
-import dbus.service
6473
 
-
6474
 
-ellipsis = unichr(0x2026)
6475
 
-
6476
 
-try:
6477
 
-    try_CUPS_SERVER_REMOTE_ANY = cups.CUPS_SERVER_REMOTE_ANY
6478
 
-except AttributeError:
6479
 
-    # cups module was compiled with CUPS < 1.3
6480
 
-    try_CUPS_SERVER_REMOTE_ANY = "_remote_any"
6481
 
-
6482
 
-def validDeviceURI (uri):
6483
 
-    """Returns True is the provided URI is valid."""
6484
 
-    if uri.find (":/") > 0:
6485
 
-        return True
6486
 
-    return False
6487
 
-
6488
 
-class GUI(QWidget):
6489
 
-    """our main class is the main window"""
6490
 
-
6491
 
-    printer_states = { cups.IPP_PRINTER_IDLE: i18nc("Printer state", "Idle"),
6492
 
-                       cups.IPP_PRINTER_PROCESSING: i18nc("Printer state", "Processing"),
6493
 
-                       cups.IPP_PRINTER_BUSY: i18nc("Printer state", "Busy"),
6494
 
-                       cups.IPP_PRINTER_STOPPED: i18nc("Printer state", "Stopped") }
6495
 
-
6496
 
-    def __init__(self, start_printer = None, change_ppd = False):
6497
 
-        QWidget.__init__(self)
6498
 
-
6499
 
-        try:
6500
 
-            self.language = locale.getlocale(locale.LC_MESSAGES)
6501
 
-            self.encoding = locale.getlocale(locale.LC_CTYPE)
6502
 
-        except:
6503
 
-            nonfatalException()
6504
 
-            os.environ['LC_ALL'] = 'C'
6505
 
-            locale.setlocale (locale.LC_ALL, "")
6506
 
-            self.language = locale.getlocale(locale.LC_MESSAGES)
6507
 
-            self.encoding = locale.getlocale(locale.LC_CTYPE)
6508
 
-
6509
 
-        self.printer = None
6510
 
-        self.conflicts = set() # of options
6511
 
-        self.connect_server = (self.printer and self.printer.getServer()) \
6512
 
-                               or cups.getServer()     
6513
 
-        self.connect_user = cups.getUser()
6514
 
-        self.password = '' #FIXME not in Gnome version
6515
 
-        self.passwd_retry = False #FIXME not in Gnome version
6516
 
-        self.widget_data_setting = {} #FIXME not in Gnome version
6517
 
-        #FIXMEcups.setPasswordCB(self.cupsPasswdCallback)        
6518
 
-        ##self.server_is_publishing = False #FIXME new in Gnome version
6519
 
-
6520
 
-        self.changed = set() # of options
6521
 
-
6522
 
-        self.servers = set((self.connect_server,))
6523
 
-
6524
 
-        try:
6525
 
-            self.cups = cups.Connection()
6526
 
-        except RuntimeError:
6527
 
-           #warn the user that cups is not running
6528
 
-           message = i18n("CUPS is not currently running. CUPS is required for complete printing functionality. Please start CUPS then restart this application.")
6529
 
-           answer = QMessageBox.warning(self, i18n("Print Server Not Running"), message, QMessageBox.Ok)
6530
 
-           #still allow the app to start for those that really want that
6531
 
-           if answer == QMessageBox.Ok:
6532
 
-               pass
6533
 
-           
6534
 
-            self.cups = None
6535
 
-
6536
 
-        if os.path.exists("system-config-printer.ui"):
6537
 
-            APPDIR = QDir.currentPath()
6538
 
-        else:
6539
 
-            file = KStandardDirs.locate("appdata", "system-config-printer.ui")
6540
 
-            APPDIR = file.left(file.lastIndexOf("/"))
6541
 
-
6542
 
-        uic.loadUi(APPDIR + "/" + "system-config-printer.ui", self)
6543
 
-        self.show()
6544
 
-
6545
 
-        # New Printer Dialog
6546
 
-        self.newPrinterGUI = np = NewPrinterGUI(self)
6547
 
-        #np.NewPrinterWindow.set_transient_for(self.MainWindow)
6548
 
-
6549
 
-        self.setConnected()
6550
 
-
6551
 
-        self.connect(self.mainlist, SIGNAL("itemSelectionChanged()"), self.on_tvMainList_cursor_changed)
6552
 
-        self.connect(self.mainlist, SIGNAL("currentItemChanged (QTreeWidgetItem*, QTreeWidgetItem*)"), self.on_tvMainList_changed)
6553
 
-        self.connect(self.chkServerBrowse, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
6554
 
-        self.connect(self.chkServerShare, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
6555
 
-        self.connect(self.chkServerShareAny, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
6556
 
-        self.connect(self.chkServerRemoteAdmin, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
6557
 
-        self.connect(self.chkServerAllowCancelAll, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
6558
 
-        self.connect(self.chkServerLogDebug, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
6559
 
-
6560
 
-        self.connect(self.btnNewClass, SIGNAL("clicked()"), self.on_new_class_activate)
6561
 
-        self.connect(self.btnNewPrinter, SIGNAL("clicked()"), self.on_new_printer_activate)
6562
 
-
6563
 
-        self.connect(self.entPDescription, SIGNAL("textEdited(const QString&)"), self.on_printer_changed)
6564
 
-        self.connect(self.entPLocation, SIGNAL("textEdited(const QString&)"), self.on_printer_changed)
6565
 
-        self.connect(self.entPDevice, SIGNAL("textEdited(const QString&)"), self.on_printer_changed)
6566
 
-        self.connect(self.chkPEnabled, SIGNAL("stateChanged(int)"), self.on_printer_changed)
6567
 
-        self.connect(self.chkPAccepting, SIGNAL("stateChanged(int)"), self.on_printer_changed)
6568
 
-        self.connect(self.chkPShared, SIGNAL("stateChanged(int)"), self.on_printer_changed)
6569
 
-        self.connect(self.cmbPErrorPolicy, SIGNAL("currentIndexChanged(int)"), self.on_printer_changed)
6570
 
-        self.connect(self.cmbPOperationPolicy, SIGNAL("currentIndexChanged(int)"), self.on_printer_changed)
6571
 
-        self.connect(self.cmbPStartBanner, SIGNAL("currentIndexChanged(int)"), self.on_printer_changed)
6572
 
-        self.connect(self.cmbPEndBanner, SIGNAL("currentIndexChanged(int)"), self.on_printer_changed)
6573
 
-        #self.connect(self.rbtnPAllow, SIGNAL("toggled(bool)"), self.on_printer_changed)
6574
 
-
6575
 
-        try:
6576
 
-            self.populateList(start_printer, change_ppd)
6577
 
-        except cups.HTTPError, (s,):
6578
 
-            self.cups = None
6579
 
-            self.setConnected()
6580
 
-            self.populateList()
6581
 
-            self.show_HTTP_Error(s)
6582
 
-
6583
 
-        self.mainlist.header().hide()
6584
 
-
6585
 
-        #hide some bits until implemented
6586
 
-        self.btnNewPrinterNetwork.hide()
6587
 
-        self.newPrinterNetworkLabel.hide()
6588
 
-        self.btnNewPrinterSpecial.hide()
6589
 
-        self.newPrinterSpecialLabel.hide()
6590
 
-        self.btnNewPrinter.setText(i18n("New Printer"))
6591
 
-        self.btnPrinterPropertiesApply.setIcon(KIcon("dialog-ok-apply"))
6592
 
-        self.btnRevert.setIcon(KIcon("document-revert"))
6593
 
-        self.newPrinterLabel.hide()
6594
 
-        #(obsolete) only show settings until ready for the rest
6595
 
-        #self.mainlist.hide()
6596
 
-        self.mainlist.setCurrentItem(self.settingsItem)
6597
 
-        #FIXME hide labels until implemented
6598
 
-        self.lblPOptions.hide()
6599
 
-        self.lblPInstallOptions.hide()
6600
 
-
6601
 
-        self.setWindowIcon(KIcon("printer"))
6602
 
-
6603
 
-    # now called  dests_iconview_item_activated() in the Gnome version
6604
 
-    def on_tvMainList_cursor_changed(self):
6605
 
-        if self.changed:
6606
 
-            # The unapplied changes for this item have not been saved,
6607
 
-            # and the user just pressed "Cancel".
6608
 
-            #FIXME, should offer dialog prompting to save or cancel here
6609
 
-            return
6610
 
-        items = self.mainlist.selectedItems()
6611
 
-        if len(items) < 1:
6612
 
-            return
6613
 
-        item = items[0]
6614
 
-        #FIXME only show settings until ready for the rest
6615
 
-        #item = self.settingsItem
6616
 
-        type = str(item.text(1))
6617
 
-        name = str(item.text(0))
6618
 
-        #name, type = self.getSelectedItem()
6619
 
-        #model, self.mainListSelected = self.tvMainList.get_selection().get_selected()
6620
 
-        #Save the values incase it gets deselected
6621
 
-        self.mainListSelectedType = type
6622
 
-        self.mainListSelectedName = name
6623
 
-        item_selected = True
6624
 
-        if type == "New":
6625
 
-            #self.ntbkMain.set_current_page(0)
6626
 
-            self.ntbkMain.setCurrentIndex(0)
6627
 
-        elif type == "Settings":
6628
 
-            #self.ntbkMain.set_current_page(0)
6629
 
-            self.ntbkMain.setCurrentIndex(1)
6630
 
-            if self.cups:
6631
 
-                self.fillServerTab()
6632
 
-            else:
6633
 
-                # No connection to CUPS.  Make sure the Apply/Revert buttons
6634
 
-                # are not sensitive.
6635
 
-                self.setDataButtonState()
6636
 
-            item_selected = False
6637
 
-        elif type in ['Printer', 'Class']:
6638
 
-            try:
6639
 
-                self.fillPrinterTab(name)
6640
 
-                self.fillPrinterOptions()
6641
 
-                self.setDataButtonState()
6642
 
-            except RuntimeError:
6643
 
-                # Perhaps cupsGetPPD2 failed for a browsed printer.
6644
 
-                self.ntbkMain.setCurrentIndex(3)
6645
 
-                #self.ntbkMain.set_current_page(2)
6646
 
-                return
6647
 
-
6648
 
-            #self.ntbkMain.set_current_page(1)
6649
 
-            self.ntbkMain.setCurrentIndex(2)
6650
 
-        elif type == "None":
6651
 
-            #self.ntbkMain.set_current_page(2)
6652
 
-            self.ntbkMain.setCurrentIndex(3)
6653
 
-            self.setDataButtonState()
6654
 
-            item_selected = False
6655
 
-
6656
 
-        """FIXME, copy button
6657
 
-        is_local = item_selected and not self.printers[name].discovered
6658
 
-        for widget in [self.copy, self.btnCopy]:
6659
 
-            widget.set_sensitive(item_selected)
6660
 
-        for widget in [self.delete, self.btnDelete]:
6661
 
-            widget.set_sensitive(is_local)
6662
 
-        """
6663
 
-
6664
 
-    def printer_properties_response(self):
6665
 
-        name, type = self.getSelectedItem()
6666
 
-        if type in ("Printer", "Class"):
6667
 
-            return self.save_printer(self.printer)
6668
 
-        elif type == "Settings":
6669
 
-            return self.save_serversettings()
6670
 
-
6671
 
-    def on_tvMainList_changed(self, new, old):
6672
 
-        """about to change, offer to save"""
6673
 
-        if self.changed:
6674
 
-            answer = QMessageBox.question(self, "Save Changes", "Do you want to save changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Save)
6675
 
-            if answer == QMessageBox.Save:
6676
 
-                self.printer_properties_response()
6677
 
-            elif answer == QMessageBox.Discard:
6678
 
-                self.changed = set() # avoid asking the user
6679
 
-
6680
 
-    def busy (self, win = None):
6681
 
-        try:
6682
 
-            if not win:
6683
 
-                win = self
6684
 
-            win.setCursor(Qt.WaitCursor)
6685
 
-            QApplication.processEvents()
6686
 
-        except:
6687
 
-            nonfatalException ()
6688
 
-
6689
 
-    def ready (self, win = None):
6690
 
-        try:
6691
 
-            if not win:
6692
 
-                win = self
6693
 
-            win.setCursor(Qt.ArrowCursor)
6694
 
-            QApplication.processEvents()
6695
 
-        except:
6696
 
-            nonfatalException ()
6697
 
-
6698
 
-    def setConnected(self):
6699
 
-        connected = bool(self.cups)
6700
 
-
6701
 
-        host = cups.getServer()
6702
 
-
6703
 
-        if host[0] == '/':
6704
 
-            host = 'localhost'
6705
 
-        self.setWindowTitle(i18n("Printer configuration - %1", host))
6706
 
-
6707
 
-        if connected:
6708
 
-            status_msg = i18n("Connected to %1", host)
6709
 
-        else:
6710
 
-            status_msg = i18n("Not connected")
6711
 
-        #FIXME do we want a statusbar? 
6712
 
-        #self.statusbarMain.push(self.status_context_id, status_msg)
6713
 
-
6714
 
-        for widget in (#FIXMEself.btnNewPrinter, self.btnNewClass,
6715
 
-                       #self.new_printer, self.new_class,
6716
 
-                       self.chkServerBrowse, self.chkServerShare,
6717
 
-                       self.chkServerRemoteAdmin,
6718
 
-                       self.chkServerAllowCancelAll,
6719
 
-                       self.chkServerLogDebug):
6720
 
-            widget.setEnabled(connected)
6721
 
-
6722
 
-        sharing = self.chkServerShare.isChecked ()
6723
 
-        self.chkServerShareAny.setEnabled (sharing)
6724
 
-
6725
 
-        try:
6726
 
-            del self.server_settings
6727
 
-        except:
6728
 
-            pass
6729
 
-
6730
 
-    def populateList(self, start_printer = None, change_ppd = False):
6731
 
-        #FIXMEold_name, old_type = self.getSelectedItem()
6732
 
-        old_name = ""
6733
 
-        old_type = ""
6734
 
-
6735
 
-        select_path = None
6736
 
-
6737
 
-        if self.cups:
6738
 
-            try:
6739
 
-                # get Printers
6740
 
-                self.printers = cupshelpers.getPrinters(self.cups)
6741
 
-
6742
 
-                # Get default printer.
6743
 
-                try:
6744
 
-                    self.default_printer = self.cups.getDefault ()
6745
 
-                except AttributeError: # getDefault appeared in pycups-1.9.31
6746
 
-                    # This fetches the list of printers and classes *again*,
6747
 
-                    # just to find out the default printer.
6748
 
-                    dests = self.cups.getDests ()
6749
 
-                    if dests.has_key ((None,None)):
6750
 
-                        self.default_printer = dests[(None,None)].name
6751
 
-                    else:
6752
 
-                        self.default_printer = None
6753
 
-            except cups.IPPError, (e, m):
6754
 
-                self.show_IPP_Error(e, m)
6755
 
-                self.printers = {}
6756
 
-                self.default_printer = None
6757
 
-        else:
6758
 
-            self.printers = {}
6759
 
-            self.default_printer = None
6760
 
-
6761
 
-        local_printers = []
6762
 
-        local_classes = []
6763
 
-        remote_printers = []
6764
 
-        remote_classes = []
6765
 
-
6766
 
-        for name, printer in self.printers.iteritems():
6767
 
-            if printer.default:
6768
 
-                self.default_printer = name
6769
 
-            self.servers.add(printer.getServer())
6770
 
-
6771
 
-            if printer.remote:
6772
 
-                if printer.is_class: remote_classes.append(name)
6773
 
-                else: remote_printers.append(name)
6774
 
-            else:
6775
 
-                if printer.is_class: local_classes.append(name)
6776
 
-                else: local_printers.append(name)
6777
 
-
6778
 
-        local_printers.sort()
6779
 
-        local_classes.sort()
6780
 
-        remote_printers.sort()
6781
 
-        remote_classes.sort()
6782
 
-
6783
 
-        if (old_name != "" and
6784
 
-            (not old_name in local_printers) and
6785
 
-            (not old_name in local_classes) and
6786
 
-            (not old_name in remote_printers) and
6787
 
-            (not old_name in remote_classes)):
6788
 
-            # The previously selected printer no longer exists.
6789
 
-            old_name = ""
6790
 
-
6791
 
-        if (self.default_printer != None and
6792
 
-            start_printer == None and
6793
 
-            old_name == ""):
6794
 
-            start_printer = self.default_printer
6795
 
-
6796
 
-        if not start_printer:
6797
 
-            start_printer = old_name
6798
 
-
6799
 
-        expanded = {
6800
 
-            "_printers" : True,
6801
 
-            "_classes" : True,
6802
 
-            "_remote_printers" : True,
6803
 
-            "_remote_classes" : True,
6804
 
-            }
6805
 
-
6806
 
-        """
6807
 
-        # remove old printers/classes
6808
 
-        iter = self.mainlist.get_iter_first()
6809
 
-        iter = self.mainlist.iter_next(iter) # step over server settings
6810
 
-        while iter:
6811
 
-            entry = self.mainlist.get_value(iter, 1)
6812
 
-            path = self.mainlist.get_path(iter)
6813
 
-            expanded[entry] = self.tvMainList.row_expanded(path)
6814
 
-            more_entries =  self.mainlist.remove(iter)
6815
 
-            if not more_entries: break
6816
 
-        """
6817
 
-        self.mainlist.clear()
6818
 
-        QTreeWidgetItem(self.mainlist, ["New Printer", 'New'])
6819
 
-        self.settingsItem = QTreeWidgetItem(self.mainlist, ["Server Settings", 'Settings'])
6820
 
-
6821
 
-        # add new
6822
 
-        for printers, text, name in (
6823
 
-            (local_printers, i18n("Local Printers"), "_printers"),
6824
 
-            (local_classes, i18n("Local Classes"), "_classes"),
6825
 
-            (remote_printers, i18n("Remote Printers"), "_remote_printers"),
6826
 
-            (remote_classes, i18n("Remote Classes"), "_remote_classes")):
6827
 
-            if not printers: continue
6828
 
-
6829
 
-            #self.mainlist.addTopLevelItem(QTreeWidgetItem(self.mainlist, text))
6830
 
-            rootTreeItem = QTreeWidgetItem(self.mainlist, [text, name])
6831
 
-            #iter = self.mainlist.append(None, (text, name))
6832
 
-            #path = self.mainlist.get_path(iter)
6833
 
-
6834
 
-            for printer_name in printers:
6835
 
-                if start_printer == None:
6836
 
-                    start_printer = printer_name
6837
 
-                treeItem = QTreeWidgetItem(rootTreeItem, [printer_name, "Printer"])
6838
 
-                #p_iter = self.mainlist.append(iter, (printer_name, "Printer"))
6839
 
-                if printer_name==start_printer:
6840
 
-                    treeItem.setSelected(True)
6841
 
-                    expanded[name] = True
6842
 
-            if expanded[name]:
6843
 
-                rootTreeItem.setExpanded(True)
6844
 
-                #self.tvMainList.expand_row(path, False)
6845
 
-        self.on_tvMainList_cursor_changed()
6846
 
-        self.setDataButtonState()
6847
 
-
6848
 
-        """FIXME
6849
 
-        if change_ppd:
6850
 
-            self.on_btnChangePPD_clicked (self.btnChangePPD)
6851
 
-        """
6852
 
-
6853
 
-    #TODO
6854
 
-    # Connect to Server
6855
 
-
6856
 
-    def on_printer_changed(self, text):
6857
 
-        widget = self.sender()
6858
 
-        if not widget:  #method called as a method not a slot
6859
 
-            return
6860
 
-        if isinstance(widget, QCheckBox):
6861
 
-            value = widget.isChecked()
6862
 
-        elif isinstance(widget, QLineEdit):
6863
 
-            value = unicode(widget.text())
6864
 
-        elif isinstance(widget, QRadioButton):
6865
 
-            value = widget.isChecked()
6866
 
-        elif isinstance(widget, QComboBox):
6867
 
-            value = unicode(widget.currentText())
6868
 
-        else:
6869
 
-            raise ValueError, "Widget type not supported (yet)"
6870
 
-
6871
 
-        p = self.printer
6872
 
-        old_values = {
6873
 
-            self.entPDescription : p.info,
6874
 
-            self.entPLocation : p.location,
6875
 
-            self.entPDevice : p.device_uri,
6876
 
-            self.chkPEnabled : p.enabled,
6877
 
-            self.chkPAccepting : not p.rejecting,
6878
 
-            self.chkPShared : p.is_shared,
6879
 
-            self.cmbPStartBanner : p.job_sheet_start,
6880
 
-            self.cmbPEndBanner : p.job_sheet_end,
6881
 
-            self.cmbPErrorPolicy : p.error_policy,
6882
 
-            self.cmbPOperationPolicy : p.op_policy,
6883
 
-            #self.rbtnPAllow: p.default_allow, #FIXME access control tab
6884
 
-            }
6885
 
-
6886
 
-        old_value = old_values[widget]
6887
 
-
6888
 
-        if old_value == value:
6889
 
-            self.changed.discard(widget)
6890
 
-        else:
6891
 
-            self.changed.add(widget)
6892
 
-        self.setDataButtonState()
6893
 
-
6894
 
-    #TODO
6895
 
-    # Access control
6896
 
-
6897
 
-    #TODO
6898
 
-    # Server side options
6899
 
-
6900
 
-    # set buttons sensitivity
6901
 
-    def setDataButtonState(self):
6902
 
-        try: # Might not be a printer selected
6903
 
-            possible = (self.ppd and
6904
 
-                        not bool (self.changed) and
6905
 
-                        self.printer.enabled and
6906
 
-                        not self.printer.rejecting)
6907
 
-
6908
 
-            self.btnPrintTestPage.setEnabled(possible)
6909
 
-
6910
 
-            commands = (self.printer.type & cups.CUPS_PRINTER_COMMANDS) != 0
6911
 
-            self.btnSelfTest.setEnabled(commands and possible)
6912
 
-            self.btnCleanHeads.setEnabled(commands and possible)
6913
 
-        except:
6914
 
-            debugprint ("exception in setDataButtonState")
6915
 
-            pass
6916
 
-
6917
 
-        installablebold = False
6918
 
-        optionsbold = False
6919
 
-        if self.conflicts:
6920
 
-            debugprint ("Conflicts detected")
6921
 
-            self.btnConflict.show()
6922
 
-            for option in self.conflicts:
6923
 
-                if option.tab_label == self.lblPInstallOptions:
6924
 
-                    installablebold = True
6925
 
-                else:
6926
 
-                    optionsbold = True
6927
 
-        else:
6928
 
-            self.btnConflict.hide()
6929
 
-        installabletext = i18n("Installable Options")
6930
 
-        optionstext = i18n("Printer Options")
6931
 
-        if installablebold:
6932
 
-            installabletext = i18nc("Conflicted entry", "<b>%1</b>", installabletext)
6933
 
-        if optionsbold:
6934
 
-            optionstext = i18nc("Conflicted entry", "<b>%1</b>", optionstext)
6935
 
-        self.lblPInstallOptions.setText(installabletext)
6936
 
-        self.lblPOptions.setText(optionstext)
6937
 
-
6938
 
-        """  FIXME
6939
 
-        store = self.tvPrinterProperties.get_model ()
6940
 
-        if store:
6941
 
-            for n in range (self.ntbkPrinter.get_n_pages ()):
6942
 
-                page = self.ntbkPrinter.get_nth_page (n)
6943
 
-                label = self.ntbkPrinter.get_tab_label (page)
6944
 
-                if label == self.lblPInstallOptions:
6945
 
-                    iter = store.get_iter ((n,))
6946
 
-                    store.set_value (iter, 0, installabletext)
6947
 
-                elif label == self.lblPOptions:
6948
 
-                    iter = store.get_iter ((n,))
6949
 
-                    store.set_value (iter, 0, optionstext)
6950
 
-        """
6951
 
-
6952
 
-        self.btnPrinterPropertiesApply.setEnabled(len (self.changed) > 0)
6953
 
-        self.btnRevert.setEnabled(len (self.changed) > 0)
6954
 
-
6955
 
-    def save_printer(self, printer, saveall=False):
6956
 
-        class_deleted = False
6957
 
-        name = printer.name
6958
 
-
6959
 
-        try:
6960
 
-            if not printer.is_class and self.ppd: 
6961
 
-                self.getPrinterSettings()
6962
 
-                if self.ppd.nondefaultsMarked() or saveall:
6963
 
-                    self.passwd_retry = False # use cached Passwd 
6964
 
-                    self.cups.addPrinter(name, ppd=self.ppd)
6965
 
-
6966
 
-            #FIXME classes
6967
 
-            if printer.is_class:
6968
 
-                pass
6969
 
-                """
6970
 
-                # update member list
6971
 
-                new_members = self.getCurrentClassMembers(self.tvClassMembers)
6972
 
-                if not new_members:
6973
 
-                    dialog = gtk.MessageDialog(
6974
 
-                        flags=0, type=gtk.MESSAGE_WARNING,
6975
 
-                        buttons=gtk.BUTTONS_YES_NO,
6976
 
-                        message_format=_("This will delete this class!"))
6977
 
-                    dialog.format_secondary_text(_("Proceed anyway?"))
6978
 
-                    result = dialog.run()
6979
 
-                    dialog.destroy()
6980
 
-                    if result==gtk.RESPONSE_NO:
6981
 
-                        return True
6982
 
-                    class_deleted = True
6983
 
-
6984
 
-                # update member list
6985
 
-                old_members = printer.class_members[:]
6986
 
-
6987
 
-                for member in new_members:
6988
 
-                    if member in old_members:
6989
 
-                        old_members.remove(member)
6990
 
-                    else:
6991
 
-                        self.cups.addPrinterToClass(member, name)
6992
 
-                for member in old_members:
6993
 
-                    self.cups.deletePrinterFromClass(member, name)    
6994
 
-                """
6995
 
-
6996
 
-            location = unicode(self.entPLocation.text())
6997
 
-            info = unicode(self.entPDescription.text())
6998
 
-            device_uri = unicode(self.entPDevice.text())
6999
 
-            if device_uri.find (ellipsis) != -1:
7000
 
-                # The URI is sanitized and not editable.
7001
 
-                device_uri = printer.device_uri
7002
 
-
7003
 
-            enabled = self.chkPEnabled.isChecked()
7004
 
-            accepting = self.chkPAccepting.isChecked()
7005
 
-            shared = self.chkPShared.isChecked()
7006
 
-
7007
 
-            if info!=printer.info or saveall:
7008
 
-                self.passwd_retry = False # use cached Passwd 
7009
 
-                self.cups.setPrinterInfo(name, info)
7010
 
-            if location!=printer.location or saveall:
7011
 
-                self.passwd_retry = False # use cached Passwd 
7012
 
-                self.cups.setPrinterLocation(name, location)
7013
 
-            if (not printer.is_class and
7014
 
-                (device_uri!=printer.device_uri or saveall)):
7015
 
-                self.passwd_retry = False # use cached Passwd 
7016
 
-                self.cups.setPrinterDevice(name, device_uri)
7017
 
-
7018
 
-            if enabled != printer.enabled or saveall:
7019
 
-                self.passwd_retry = False # use cached Passwd 
7020
 
-                self.printer.setEnabled(enabled)
7021
 
-            if accepting == printer.rejecting or saveall:
7022
 
-                self.passwd_retry = False # use cached Passwd 
7023
 
-                self.printer.setAccepting(accepting)
7024
 
-            if shared != printer.is_shared or saveall:
7025
 
-                self.passwd_retry = False # use cached Passwd 
7026
 
-                self.printer.setShared(shared)
7027
 
-
7028
 
-            job_sheet_start = unicode(self.cmbPStartBanner.currentText())
7029
 
-            job_sheet_end = unicode(self.cmbPEndBanner.currentText())
7030
 
-            error_policy = unicode(self.cmbPErrorPolicy.currentText())
7031
 
-            op_policy = unicode(self.cmbPOperationPolicy.currentText())
7032
 
-
7033
 
-            if (job_sheet_start != printer.job_sheet_start or
7034
 
-                job_sheet_end != printer.job_sheet_end) or saveall:
7035
 
-                self.passwd_retry = False # use cached Passwd
7036
 
-                printer.setJobSheets(job_sheet_start, job_sheet_end)
7037
 
-            if error_policy != printer.error_policy or saveall:
7038
 
-                self.passwd_retry = False # use cached Passwd
7039
 
-                printer.setErrorPolicy(error_policy)
7040
 
-            if op_policy != printer.op_policy or saveall:
7041
 
-                self.passwd_retry = False # use cached Passwd
7042
 
-                printer.setOperationPolicy(op_policy)
7043
 
-
7044
 
-            """FIXME TODO access
7045
 
-            default_allow = self.rbtnPAllow.get_active()
7046
 
-            except_users = self.getPUsers()
7047
 
-
7048
 
-            if (default_allow != printer.default_allow or
7049
 
-                except_users != printer.except_users) or saveall:
7050
 
-                self.passwd_retry = False # use cached Passwd
7051
 
-                printer.setAccess(default_allow, except_users)
7052
 
-
7053
 
-            for option in printer.attributes:
7054
 
-                if option not in self.server_side_options:
7055
 
-                    printer.unsetOption(option)
7056
 
-            for option in self.server_side_options.itervalues():
7057
 
-                if option.is_changed() or saveall:
7058
 
-                    printer.setOption(option.name, option.get_current_value())
7059
 
-            """
7060
 
-        except cups.IPPError, (e, s):
7061
 
-            self.show_IPP_Error(e, s)
7062
 
-            return True
7063
 
-        self.changed = set() # of options
7064
 
-        if not self.__dict__.has_key ("server_settings"):
7065
 
-            # We can authenticate with the server correctly at this point,
7066
 
-            # but we have never fetched the server settings to see whether
7067
 
-            # the server is publishing shared printers.  Fetch the settings
7068
 
-            # now so that we can update the "not published" label if necessary.
7069
 
-            try:
7070
 
-                self.server_settings = self.cups.adminGetServerSettings()
7071
 
-            except:
7072
 
-                nonfatalException()
7073
 
-
7074
 
-        if class_deleted:
7075
 
-            self.populateList ()
7076
 
-        else:
7077
 
-            # Update our copy of the printer's settings.
7078
 
-            printers = cupshelpers.getPrinters (self.cups)
7079
 
-            this_printer = { name: printers[name] }
7080
 
-            self.printers.update (this_printer)
7081
 
-
7082
 
-        return False
7083
 
-
7084
 
-    def getPrinterSettings(self):
7085
 
-        #self.ppd.markDefaults()
7086
 
-        for option in self.options.itervalues():
7087
 
-            option.writeback()
7088
 
-
7089
 
-    @pyqtSignature("")
7090
 
-    def on_btnPrintTestPage_clicked(self):
7091
 
-        if self.test_button_cancels:
7092
 
-            jobs = self.printer.testsQueued ()
7093
 
-            for job in jobs:
7094
 
-                debugprint ("Canceling job %s" % job)
7095
 
-                try:
7096
 
-                    self.cups.cancelJob (job)
7097
 
-                except cups.IPPError, (e, msg):
7098
 
-                    self.show_IPP_Error(e, msg)
7099
 
-            self.setTestButton (self.printer)
7100
 
-            return
7101
 
-        try:
7102
 
-            # if we have a page size specific custom test page, use it;
7103
 
-            # otherwise use cups' default one
7104
 
-            custom_testpage = None
7105
 
-            opt = self.ppd.findOption ("PageSize")
7106
 
-            if opt:
7107
 
-                custom_testpage = os.path.join(SYSTEM_CONFIG_PRINTER_DIR, 'testpage-%s.ps' % opt.defchoice.lower())
7108
 
-
7109
 
-            if custom_testpage and os.path.exists(custom_testpage):
7110
 
-                debugprint ('Printing custom test page ' + custom_testpage)
7111
 
-                job_id = self.cups.printTestPage(self.printer.name,
7112
 
-                    file=custom_testpage)
7113
 
-            else:
7114
 
-                debugprint ('Printing default test page')
7115
 
-                job_id = self.cups.printTestPage(self.printer.name)
7116
 
-
7117
 
-            self.setTestButton (self.printer)
7118
 
-            QMessageBox.information(self, i18nc("Test page submitted", "Submitted"), i18n("Test page submitted as "
7119
 
-                                                            "job %d") % job_id)
7120
 
-        except cups.IPPError, (e, msg):
7121
 
-            if (e == cups.IPP_NOT_AUTHORIZED and
7122
 
-                self.connect_server != 'localhost' and
7123
 
-                self.connect_server[0] != '/'):
7124
 
-                self.lblError.set_markup ('<span size="larger">'+
7125
 
-                                          i18n("<b>Not possible</b>") + '</span>\n\n' +
7126
 
-                                          i18n("The remote server did not accept "
7127
 
-                                            "the print job, most likely "
7128
 
-                                            "because the printer is not "
7129
 
-                                            "shared."))
7130
 
-                self.ErrorDialog.set_transient_for (self.MainWindow)
7131
 
-                self.ErrorDialog.run ()
7132
 
-                self.ErrorDialog.hide ()
7133
 
-            else:
7134
 
-                self.show_IPP_Error(e, msg)
7135
 
-
7136
 
-    def maintenance_command (self, command):
7137
 
-        (tmpfd, tmpfname) = tempfile.mkstemp ()
7138
 
-        os.write (tmpfd, "#CUPS-COMMAND\n%s\n" % command)
7139
 
-        os.close (tmpfd)
7140
 
-        try:
7141
 
-            format = "application/vnd.cups-command"
7142
 
-            job_id = self.cups.printTestPage (self.printer.name,
7143
 
-                                              format=format,
7144
 
-                                              file=tmpfname,
7145
 
-                                              user=self.connect_user)
7146
 
-            self.lblInfo.set_markup ('<span size="larger">' +
7147
 
-                                     i18nc("Maintenance command submitted", "<b>Submitted</b>") + '</span>\n\n' +
7148
 
-                                     i18n("Maintenance command submitted as "
7149
 
-                                       "job %d") % job_id)
7150
 
-            self.InfoDialog.set_transient_for (self.MainWindow)
7151
 
-            self.InfoDialog.run ()
7152
 
-            self.InfoDialog.hide ()
7153
 
-        except cups.IPPError, (e, msg):
7154
 
-            if (e == cups.IPP_NOT_AUTHORIZED and
7155
 
-                self.printer.name != 'localhost'):
7156
 
-                self.lblError.set_markup ('<span size="larger">'+
7157
 
-                                          i18n("<b>Not possible</b>") + '</span>\n\n' +
7158
 
-                                          i18n("The remote server did not accept "
7159
 
-                                            "the print job, most likely "
7160
 
-                                            "because the printer is not "
7161
 
-                                            "shared."))
7162
 
-                self.ErrorDialog.set_transient_for (self.MainWindow)
7163
 
-                self.ErrorDialog.run ()
7164
 
-                self.ErrorDialog.hide ()
7165
 
-            else:
7166
 
-                self.show_IPP_Error(e, msg)
7167
 
-
7168
 
-    @pyqtSignature("")
7169
 
-    def on_btnSelfTest_clicked(self):
7170
 
-        self.maintenance_command ("PrintSelfTestPage")
7171
 
-
7172
 
-    @pyqtSignature("")
7173
 
-    def on_btnCleanHeads_clicked(self):
7174
 
-        self.maintenance_command ("Clean all")
7175
 
-
7176
 
-    def fillComboBox(self, combobox, values, value):
7177
 
-        combobox.clear()
7178
 
-        for nr, val in enumerate(values):
7179
 
-            combobox.addItem(val)
7180
 
-            if val == value: 
7181
 
-                combobox.setCurrentIndex(nr)
7182
 
-
7183
 
-    def fillPrinterTab(self, name):
7184
 
-        self.changed = set() # of options
7185
 
-        self.options = {} # keyword -> Option object
7186
 
-        self.conflicts = set() # of options
7187
 
-
7188
 
-        printer = self.printers[name] 
7189
 
-        self.printer = printer
7190
 
-        printer.getAttributes ()
7191
 
-
7192
 
-        editable = not self.printer.discovered
7193
 
-        editablePPD = not self.printer.remote
7194
 
-
7195
 
-        try:
7196
 
-            self.ppd = printer.getPPD()
7197
 
-        except cups.IPPError, (e, m):
7198
 
-            # Some IPP error other than IPP_NOT_FOUND.
7199
 
-            self.show_IPP_Error(e, m)
7200
 
-            # Treat it as a raw queue.
7201
 
-            self.ppd = False
7202
 
-        except RuntimeError:
7203
 
-            # The underlying cupsGetPPD2() function returned NULL without
7204
 
-            # setting an IPP error, so it'll be something like a failed
7205
 
-            # connection.
7206
 
-            #FIXME show a dialogue
7207
 
-            debugprint("Error!")
7208
 
-            """
7209
 
-            self.lblError.set_markup('<span size="larger">' +
7210
 
-                                     _("<b>Error</b>") + '</span>\n\n' +
7211
 
-                                     _("There was a problem connecting to "
7212
 
-                                       "the CUPS server."))
7213
 
-            self.ErrorDialog.set_transient_for(self.MainWindow)
7214
 
-            self.ErrorDialog.run()
7215
 
-            self.ErrorDialog.hide()
7216
 
-            """
7217
 
-            raise
7218
 
-
7219
 
-        for widget in (self.entPDescription, self.entPLocation,
7220
 
-                       self.entPDevice):
7221
 
-            widget.setReadOnly(not editable)
7222
 
-
7223
 
-        for widget in (self.btnSelectDevice, self.btnChangePPD):
7224
 
-            """,FIXME
7225
 
-                       self.chkPEnabled, self.chkPAccepting, self.chkPShared,
7226
 
-                       self.cmbPStartBanner, self.cmbPEndBanner,
7227
 
-                       self.cmbPErrorPolicy, self.cmbPOperationPolicy,
7228
 
-                       self.rbtnPAllow, self.rbtnPDeny, self.tvPUsers,
7229
 
-                       self.entPUser, self.btnPAddUser, self.btnPDelUser):
7230
 
-            """
7231
 
-            widget.setEnabled(editable)
7232
 
-
7233
 
-        # Description page
7234
 
-        self.entPDescription.setText(printer.info)
7235
 
-        self.entPLocation.setText(printer.location)
7236
 
-        #obsolete self.lblPMakeModel.setText(printer.make_and_model)
7237
 
-        #obsolete self.lblPState.setText(printer.state_description)
7238
 
-
7239
 
-        uri = printer.device_uri
7240
 
-        if uri.startswith("smb://"):
7241
 
-            (group, host, share,
7242
 
-             user, password) = SMBURI (uri=uri[6:]).separate ()
7243
 
-            if password:
7244
 
-                uri = "smb://"
7245
 
-                if len (user) or len (password):
7246
 
-                    uri += ellipsis
7247
 
-                uri += SMBURI (group=group, host=host, share=share).get_uri ()
7248
 
-                self.entPDevice.setEnabled(False)
7249
 
-            else:
7250
 
-                self.entPDevice.setEnabled(True)
7251
 
-        self.entPDevice.setText(uri)
7252
 
-        self.changed.discard(self.entPDevice)
7253
 
-
7254
 
-        # Hide make/model and Device URI for classes
7255
 
-        for widget in (self.lblPMakeModel2, self.lblPMakeModel,
7256
 
-                       self.btnChangePPD, self.lblPDevice2,
7257
 
-                       self.entPDevice, self.btnSelectDevice):
7258
 
-            if printer.is_class:
7259
 
-                widget.hide()
7260
 
-            else:
7261
 
-                widget.show()
7262
 
-
7263
 
-
7264
 
-        # default printer
7265
 
-        self.btnPMakeDefault.setEnabled(not printer.default)
7266
 
-        if printer.default:
7267
 
-            self.lblPDefault.setText(i18n("This is the default printer"))
7268
 
-        elif self.default_printer:
7269
 
-            self.lblPDefault.setText(self.default_printer)
7270
 
-        else:
7271
 
-            self.lblPDefault.setText(i18n("No default printer set."))
7272
 
-
7273
 
-        self.setTestButton (printer)
7274
 
-
7275
 
-        # Policy tab
7276
 
-        # ----------
7277
 
-
7278
 
-        # State
7279
 
-        self.chkPEnabled.setChecked(printer.enabled)
7280
 
-        self.chkPAccepting.setChecked(not printer.rejecting)
7281
 
-        self.chkPShared.setChecked(printer.is_shared)
7282
 
-        try:
7283
 
-            if printer.is_shared:
7284
 
-                flag = cups.CUPS_SERVER_SHARE_PRINTERS
7285
 
-                publishing = int (self.server_settings[flag])
7286
 
-                if publishing:
7287
 
-                    self.lblNotPublished.hide()
7288
 
-                else:
7289
 
-                    self.lblNotPublished.show()
7290
 
-            else:
7291
 
-                self.lblNotPublished.hide()
7292
 
-        except:
7293
 
-            self.lblNotPublished.hide()
7294
 
-
7295
 
-        # Job sheets
7296
 
-        self.cmbPStartBanner.setEnabled(editable)
7297
 
-        self.cmbPEndBanner.setEnabled(editable)
7298
 
-
7299
 
-        # Policies
7300
 
-        self.cmbPErrorPolicy.setEnabled(editable)
7301
 
-        self.cmbPOperationPolicy.setEnabled(editable)
7302
 
-
7303
 
-        """
7304
 
-        # Access control
7305
 
-        self.rbtnPAllow.set_active(printer.default_allow)
7306
 
-        self.rbtnPDeny.set_active(not printer.default_allow)
7307
 
-        self.setPUsers(printer.except_users)
7308
 
-
7309
 
-        self.entPUser.set_text("")
7310
 
-
7311
 
-        # Server side options (Job options)
7312
 
-        self.server_side_options = {}
7313
 
-        for option in self.job_options_widgets.values ():
7314
 
-            if option.name == "media" and self.ppd:
7315
 
-                # Slightly special case because the 'system default'
7316
 
-                # (i.e. what you get when you press Reset) depends
7317
 
-                # on the printer's PageSize.
7318
 
-                opt = self.ppd.findOption ("PageSize")
7319
 
-                if opt:
7320
 
-                    option.set_default (opt.defchoice)
7321
 
-
7322
 
-            option_editable = editable
7323
 
-            try:
7324
 
-                value = self.printer.attributes[option.name]
7325
 
-            except KeyError:
7326
 
-                option.reinit (None)
7327
 
-            else:
7328
 
-                try:
7329
 
-                    if self.printer.possible_attributes.has_key (option.name):
7330
 
-                        supported = self.printer.\
7331
 
-                                    possible_attributes[option.name][1]
7332
 
-                        # Set the option widget.
7333
 
-                        # In CUPS 1.3.x the orientation-requested-default
7334
 
-                        # attribute may have the value None; this means there
7335
 
-                        # is no value set.  This suits our needs here, as None
7336
 
-                        # resets the option to the system default and makes the
7337
 
-                        # Reset button insensitive.
7338
 
-                        option.reinit (value, supported=supported)
7339
 
-                    else:
7340
 
-                        option.reinit (value)
7341
 
-
7342
 
-                    self.server_side_options[option.name] = option
7343
 
-                except:
7344
 
-                    option_editable = False
7345
 
-                    self.lblError.set_markup ('<span ' +
7346
 
-                                              'size="larger">' +
7347
 
-                                              _("<b>Error</b>") + '</span>\n\n' +
7348
 
-                                              _("Option '%s' has value '%s' "
7349
 
-                                                "and cannot be edited.") %
7350
 
-                                              (option.name, value))
7351
 
-                    self.ErrorDialog.set_transient_for (self.MainWindow)
7352
 
-                    self.ErrorDialog.run()
7353
 
-                    self.ErrorDialog.hide()
7354
 
-            option.widget.set_sensitive (option_editable)
7355
 
-            if not editable:
7356
 
-                option.button.set_sensitive (False)
7357
 
-        self.other_job_options = []
7358
 
-        self.draw_other_job_options (editable=editable)
7359
 
-        for option in self.printer.attributes.keys ():
7360
 
-            if self.server_side_options.has_key (option):
7361
 
-                continue
7362
 
-            supported = ""
7363
 
-            if self.printer.possible_attributes.has_key (option):
7364
 
-                supported = self.printer.possible_attributes[option][1]
7365
 
-            self.add_job_option (option, value=self.printer.attributes[option],
7366
 
-                                 supported=supported, is_new=False,
7367
 
-                                 editable=editable)
7368
 
-        self.entNewJobOption.set_text ('')
7369
 
-        self.entNewJobOption.set_sensitive (editable)
7370
 
-        self.btnNewJobOption.set_sensitive (False)
7371
 
-
7372
 
-        if printer.is_class:
7373
 
-            # remove InstallOptions tab
7374
 
-            tab_nr = self.ntbkPrinter.page_num(self.swPInstallOptions)
7375
 
-            if tab_nr != -1:
7376
 
-                self.ntbkPrinter.remove_page(tab_nr)
7377
 
-            self.fillClassMembers(name, editable)
7378
 
-        else:
7379
 
-            # real Printer
7380
 
-            self.fillPrinterOptions(name, editablePPD)
7381
 
-
7382
 
-        """
7383
 
-        self.changed = set() # of options
7384
 
-        self.updatePrinterProperties ()
7385
 
-        self.setDataButtonState()
7386
 
-
7387
 
-    def fillPrinterOptions(self):
7388
 
-        return #FIXME TODO options tabs
7389
 
-
7390
 
-    #In Gnome is now on_delete_activate(self, UNUSED):
7391
 
-    @pyqtSignature("")
7392
 
-    def on_btnDelete_clicked(self):
7393
 
-        name, type = self.getSelectedItem()
7394
 
-        print name
7395
 
-
7396
 
-        # Confirm
7397
 
-        if type == "Printer":
7398
 
-            message_format = i18n("Really delete printer %s?")
7399
 
-        else:
7400
 
-            message_format = i18n("Really delete class %s?")
7401
 
-
7402
 
-       cancel = QMessageBox.question(self,"",
7403
 
-                unicode(message_format) % name,
7404
 
-                i18n("&Yes"), i18n("&No"),
7405
 
-                QString(), 0, 1)
7406
 
-
7407
 
-        if cancel:
7408
 
-            return
7409
 
-        try:
7410
 
-            self.cups.deletePrinter(name)
7411
 
-        except cups.IPPError, (e, msg):
7412
 
-            self.show_IPP_Error(e, msg)
7413
 
-
7414
 
-        self.changed = set()
7415
 
-        self.populateList()
7416
 
-        self.mainlist.setCurrentItem(self.mainlist.itemAt(0,0))
7417
 
-
7418
 
-    #in Gnome side is now  set_default_printer (self, name):
7419
 
-    @pyqtSignature("")
7420
 
-    def on_btnPMakeDefault_clicked(self):
7421
 
-        try:
7422
 
-            self.cups.setDefault(self.printer.name)
7423
 
-        except cups.IPPError, (e, msg):
7424
 
-            self.show_IPP_Error(e, msg)
7425
 
-            return
7426
 
-
7427
 
-        # Also need to check system-wide lpoptions because that's how
7428
 
-        # previous Fedora versions set the default (bug #217395).
7429
 
-        (tmpfd, tmpfname) = tempfile.mkstemp ()
7430
 
-        success = False
7431
 
-        try:
7432
 
-            resource = "/admin/conf/lpoptions"
7433
 
-            self.cups.getFile(resource, tmpfname)
7434
 
-            #success = True
7435
 
-        except cups.HTTPError, (s,):
7436
 
-            try:
7437
 
-                os.remove (tmpfname)
7438
 
-            except OSError:
7439
 
-                pass
7440
 
-
7441
 
-            if s != cups.HTTP_NOT_FOUND:
7442
 
-                self.show_HTTP_Error(s)
7443
 
-                return
7444
 
-
7445
 
-        if success:
7446
 
-            lines = file (tmpfname).readlines ()
7447
 
-            changed = False
7448
 
-            i = 0
7449
 
-            for line in lines:
7450
 
-                if line.startswith ("Default "):
7451
 
-                    # This is the system-wide default.
7452
 
-                    name = line.split (' ')[1]
7453
 
-                    if name != self.printer.name:
7454
 
-                        # Stop it from over-riding the server default.
7455
 
-                        lines[i] = "Dest " + line[8:]
7456
 
-                        changed = True
7457
 
-                i += 1
7458
 
-
7459
 
-            if changed:
7460
 
-                file (tmpfname, 'w').writelines (lines)
7461
 
-                try:
7462
 
-                    self.cups.putFile (resource, tmpfname)
7463
 
-                except cups.HTTPError, (s,):
7464
 
-                    os.remove (tmpfname)
7465
 
-                    print s
7466
 
-                    self.show_HTTP_Error(s)
7467
 
-                    return
7468
 
-
7469
 
-                # Now reconnect because the server needs to reload.
7470
 
-                self.reconnect ()
7471
 
-
7472
 
-        try:
7473
 
-            os.remove (tmpfname)
7474
 
-        except OSError:
7475
 
-            pass
7476
 
-
7477
 
-        try:
7478
 
-            self.populateList()
7479
 
-        except cups.HTTPError, (s,):
7480
 
-            self.cups = None
7481
 
-            self.setConnected()
7482
 
-            self.populateList()
7483
 
-            self.show_HTTP_Error(s)
7484
 
-
7485
 
-    ##########################################################################
7486
 
-    ### Server settings
7487
 
-    ##########################################################################
7488
 
-
7489
 
-    def fillServerTab(self):
7490
 
-        self.changed = set()
7491
 
-        try:
7492
 
-            self.server_settings = self.cups.adminGetServerSettings()
7493
 
-        except cups.IPPError, (e, m):
7494
 
-            #FIXME
7495
 
-            self.show_IPP_Error(e, m)
7496
 
-            self.tvMainList.get_selection().unselect_all()
7497
 
-            self.on_tvMainList_cursor_changed(self.tvMainList)
7498
 
-            return
7499
 
-
7500
 
-        for widget, setting in [
7501
 
-            (self.chkServerBrowse, cups.CUPS_SERVER_REMOTE_PRINTERS),
7502
 
-            (self.chkServerShare, cups.CUPS_SERVER_SHARE_PRINTERS),
7503
 
-            (self.chkServerShareAny, try_CUPS_SERVER_REMOTE_ANY),
7504
 
-            (self.chkServerRemoteAdmin, cups.CUPS_SERVER_REMOTE_ADMIN),
7505
 
-            (self.chkServerAllowCancelAll, cups.CUPS_SERVER_USER_CANCEL_ANY),
7506
 
-            (self.chkServerLogDebug, cups.CUPS_SERVER_DEBUG_LOGGING),]:
7507
 
-            # widget.set_data("setting", setting)
7508
 
-            self.widget_data_setting[widget] = setting
7509
 
-            self.disconnect(widget, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
7510
 
-            if self.server_settings.has_key(setting):
7511
 
-                widget.setChecked(int(self.server_settings[setting]))
7512
 
-                widget.setEnabled(True)
7513
 
-            else:
7514
 
-                widget.setChecked(False)
7515
 
-                widget.setEnabled(False)
7516
 
-            self.connect(widget, SIGNAL("stateChanged(int)"), self.on_server_widget_changed)
7517
 
-        self.setDataButtonState()
7518
 
-        # Set sensitivity of 'Allow printing from the Internet'.
7519
 
-        self.on_server_changed (self.chkServerShare) # (any will do here)
7520
 
-
7521
 
-    def on_server_widget_changed(self, value):
7522
 
-        self.on_server_changed(self.sender())
7523
 
-
7524
 
-    def on_server_changed(self, widget):
7525
 
-        #setting = widget.get_data("setting")
7526
 
-        #print "widget_data_setting " + str(self.widget_data_setting)
7527
 
-        #print "widget " + str(widget)
7528
 
-        setting = self.widget_data_setting[widget]
7529
 
-        if self.server_settings.has_key (setting):
7530
 
-            if str(int(widget.isChecked())) == self.server_settings[setting]:
7531
 
-                self.changed.discard(widget)
7532
 
-            else:
7533
 
-                self.changed.add(widget)
7534
 
-
7535
 
-        sharing = self.chkServerShare.isChecked ()
7536
 
-        self.chkServerShareAny.setEnabled (
7537
 
-            sharing and self.server_settings.has_key(try_CUPS_SERVER_REMOTE_ANY))
7538
 
-
7539
 
-        self.setDataButtonState()
7540
 
-
7541
 
-    def save_serversettings(self):
7542
 
-        setting_dict = self.server_settings.copy()
7543
 
-        for widget, setting in [
7544
 
-            (self.chkServerBrowse, cups.CUPS_SERVER_REMOTE_PRINTERS),
7545
 
-            (self.chkServerShare, cups.CUPS_SERVER_SHARE_PRINTERS),
7546
 
-            (self.chkServerShareAny, try_CUPS_SERVER_REMOTE_ANY),
7547
 
-            (self.chkServerRemoteAdmin, cups.CUPS_SERVER_REMOTE_ADMIN),
7548
 
-            (self.chkServerAllowCancelAll, cups.CUPS_SERVER_USER_CANCEL_ANY),
7549
 
-            (self.chkServerLogDebug, cups.CUPS_SERVER_DEBUG_LOGGING),]:
7550
 
-            if not self.server_settings.has_key(setting): continue
7551
 
-            setting_dict[setting] = str(int(widget.isChecked()))
7552
 
-        try:
7553
 
-            self.cups.adminSetServerSettings(setting_dict)
7554
 
-        except cups.IPPError, (e, m):
7555
 
-            self.show_IPP_Error(e, m)
7556
 
-            return True
7557
 
-        except RuntimeError, s:
7558
 
-            self.show_IPP_Error(None, s)
7559
 
-            return True
7560
 
-        self.changed = set()
7561
 
-        self.setDataButtonState()
7562
 
-        time.sleep(1) # give the server a chance to process our request
7563
 
-
7564
 
-        # Now reconnect, in case the server needed to reload.
7565
 
-        self.reconnect ()
7566
 
-
7567
 
-        # Refresh the server settings in case they have changed in the
7568
 
-        # mean time.
7569
 
-        try:
7570
 
-            self.fillServerTab()
7571
 
-        except:
7572
 
-            nonfatalException()
7573
 
-
7574
 
-    # ====================================================================
7575
 
-    # == New Printer Dialog ==============================================
7576
 
-    # ====================================================================
7577
 
-
7578
 
-    # new printer
7579
 
-    def on_new_printer_activate(self):
7580
 
-        self.busy()
7581
 
-        self.newPrinterGUI.init("printer")
7582
 
-        self.ready()
7583
 
-
7584
 
-    # new class
7585
 
-    def on_new_class_activate(self):
7586
 
-        self.newPrinterGUI.init("class")
7587
 
-
7588
 
-    @pyqtSignature("")
7589
 
-    def on_btnSelectDevice_clicked(self):
7590
 
-        self.newPrinterGUI.init("device")
7591
 
-
7592
 
-    @pyqtSignature("")
7593
 
-    def on_btnChangePPD_clicked(self):
7594
 
-        self.busy(self)
7595
 
-        self.newPrinterGUI.init("ppd")
7596
 
-        self.ready(self)
7597
 
-
7598
 
-    def checkNPName(self, name):
7599
 
-        if not name: return False
7600
 
-        name = name.lower()
7601
 
-        for printer in self.printers.values():
7602
 
-            if not printer.discovered and printer.name.lower()==name:
7603
 
-                return False
7604
 
-        return True
7605
 
-
7606
 
-    def makeNameUnique(self, name):
7607
 
-        """Make a suggested queue name valid and unique."""
7608
 
-        name = name.replace (" ", "_")
7609
 
-        name = name.replace ("/", "_")
7610
 
-        name = name.replace ("#", "_")
7611
 
-        if not self.checkNPName (name):
7612
 
-            suffix=2
7613
 
-            while not self.checkNPName (name + str (suffix)):
7614
 
-                suffix += 1
7615
 
-                if suffix == 100:
7616
 
-                    break
7617
 
-            name += str (suffix)
7618
 
-        return name
7619
 
-
7620
 
-    #TODO
7621
 
-    ## Watcher interface helpers
7622
 
-
7623
 
-    @pyqtSignature("")
7624
 
-    def on_btnRevert_clicked(self):
7625
 
-        self.changed = set() # avoid asking the user
7626
 
-        self.on_tvMainList_cursor_changed()
7627
 
-
7628
 
-    @pyqtSignature("")
7629
 
-    def on_btnPrinterPropertiesApply_clicked(self):
7630
 
-        err = self.printer_properties_response()
7631
 
-        if not err:
7632
 
-            self.populateList()
7633
 
-        else:
7634
 
-            nonfatalException()
7635
 
-
7636
 
-    def show_IPP_Error(self, exception, message):
7637
 
-        if exception == cups.IPP_NOT_AUTHORIZED:
7638
 
-            QMessageBox.critical(self, i18n('Not authorized'), i18n('The password may be incorrect.'))
7639
 
-        else:
7640
 
-            QMessageBox.critical(self, i18n('CUPS server error'), i18n("There was an error during the CUPS "\
7641
 
-                                                              "operation: '%1'.", message))
7642
 
-    def show_HTTP_Error(self, status):
7643
 
-        if (status == cups.HTTP_UNAUTHORIZED or
7644
 
-            status == cups.HTTP_FORBIDDEN):
7645
 
-            QMessageBox.critical(self, i18n('Not authorized'), 
7646
 
-                                 i18n('The password may be incorrect, or the '
7647
 
-                                   'server may be configured to deny '
7648
 
-                                   'remote administration.'))
7649
 
-        else:
7650
 
-            if status == cups.HTTP_BAD_REQUEST:
7651
 
-                msg = i18nc("HTTP error", "Bad request")
7652
 
-            elif status == cups.HTTP_NOT_FOUND:
7653
 
-                msg = i18nc("HTTP error", "Not found")
7654
 
-            elif status == cups.HTTP_REQUEST_TIMEOUT:
7655
 
-                msg = i18nc("HTTP error", "Request timeout")
7656
 
-            elif status == cups.HTTP_UPGRADE_REQUIRED:
7657
 
-                msg = i18nc("HTTP error", "Upgrade required")
7658
 
-            elif status == cups.HTTP_SERVER_ERROR:
7659
 
-                msg = i18nc("HTTP error", "Server error")
7660
 
-            elif status == -1:
7661
 
-                msg = i18nc("HTTP error", "Not connected")
7662
 
-            else:
7663
 
-                msg = i18nc("HTTP error", "status %1", status)
7664
 
-
7665
 
-        QMessageBox.critical(self, i18n('CUPS server error'), i18n("There was an HTTP error: %1.", msg))
7666
 
-
7667
 
-    def getSelectedItem(self):
7668
 
-        return str(self.mainListSelectedName).decode ('utf-8'), str(self.mainListSelectedType)
7669
 
-        """
7670
 
-        items = self.mainlist.selectedItems()
7671
 
-        if len(items) < 1:
7672
 
-            return ("", 'None')
7673
 
-            item = items[0]
7674
 
-            name = item.text(0)
7675
 
-            type = item.text(1)
7676
 
-            name = str(name).decode ('utf-8')
7677
 
-            return name.strip(), type
7678
 
-        """
7679
 
-
7680
 
-    def reconnect (self):
7681
 
-        """Reconnect to CUPS after the server has reloaded."""
7682
 
-        # libcups would handle the reconnection if we just told it to
7683
 
-        # do something, for example fetching a list of classes.
7684
 
-        # However, our local authentication certificate would be
7685
 
-        # invalidated by a server restart, so it is better for us to
7686
 
-        # handle the reconnection ourselves.
7687
 
-
7688
 
-        # Disconnect.
7689
 
-        self.cups = None
7690
 
-        self.setConnected()
7691
 
-
7692
 
-        cups.setServer(self.connect_server)
7693
 
-        cups.setUser(self.connect_user)
7694
 
-        attempt = 1
7695
 
-        while attempt <= 5:
7696
 
-            try:
7697
 
-                self.cups = cups.Connection ()
7698
 
-                break
7699
 
-            except RuntimeError:
7700
 
-                # Connection failed.
7701
 
-                time.sleep(1)
7702
 
-                attempt += 1
7703
 
-
7704
 
-        self.setConnected()
7705
 
-        self.passwd_retry = False
7706
 
-
7707
 
-    def updatePrinterProperties(self):
7708
 
-        debugprint ("update printer properties")
7709
 
-        printer = self.printer
7710
 
-        self.lblPMakeModel.setText(printer.make_and_model)
7711
 
-        state = self.printer_states.get (printer.state, i18nc("Printer state", "Unknown"))
7712
 
-       reason = printer.other_attributes.get ('printer-state-message', '')
7713
 
-       if len (reason) > 0:
7714
 
-           state += ' - ' + reason
7715
 
-        self.lblPState.setText(state)
7716
 
-        if len (self.changed) == 0:
7717
 
-            debugprint ("no changes yet: full printer properties update")
7718
 
-            # State
7719
 
-            self.chkPEnabled.setEnabled(printer.enabled)
7720
 
-            self.chkPAccepting.setEnabled(not printer.rejecting)
7721
 
-            self.chkPShared.setEnabled(printer.is_shared)
7722
 
-
7723
 
-            # Job sheets
7724
 
-            self.fillComboBox(self.cmbPStartBanner,
7725
 
-                              printer.job_sheets_supported,
7726
 
-                              printer.job_sheet_start),
7727
 
-            self.fillComboBox(self.cmbPEndBanner, printer.job_sheets_supported,
7728
 
-                              printer.job_sheet_end)
7729
 
-
7730
 
-            # Policies
7731
 
-            self.fillComboBox(self.cmbPErrorPolicy,
7732
 
-                              printer.error_policy_supported,
7733
 
-                              printer.error_policy)
7734
 
-            self.fillComboBox(self.cmbPOperationPolicy,
7735
 
-                              printer.op_policy_supported,
7736
 
-                              printer.op_policy)
7737
 
-
7738
 
-            """
7739
 
-            # Access control
7740
 
-            self.rbtnPAllow.set_active(printer.default_allow)
7741
 
-            self.rbtnPDeny.set_active(not printer.default_allow)
7742
 
-            self.setPUsers(printer.except_users)
7743
 
-            """
7744
 
-
7745
 
-    def setTestButton (self, printer):
7746
 
-        if printer.testsQueued ():
7747
 
-            self.test_button_cancels = True
7748
 
-            self.btnPrintTestPage.setText(i18n('Cancel Tests'))
7749
 
-            self.btnPrintTestPage.setEnabled(True)
7750
 
-        else:
7751
 
-            self.test_button_cancels = False
7752
 
-            self.btnPrintTestPage.setText(i18n('Print Test Page'))
7753
 
-            self.setDataButtonState()
7754
 
-
7755
 
-    def getCurrentClassMembers(self, listwidget):
7756
 
-        count = listwidget.count()
7757
 
-        result = []
7758
 
-        for i in range(count):            
7759
 
-            result.append(listwidget.item(i).text())
7760
 
-        result.sort()
7761
 
-        return result
7762
 
-
7763
 
-    def moveClassMembers(self, treeview_from, treeview_to):
7764
 
-        rows = treeview_from.selectedItems()
7765
 
-        for row in rows:
7766
 
-            treeview_from.takeItem(treeview_from.row(row))
7767
 
-            treeview_to.addItem(row)
7768
 
-
7769
 
-    # Password handling
7770
 
-
7771
 
-    #FIXME obsolete?
7772
 
-    def cupsPasswdCallback(self, querystring):
7773
 
-        return "" #FIXME
7774
 
-        if self.passwd_retry or len(self.password) == 0:
7775
 
-            waiting = self.WaitWindow.get_property('visible')
7776
 
-            if waiting:
7777
 
-                self.WaitWindow.hide ()
7778
 
-            self.lblPasswordPrompt.set_label (self.prompt_primary +
7779
 
-                                              querystring)
7780
 
-            self.PasswordDialog.set_transient_for (self.MainWindow)
7781
 
-            self.entPasswd.grab_focus ()
7782
 
-
7783
 
-            result = self.PasswordDialog.run()
7784
 
-            self.PasswordDialog.hide()
7785
 
-            if waiting:
7786
 
-                self.WaitWindow.show ()
7787
 
-            while gtk.events_pending ():
7788
 
-                gtk.main_iteration ()
7789
 
-            if result == gtk.RESPONSE_OK:
7790
 
-                self.password = self.entPasswd.get_text()
7791
 
-            else:
7792
 
-                self.password = ''
7793
 
-            self.passwd_retry = False
7794
 
-        else:
7795
 
-            self.passwd_retry = True
7796
 
-        return self.password
7797
 
-
7798
 
-class NewPrinterGUI(QDialog):
7799
 
-
7800
 
-    new_printer_device_tabs = {
7801
 
-        "parallel" : 0, # empty tab
7802
 
-        "usb" : 0,
7803
 
-        "hal" : 0,
7804
 
-        "beh" : 0,
7805
 
-        "hp" : 0,
7806
 
-        "hpfax" : 0,
7807
 
-        "socket": 2,
7808
 
-        "ipp" : 3,
7809
 
-        "http" : 3,
7810
 
-        "lpd" : 4,
7811
 
-        "scsi" : 5,
7812
 
-        "serial" : 6,
7813
 
-        "smb" : 7,
7814
 
-        }
7815
 
-
7816
 
-    ntbkNewPrinterPages = {
7817
 
-        "name" : 0,
7818
 
-        "device" : 1,
7819
 
-        "make" : 2,
7820
 
-        "model" : 3,
7821
 
-        "class-members" : 4,
7822
 
-        "downloadable" : -1,
7823
 
-    }
7824
 
-
7825
 
-    def __init__(self, mainapp):
7826
 
-        QDialog.__init__(self, mainapp)
7827
 
-        self.mainapp = mainapp
7828
 
-        self.language = mainapp.language
7829
 
-        self.dialog_mode = ""
7830
 
-
7831
 
-        self.WaitWindow = QMessageBox(self.mainapp)
7832
 
-        self.WaitWindow.setStandardButtons(QMessageBox.NoButton)
7833
 
-
7834
 
-        if os.path.exists("system-config-printer.ui"):
7835
 
-            APPDIR = QDir.currentPath()
7836
 
-        else:
7837
 
-            file = KStandardDirs.locate("appdata", "system-config-printer.ui")
7838
 
-            APPDIR = file.left(file.lastIndexOf("/"))
7839
 
-
7840
 
-        uic.loadUi(APPDIR + "/" + "new-printer.ui", self)
7841
 
-
7842
 
-        self.connect(self.tvNPDevices, SIGNAL("itemSelectionChanged()"), self.on_tvNPDevices_cursor_changed)
7843
 
-        self.connect(self.tvNPMakes, SIGNAL("itemSelectionChanged()"), self.on_tvNPMakes_cursor_changed)
7844
 
-        self.connect(self.tvNPModels, SIGNAL("itemSelectionChanged()"), self.on_tvNPModels_cursor_changed)
7845
 
-        self.connect(self.entNPTDevice, SIGNAL("textEdited(const QString&)"), self.on_entNPTDevice_changed)
7846
 
-#        self.connect(self.entNPTIPPHostname, SIGNAL("textEdited(const QString&)"), self.on_entNPTIPPHostname_changed)
7847
 
-#        self.connect(self.entNPTIPPQueuename, SIGNAL("textEdited(const QString&)"), self.on_entNPTIPPQueuename_changed)
7848
 
-        self.connect(self.entSMBURI, SIGNAL("textEdited(const QString&)"), self.on_entSMBURI_changed)
7849
 
-        self.rbtnSMBAuthPrompt.setChecked(True)
7850
 
-        self.on_rbtnSMBAuthSet_toggled(False)
7851
 
-        self.connect(self.rbtnSMBAuthSet, SIGNAL("toggled(bool)"), self.on_rbtnSMBAuthSet_toggled)
7852
 
-        self.rbtnNPFoomatic.setChecked(True)
7853
 
-        self.connect(self.rbtnNPFoomatic, SIGNAL("toggled(bool)"), self.on_rbtnNPFoomatic_toggled)
7854
 
-       self.connect(self.filechooserPPDButton, SIGNAL("clicked()"),self.on_filechooserPPDButton)
7855
 
-        self.options = {} # keyword -> Option object
7856
 
-        self.changed = set()
7857
 
-        self.conflicts = set()
7858
 
-        self.ppd = None
7859
 
-
7860
 
-        # Synchronisation objects.
7861
 
-        self.ppds_lock = thread.allocate_lock()
7862
 
-        self.devices_lock = thread.allocate_lock()
7863
 
-        self.smb_lock = thread.allocate_lock()
7864
 
-        self.ipp_lock = thread.allocate_lock()
7865
 
-        self.drivers_lock = thread.allocate_lock()
7866
 
-
7867
 
-        #self.connect(self.btnNCAddMember, SIGNAL("clicked()"), self.slot_btnNCAddMember_clicked)
7868
 
-        #self.connect(self.btnNCDelMember, SIGNAL("clicked()"), self.slot_btnNCDelMember_clicked)
7869
 
-
7870
 
-        """
7871
 
-        # share with mainapp
7872
 
-        self.WaitWindow = mainapp.WaitWindow
7873
 
-        self.lblWait = mainapp.lblWait
7874
 
-        self.busy = mainapp.busy
7875
 
-        self.ready = mainapp.ready
7876
 
-        self.show_IPP_Error = mainapp.show_IPP_Error
7877
 
-        self.show_HTTP_Error = mainapp.show_HTTP_Error
7878
 
-        """
7879
 
-
7880
 
-        # Optionally disable downloadable driver support.
7881
 
-        if not config.DOWNLOADABLE_DRIVER_SUPPORT:
7882
 
-            self.rbtnNPDownloadableDriverSearch.setEnabled(False)
7883
 
-            self.downloadableDriverSearchFrame.hide()
7884
 
-
7885
 
-        """
7886
 
-        # Set up OpenPrinting widgets.
7887
 
-        self.openprinting = openprinting.OpenPrinting ()
7888
 
-        self.openprinting_query_handle = None
7889
 
-        combobox = self.cmbNPDownloadableDriverFoundPrinters
7890
 
-        cell = gtk.CellRendererText()
7891
 
-        combobox.pack_start (cell, True)
7892
 
-        combobox.add_attribute(cell, 'text', 0)
7893
 
-
7894
 
-        # SMB browser
7895
 
-        self.smb_store = gtk.TreeStore (str, # host or share
7896
 
-                                        str, # comment
7897
 
-                                        gobject.TYPE_PYOBJECT, # domain dict
7898
 
-                                        gobject.TYPE_PYOBJECT) # host dict
7899
 
-        self.tvSMBBrowser.set_model (self.smb_store)
7900
 
-        self.smb_store.set_sort_column_id (0, gtk.SORT_ASCENDING)
7901
 
-
7902
 
-        # SMB list columns
7903
 
-        col = gtk.TreeViewColumn (_("Share"), gtk.CellRendererText (),
7904
 
-                                  text=0)
7905
 
-        col.set_resizable (True)
7906
 
-        col.set_sort_column_id (0)
7907
 
-        self.tvSMBBrowser.append_column (col)
7908
 
-
7909
 
-        col = gtk.TreeViewColumn (_("Comment"), gtk.CellRendererText (),
7910
 
-                                  text=1)
7911
 
-        self.tvSMBBrowser.append_column (col)
7912
 
-        slct = self.tvSMBBrowser.get_selection ()
7913
 
-        slct.set_select_function (self.smb_select_function)
7914
 
-
7915
 
-        self.SMBBrowseDialog.set_transient_for(self.NewPrinterWindow)
7916
 
-
7917
 
-        # IPP browser
7918
 
-        self.ipp_store = gtk.TreeStore (str, # queue
7919
 
-                                        str, # location
7920
 
-                                        gobject.TYPE_PYOBJECT) # dict
7921
 
-        self.tvIPPBrowser.set_model (self.ipp_store)
7922
 
-        self.ipp_store.set_sort_column_id (0, gtk.SORT_ASCENDING)
7923
 
-
7924
 
-        # IPP list columns
7925
 
-        col = gtk.TreeViewColumn (_("Queue"), gtk.CellRendererText (),
7926
 
-                                  text=0)
7927
 
-        col.set_resizable (True)
7928
 
-        col.set_sort_column_id (0)
7929
 
-        self.tvIPPBrowser.append_column (col)
7930
 
-
7931
 
-        col = gtk.TreeViewColumn (_("Location"), gtk.CellRendererText (),
7932
 
-                                  text=1)
7933
 
-        self.tvIPPBrowser.append_column (col)
7934
 
-        self.IPPBrowseDialog.set_transient_for(self.NewPrinterWindow)
7935
 
-
7936
 
-        self.tvNPDriversTooltips = TreeViewTooltips(self.tvNPDrivers, self.NPDriversTooltips)
7937
 
-
7938
 
-        ppd_filter = gtk.FileFilter()
7939
 
-        ppd_filter.set_name(_("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"))
7940
 
-        ppd_filter.add_pattern("*.ppd")
7941
 
-        ppd_filter.add_pattern("*.PPD")
7942
 
-        ppd_filter.add_pattern("*.ppd.gz")
7943
 
-        ppd_filter.add_pattern("*.PPD.gz")
7944
 
-        ppd_filter.add_pattern("*.PPD.GZ")
7945
 
-        self.filechooserPPD.add_filter(ppd_filter)
7946
 
-
7947
 
-        ppd_filter = gtk.FileFilter()
7948
 
-        ppd_filter.set_name(_("All files (*)"))
7949
 
-        ppd_filter.add_pattern("*")
7950
 
-        self.filechooserPPD.add_filter(ppd_filter)
7951
 
-
7952
 
-        self.xml.signal_autoconnect(self)
7953
 
-        """
7954
 
-
7955
 
-        #FIXME hide bits which are not yet implemented
7956
 
-        self.btnSMBBrowse.hide()
7957
 
-        self.btnSMBVerify.hide()
7958
 
-        self.btnIPPFindQueue.hide()
7959
 
-        self.btnIPPVerify.hide()
7960
 
-        self.btnNPTLpdProbe.hide()
7961
 
-
7962
 
-    def option_changed(self, option):
7963
 
-        if option.is_changed():
7964
 
-            self.changed.add(option)
7965
 
-        else:
7966
 
-            self.changed.discard(option)
7967
 
-
7968
 
-        if option.conflicts:
7969
 
-            self.conflicts.add(option)
7970
 
-        else:
7971
 
-            self.conflicts.discard(option)
7972
 
-        self.setDataButtonState()
7973
 
-
7974
 
-        return
7975
 
-
7976
 
-    def setDataButtonState(self):
7977
 
-        self.btnNPForward.setEnabled(not bool(self.conflicts))
7978
 
-
7979
 
-    def init(self, dialog_mode):
7980
 
-        self.dialog_mode = dialog_mode
7981
 
-        self.options = {} # keyword -> Option object
7982
 
-        self.changed = set()
7983
 
-        self.conflicts = set()
7984
 
-
7985
 
-        """
7986
 
-        combobox = self.cmbNPDownloadableDriverFoundPrinters
7987
 
-        combobox.set_model (gtk.ListStore (str, str))
7988
 
-        self.entNPDownloadableDriverSearch.set_text ('')
7989
 
-        button = self.btnNPDownloadableDriverSearch
7990
 
-        label = button.get_children ()[0].get_children ()[0].get_children ()[1]
7991
 
-        self.btnNPDownloadableDriverSearch_label = label
7992
 
-        label.set_text (_("Search"))
7993
 
-        """
7994
 
-
7995
 
-        if self.dialog_mode == "printer":
7996
 
-            self.setWindowTitle(i18n("New Printer"))
7997
 
-            # Start on devices page (1, not 0)
7998
 
-            self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages["device"])
7999
 
-            self.fillDeviceTab()
8000
 
-            self.on_rbtnNPFoomatic_toggled()
8001
 
-            # Start fetching information from CUPS in the background
8002
 
-            self.new_printer_PPDs_loaded = False
8003
 
-            self.queryPPDs ()
8004
 
-
8005
 
-        elif self.dialog_mode == "class":
8006
 
-            self.setWindowTitle(i18n("New Class"))
8007
 
-            self.fillNewClassMembers()
8008
 
-            # Start on name page
8009
 
-            self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages["name"])
8010
 
-        elif self.dialog_mode == "device":
8011
 
-            self.setWindowTitle(i18n("Change Device URI"))
8012
 
-            self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages["device"])
8013
 
-            self.queryDevices ()
8014
 
-            self.loadPPDs()
8015
 
-            self.fillDeviceTab(self.mainapp.printer.device_uri)
8016
 
-            # Start fetching information from CUPS in the background
8017
 
-            self.new_printer_PPDs_loaded = False
8018
 
-            self.queryPPDs ()
8019
 
-        elif self.dialog_mode == "ppd":
8020
 
-            self.setWindowTitle(i18n("Change Driver"))
8021
 
-            self.ntbkNewPrinter.setCurrentIndex(2)
8022
 
-            self.on_rbtnNPFoomatic_toggled()
8023
 
-
8024
 
-            self.auto_model = ""
8025
 
-            ppd = self.mainapp.ppd
8026
 
-            if ppd:
8027
 
-                attr = ppd.findAttr("Manufacturer")
8028
 
-                if attr:
8029
 
-                    self.auto_make = attr.value
8030
 
-                else:
8031
 
-                    self.auto_make = ""
8032
 
-                attr = ppd.findAttr("ModelName")
8033
 
-                if not attr: attr = ppd.findAttr("ShortNickName")
8034
 
-                if not attr: attr = ppd.findAttr("NickName")
8035
 
-                if attr:
8036
 
-                    if attr.value.startswith(self.auto_make):
8037
 
-                        self.auto_model = attr.value[len(self.auto_make):].strip ()
8038
 
-                    else:
8039
 
-                        try:
8040
 
-                            self.auto_model = attr.value.split(" ", 1)[1]
8041
 
-                        except IndexError:
8042
 
-                            self.auto_model = ""
8043
 
-                else:
8044
 
-                    self.auto_model = ""
8045
 
-            else:
8046
 
-                # Special CUPS names for a raw queue.
8047
 
-                self.auto_make = 'Raw'
8048
 
-                self.auto_model = 'Queue'
8049
 
-
8050
 
-            self.loadPPDs ()
8051
 
-            self.fillMakeList()
8052
 
-
8053
 
-        if self.dialog_mode in ("printer", "class"):
8054
 
-            self.entNPName.setText (self.mainapp.makeNameUnique(self.dialog_mode))
8055
 
-            #FIXMEself.entNPName.grab_focus()
8056
 
-            for widget in [self.entNPLocation,
8057
 
-                           self.entNPDescription]: #,
8058
 
-                           #self.entSMBURI, self.entSMBUsername,
8059
 
-                           #self.entSMBPassword, self.entNPTDirectJetHostname]:
8060
 
-                widget.setText('')
8061
 
-
8062
 
-            try:
8063
 
-                p = os.popen ('/bin/hostname', 'r')
8064
 
-                hostname = p.read ().strip ()
8065
 
-                p.close ()
8066
 
-                self.entNPLocation.setText(hostname)
8067
 
-            except:
8068
 
-                nonfatalException ()
8069
 
-
8070
 
-        self.entNPTDirectJetPort.setText('9100')
8071
 
-        self.setNPButtons()
8072
 
-        self.exec_()
8073
 
-
8074
 
-    # get PPDs
8075
 
-
8076
 
-    def queryPPDs(self):
8077
 
-        debugprint ("queryPPDs")
8078
 
-        if not self.ppds_lock.acquire(0):
8079
 
-            debugprint ("queryPPDs: in progress")
8080
 
-            return
8081
 
-        debugprint ("Lock acquired for PPDs thread")
8082
 
-        # Start new thread
8083
 
-        thread.start_new_thread (self.getPPDs_thread, (self.language[0],))
8084
 
-        debugprint ("PPDs thread started")
8085
 
-
8086
 
-    def getPPDs_thread(self, language):
8087
 
-        try:
8088
 
-            debugprint ("Connecting (PPDs)")
8089
 
-            cups.setServer (self.mainapp.connect_server)
8090
 
-            cups.setUser (self.mainapp.connect_user)
8091
 
-            cups.setPasswordCB (self.mainapp.cupsPasswdCallback)
8092
 
-            # cups.setEncryption (...)
8093
 
-            c = cups.Connection ()
8094
 
-            debugprint ("Fetching PPDs")
8095
 
-            ppds_dict = c.getPPDs()
8096
 
-            self.ppds_result = cupshelpers.ppds.PPDs(ppds_dict,
8097
 
-                                                     language=language)
8098
 
-            debugprint ("Closing connection (PPDs)")
8099
 
-            del c
8100
 
-        except cups.IPPError, (e, msg):
8101
 
-            self.ppds_result = cups.IPPError (e, msg)
8102
 
-        except:
8103
 
-            nonfatalException()
8104
 
-            self.ppds_result = { }
8105
 
-
8106
 
-        debugprint ("Releasing PPDs lock")
8107
 
-        self.ppds_lock.release ()
8108
 
-
8109
 
-    def fetchPPDs(self, parent=None):
8110
 
-        debugprint ("fetchPPDs")
8111
 
-        self.queryPPDs()
8112
 
-        time.sleep (0.1)
8113
 
-
8114
 
-        # Keep the UI refreshed while we wait for the devices to load.
8115
 
-        waiting = False
8116
 
-        while (self.ppds_lock.locked()):
8117
 
-            if not waiting:
8118
 
-                waiting = True
8119
 
-                self.WaitWindow.setText(i18n('<b>Searching</b>') + '<br /><br />' +
8120
 
-                                         i18n('Searching for drivers'))
8121
 
-                self.WaitWindow.show ()
8122
 
-
8123
 
-            QApplication.processEvents()
8124
 
-
8125
 
-            time.sleep (0.1)
8126
 
-
8127
 
-        if waiting:
8128
 
-            self.WaitWindow.hide ()
8129
 
-
8130
 
-        debugprint ("Got PPDs")
8131
 
-        result = self.ppds_result # atomic operation
8132
 
-        if isinstance (result, cups.IPPError):
8133
 
-            # Propagate exception.
8134
 
-            raise result
8135
 
-        return result
8136
 
-
8137
 
-    def loadPPDs(self, parent=None):
8138
 
-        try:
8139
 
-            return self.ppds
8140
 
-        except:
8141
 
-            self.ppds = self.fetchPPDs (parent=parent)
8142
 
-            return self.ppds
8143
 
-
8144
 
-    def dropPPDs(self):
8145
 
-        try:
8146
 
-            del self.ppds
8147
 
-        except:
8148
 
-            pass
8149
 
-
8150
 
-    # Class members
8151
 
-
8152
 
-    def fillNewClassMembers(self):
8153
 
-        self.tvNCMembers.clear()
8154
 
-        self.tvNCNotMembers.clear()
8155
 
-        for printer in self.mainapp.printers.itervalues():
8156
 
-            self.tvNCNotMembers.addItem(printer.name)
8157
 
-
8158
 
-    @pyqtSignature("")
8159
 
-    def on_btnNCAddMember_clicked(self):
8160
 
-        self.mainapp.moveClassMembers(self.tvNCNotMembers, self.tvNCMembers)
8161
 
-        self.btnNPApply.setEnabled(
8162
 
-            bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
8163
 
-
8164
 
-    @pyqtSignature("")
8165
 
-    def on_btnNCDelMember_clicked(self):
8166
 
-        self.mainapp.moveClassMembers(self.tvNCMembers, self.tvNCNotMembers)
8167
 
-        self.btnNPApply.setEnabled(
8168
 
-            bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
8169
 
-
8170
 
-    @pyqtSignature("")
8171
 
-    def on_btnNPBack_clicked(self):
8172
 
-        self.nextNPTab(-1)
8173
 
-
8174
 
-    @pyqtSignature("")
8175
 
-    def on_btnNPForward_clicked(self):
8176
 
-        self.nextNPTab()
8177
 
-
8178
 
-    def nextNPTab(self, step=1):
8179
 
-        page_nr = self.ntbkNewPrinter.currentIndex()
8180
 
-
8181
 
-        if self.dialog_mode == "class":
8182
 
-            #order = [0, 4, 5]
8183
 
-            order = [self.ntbkNewPrinterPages["name"], self.ntbkNewPrinterPages["class-members"]]
8184
 
-        elif self.dialog_mode == "printer":
8185
 
-            #self.busy(self)
8186
 
-            if page_nr == 1: # Device (first page)
8187
 
-                # Choose an appropriate name.
8188
 
-                name = 'printer'
8189
 
-                try:
8190
 
-                    if self.device.id:
8191
 
-                        name = self.device.id_dict["MDL"]
8192
 
-                    name = self.mainapp.makeNameUnique (name)
8193
 
-                    self.entNPName.setText(name)
8194
 
-                except:
8195
 
-                    nonfatalException ()
8196
 
-                self.auto_make, self.auto_model = None, None
8197
 
-                self.device.uri = self.getDeviceURI()
8198
 
-                if self.device.type in ("socket", "lpd", "ipp", "bluetooth"):
8199
 
-                    host = self.getNetworkPrinterMakeModel(self.device)
8200
 
-                    faxuri = None
8201
 
-                    if host:
8202
 
-                        faxuri = self.get_hplip_uri_for_network_printer(host,
8203
 
-                                                                        "fax")
8204
 
-                    if faxuri:
8205
 
-                        ##FIXME
8206
 
-                        dialog = gtk.Dialog(self.device.info,
8207
 
-                                            self.NewPrinterWindow,
8208
 
-                                            gtk.DIALOG_MODAL |
8209
 
-                                            gtk.DIALOG_DESTROY_WITH_PARENT,
8210
 
-                                            (i18n("Printer"), 1,
8211
 
-                                             i18n("Fax"), 2))
8212
 
-                        label = gtk.Label(i18n("This printer supports both "
8213
 
-                                            "printing and sending faxes.  "
8214
 
-                                            "Which functionality should be "
8215
 
-                                            "used for this queue?"))
8216
 
-                        dialog.vbox.pack_start(label, True, True, 0)
8217
 
-                        label.show()
8218
 
-                        queue_type = dialog.run()
8219
 
-                        dialog.destroy()
8220
 
-                        if (queue_type == 2):
8221
 
-                            self.device.id_dict = \
8222
 
-                               self.get_hpfax_device_id(faxuri)
8223
 
-                            self.device.uri = faxuri
8224
 
-                            self.auto_make = self.device.id_dict["MFG"]
8225
 
-                            self.auto_model = self.device.id_dict["MDL"]
8226
 
-                            self.device.id = "MFG:" + self.auto_make + \
8227
 
-                                             ";MDL:" + self.auto_model + \
8228
 
-                                             ";DES:" + \
8229
 
-                                             self.device.id_dict["DES"] + ";"
8230
 
-                uri = self.device.uri
8231
 
-                if uri and uri.startswith ("smb://"):
8232
 
-                    uri = SMBURI (uri=uri[6:]).sanitize_uri ()
8233
 
-
8234
 
-                # Try to access the PPD, in this case our detected IPP
8235
 
-                # printer is a queue on a remote CUPS server which is
8236
 
-                # not automatically set up on our local CUPS server
8237
 
-                # (for example DNS-SD broadcasted queue from Mac OS X)
8238
 
-                self.remotecupsqueue = None
8239
 
-                res = re.search ("ipp://(\S+(:\d+|))/printers/(\S+)", uri)
8240
 
-                if res:
8241
 
-                    resg = res.groups()
8242
 
-                    try:
8243
 
-                        conn = httplib.HTTPConnection(resg[0])
8244
 
-                        conn.request("GET", "/printers/%s.ppd" % resg[2])
8245
 
-                        resp = conn.getresponse()
8246
 
-                        if resp.status == 200: self.remotecupsqueue = resg[2]
8247
 
-                    except:
8248
 
-                        debugprint("exception in getting remotecupsqueue")
8249
 
-                        pass
8250
 
-
8251
 
-                    # We also want to fetch the printer-info and
8252
 
-                    # printer-location attributes, to pre-fill those
8253
 
-                    # fields for this new queue.
8254
 
-                    oldserver = cups.getServer()
8255
 
-                    oldport = cups.getPort()
8256
 
-                    try:
8257
 
-                        cups.setServer (resg[0])
8258
 
-                        if len (resg[1]) > 0:
8259
 
-                            cups.setPort (int (resg[1]))
8260
 
-                        else:
8261
 
-                            cups.setPort (631)
8262
 
-
8263
 
-                        c = cups.Connection ()
8264
 
-                        r = ['printer-info', 'printer-location']
8265
 
-                        attrs = c.getPrinterAttributes (uri=uri,
8266
 
-                                                        requested_attributes=r)
8267
 
-                        info = attrs.get ('printer-info', '')
8268
 
-                        location = attrs.get ('printer-location', '')
8269
 
-                        if len (info) > 0:
8270
 
-                            self.entNPDescription.setText(info)
8271
 
-                        if len (location) > 0:
8272
 
-                            self.entNPLocation.setText(location)
8273
 
-                    except:
8274
 
-                        nonfatalException ()
8275
 
-
8276
 
-                    cups.setServer (oldserver)
8277
 
-                    cups.setPort (oldport)
8278
 
-
8279
 
-                if (not self.remotecupsqueue and
8280
 
-                    not self.new_printer_PPDs_loaded):
8281
 
-                    try:
8282
 
-                        self.loadPPDs(self)
8283
 
-                    except cups.IPPError, (e, msg):
8284
 
-                        #self.ready (self)
8285
 
-                        self.show_IPP_Error(e, msg)
8286
 
-                        return
8287
 
-                    except:
8288
 
-                        self.ready (self)
8289
 
-                        return
8290
 
-                    self.new_printer_PPDs_loaded = True
8291
 
-
8292
 
-                ppdname = None
8293
 
-                try:
8294
 
-                    if self.remotecupsqueue:
8295
 
-                        # We have a remote CUPS queue, let the client queue
8296
 
-                        # stay raw so that the driver on the server gets used
8297
 
-                        ppdname = 'raw'
8298
 
-                        self.ppd = ppdname
8299
 
-                        name = self.remotecupsqueue
8300
 
-                        name = self.mainapp.makeNameUnique (name)
8301
 
-                        self.entNPName.setText(name)
8302
 
-                    elif self.device.id:
8303
 
-                        id_dict = self.device.id_dict
8304
 
-                        (status, ppdname) = self.ppds.\
8305
 
-                            getPPDNameFromDeviceID (id_dict["MFG"],
8306
 
-                                                    id_dict["MDL"],
8307
 
-                                                    id_dict["DES"],
8308
 
-                                                    id_dict["CMD"],
8309
 
-                                                    self.device.uri)
8310
 
-                    else:
8311
 
-                        (status, ppdname) = self.ppds.\
8312
 
-                            getPPDNameFromDeviceID ("Generic",
8313
 
-                                                    "Printer",
8314
 
-                                                    "Generic Printer",
8315
 
-                                                    [],
8316
 
-                                                    self.device.uri)
8317
 
-
8318
 
-                    if ppdname and not self.remotecupsqueue:
8319
 
-                        ppddict = self.ppds.getInfoFromPPDName (ppdname)
8320
 
-                        make_model = ppddict['ppd-make-and-model']
8321
 
-                        (make, model) = \
8322
 
-                            cupshelpers.ppds.ppdMakeModelSplit (make_model)
8323
 
-                        self.auto_make = make
8324
 
-                        self.auto_model = model
8325
 
-                except:
8326
 
-                    nonfatalException ()
8327
 
-                if not self.remotecupsqueue:
8328
 
-                    self.fillMakeList()
8329
 
-            elif page_nr == 3: # Model has been selected
8330
 
-                if not self.device.id:
8331
 
-                    # Choose an appropriate name when no Device ID
8332
 
-                    # is available, based on the model the user has
8333
 
-                    # selected.
8334
 
-                    try:
8335
 
-                        items = self.tvNPModels.selectedItems()
8336
 
-                        name = unicode(items[0].text())
8337
 
-                        name = self.mainapp.makeNameUnique (name)
8338
 
-                        self.entNPName.setText(name)
8339
 
-                    except:
8340
 
-                        nonfatalException ()
8341
 
-
8342
 
-            ##self.ready (self.NewPrinterWindow)
8343
 
-            if self.remotecupsqueue:
8344
 
-                order = [1, 0]
8345
 
-            elif self.rbtnNPFoomatic.isChecked():
8346
 
-                order = [1, 2, 3, 6, 0]
8347
 
-            elif self.rbtnNPPPD.isChecked():
8348
 
-                order = [1, 2, 6, 0]
8349
 
-            else:
8350
 
-                # Downloadable driver
8351
 
-                order = [1, 2, 7, 6, 0]
8352
 
-        elif self.dialog_mode == "device":
8353
 
-            order = [1]
8354
 
-        elif self.dialog_mode == "ppd":
8355
 
-            self.rbtnChangePPDasIs.setChecked(True)
8356
 
-            if self.rbtnNPFoomatic.isChecked():
8357
 
-                order = [2, 3, 5, 6]
8358
 
-            elif self.rbtnNPPPD.isChecked():
8359
 
-                order = [2, 5, 6]
8360
 
-            else:
8361
 
-                # Downloadable driver
8362
 
-                order = [2, 7, 5, 6]
8363
 
-
8364
 
-        next_page_nr = order[order.index(page_nr)+step]
8365
 
-
8366
 
-        # fill Installable Options tab
8367
 
-        if next_page_nr == 6 and step > 0:
8368
 
-            #TODO Prepare Installable Options screen.
8369
 
-            self.ppd = self.getNPPPD()
8370
 
-            """FIXME todo
8371
 
-            if next_page_nr == 6:
8372
 
-                # Prepare Installable Options screen.
8373
 
-                if isinstance(self.ppd, cups.PPD):
8374
 
-                    self.fillNPInstallableOptions()
8375
 
-                else:
8376
 
-                    self.installable_options = None
8377
 
-                    # Put a label there explaining why the page is empty.
8378
 
-                    ppd = self.ppd
8379
 
-                    self.ppd = None
8380
 
-                    self.fillNPInstallableOptions()
8381
 
-                    self.ppd = ppd
8382
 
-
8383
 
-                # step over if empty and not in PPD mode
8384
 
-                if self.dialog_mode != "ppd" and not self.installable_options:
8385
 
-                    next_page_nr = order[order.index(next_page_nr)+1]
8386
 
-            """
8387
 
-            next_page_nr = order[order.index(next_page_nr)+1]
8388
 
-        self.installable_options = False
8389
 
-        # Step over empty Installable Options tab
8390
 
-        if next_page_nr == 6 and not self.installable_options and step<0:
8391
 
-            next_page_nr = order[order.index(next_page_nr)-1]
8392
 
-
8393
 
-        if next_page_nr == 7: # About to show downloadable drivers
8394
 
-            if self.drivers_lock.locked ():
8395
 
-                # Still searching for drivers.
8396
 
-                self.lblWait.set_markup ('<span size="larger">' +
8397
 
-                                         i18n('<b>Searching</b>') + '</span>\n\n' +
8398
 
-                                         i18n('Searching for drivers'))
8399
 
-                self.WaitWindow.set_transient_for (self.NewPrinterWindow)
8400
 
-                self.WaitWindow.show ()
8401
 
-                self.busy(self)
8402
 
-
8403
 
-                # Keep the UI refreshed while we wait for the drivers
8404
 
-                # query to complete.
8405
 
-                while self.drivers_lock.locked ():
8406
 
-                    while gtk.events_pending ():
8407
 
-                        gtk.main_iteration ()
8408
 
-                    time.sleep (0.1)
8409
 
-
8410
 
-                self.ready (self.NewPrinterWindow)
8411
 
-                self.WaitWindow.hide ()
8412
 
-
8413
 
-            self.fillDownloadableDrivers()
8414
 
-
8415
 
-        self.ntbkNewPrinter.setCurrentIndex(next_page_nr)
8416
 
-
8417
 
-        self.setNPButtons()
8418
 
-
8419
 
-    def setNPButtons(self):
8420
 
-        nr = self.ntbkNewPrinter.currentIndex()
8421
 
-
8422
 
-        if self.dialog_mode == "device":
8423
 
-            self.btnNPBack.hide()
8424
 
-            self.btnNPForward.hide()
8425
 
-            self.btnNPApply.show()
8426
 
-            uri = self.getDeviceURI ()
8427
 
-            self.btnNPApply.setEnabled(validDeviceURI (uri))
8428
 
-            return
8429
 
-
8430
 
-        if self.dialog_mode == "ppd":
8431
 
-            if nr == 5: # Apply
8432
 
-                if not self.installable_options:
8433
 
-                    # There are no installable options, so this is the
8434
 
-                    # last page.
8435
 
-                    debugprint ("No installable options")
8436
 
-                    self.btnNPForward.hide ()
8437
 
-                    self.btnNPApply.show ()
8438
 
-                else:
8439
 
-                    self.btnNPForward.show ()
8440
 
-                    self.btnNPApply.hide ()
8441
 
-                return
8442
 
-            elif nr == 6:
8443
 
-                self.btnNPForward.hide()
8444
 
-                self.btnNPApply.show()
8445
 
-                return
8446
 
-            else:
8447
 
-                self.btnNPForward.show()
8448
 
-                self.btnNPApply.hide()
8449
 
-            if nr == 2:
8450
 
-                self.btnNPBack.hide()
8451
 
-                self.btnNPForward.show()
8452
 
-                downloadable_selected = False
8453
 
-                if self.rbtnNPDownloadableDriverSearch.isChecked():
8454
 
-                    combobox = self.cmbNPDownloadableDriverFoundPrinters
8455
 
-                    iter = combobox.get_active_iter () #FIXME
8456
 
-                    if iter and combobox.get_model ().get_value (iter, 1):
8457
 
-                        downloadable_selected = True
8458
 
-
8459
 
-                self.btnNPForward.setEnabled(bool(
8460
 
-                        self.rbtnNPFoomatic.isChecked() or
8461
 
-                        not self.filechooserPPD.text().isEmpty() or
8462
 
-                        downloadable_selected))
8463
 
-                return
8464
 
-            else:
8465
 
-                self.btnNPBack.show()
8466
 
-
8467
 
-        # class/printer
8468
 
-
8469
 
-        if nr == 1: # Device
8470
 
-            valid = False
8471
 
-            try:
8472
 
-                uri = self.getDeviceURI ()
8473
 
-                valid = validDeviceURI (uri)
8474
 
-            except:
8475
 
-                pass
8476
 
-            self.btnNPForward.setEnabled(valid)
8477
 
-            self.btnNPBack.hide ()
8478
 
-        else:
8479
 
-            self.btnNPBack.show()
8480
 
-
8481
 
-        self.btnNPForward.show()
8482
 
-        self.btnNPApply.hide()
8483
 
-
8484
 
-        if nr == 0: # Name
8485
 
-            self.btnNPBack.show()
8486
 
-            if self.dialog_mode == "class":
8487
 
-                self.btnNPForward.setEnabled(True)
8488
 
-            if self.dialog_mode == "printer":
8489
 
-                self.btnNPForward.hide()
8490
 
-                self.btnNPApply.show()
8491
 
-                self.btnNPApply.setEnabled(
8492
 
-                    self.mainapp.checkNPName(unicode(self.entNPName.text())))
8493
 
-        if nr == 2: # Make/PPD file
8494
 
-            downloadable_selected = False
8495
 
-            if self.rbtnNPDownloadableDriverSearch.isChecked():
8496
 
-                combobox = self.cmbNPDownloadableDriverFoundPrinters
8497
 
-                iter = combobox.get_active_iter () #FIXME
8498
 
-                if iter and combobox.get_model ().get_value (iter, 1):
8499
 
-                    downloadable_selected = True
8500
 
-
8501
 
-            self.btnNPForward.setEnabled(bool(
8502
 
-                self.rbtnNPFoomatic.isChecked() or
8503
 
-                not self.filechooserPPD.text().isEmpty() or
8504
 
-                downloadable_selected))
8505
 
-       
8506
 
-        if nr == 3: # Model/Driver
8507
 
-            iter = self.tvNPDrivers.currentItem()
8508
 
-            self.btnNPForward.setEnabled(bool(iter))
8509
 
-        if nr == 4: # Class Members
8510
 
-            self.btnNPForward.hide()
8511
 
-            self.btnNPApply.show()
8512
 
-            self.btnNPApply.setEnabled(self.tvNCMembers.count() > 0)
8513
 
-        if nr == 7: # Downloadable drivers
8514
 
-            if self.ntbkNPDownloadableDriverProperties.get_current_page() == 1: #FIXME
8515
 
-                accepted = self.rbtnNPDownloadLicenseYes.get_active ()
8516
 
-            else:
8517
 
-                treeview = self.tvNPDownloadableDrivers
8518
 
-                model, iter = treeview.get_selection ().get_selected ()
8519
 
-                accepted = (iter != None)
8520
 
-
8521
 
-            self.btnNPForward.set_sensitive(accepted)
8522
 
-    
8523
 
-    def on_filechooserPPDButton(self):
8524
 
-       home = QDir.homePath()
8525
 
-       fd = QFileDialog()
8526
 
-       fd.setFileMode(fd.ExistingFile)
8527
 
-       filename = fd.getOpenFileName(self, 'Open PPD file', home)
8528
 
-       self.filechooserPPD.setText(filename)
8529
 
-       self.btnNPForward.setEnabled(True)
8530
 
-
8531
 
-    def getDevices_thread(self):
8532
 
-        try:
8533
 
-            debugprint ("Connecting (devices)")
8534
 
-            cups.setServer (self.mainapp.connect_server)
8535
 
-            #cups.setUser (self.mainapp.connect_user)
8536
 
-            cups.setUser ("jr")
8537
 
-            cups.setPasswordCB (self.mainapp.cupsPasswdCallback)
8538
 
-            # cups.setEncryption (...)
8539
 
-            c = cups.Connection ()
8540
 
-            debugprint ("Fetching devices")
8541
 
-            self.devices_result = cupshelpers.getDevices(c)
8542
 
-        except cups.IPPError, (e, msg):
8543
 
-            self.devices_result = cups.IPPError (e, msg)
8544
 
-        except:
8545
 
-            debugprint ("Exception in getDevices_thread")
8546
 
-            self.devices_result = {}
8547
 
-
8548
 
-        try:
8549
 
-            debugprint ("Closing connection (devices)")
8550
 
-            del c
8551
 
-        except:
8552
 
-            pass
8553
 
-
8554
 
-        debugprint ("Releasing devices lock")
8555
 
-        self.devices_lock.release ()
8556
 
-
8557
 
-    # Device URI
8558
 
-    def queryDevices(self):
8559
 
-        if not self.devices_lock.acquire(0):
8560
 
-            debugprint ("queryDevices: in progress")
8561
 
-            return
8562
 
-        debugprint ("Lock acquired for devices thread")
8563
 
-        # Start new thread
8564
 
-        thread.start_new_thread (self.getDevices_thread, ())
8565
 
-        #self.getDevices_thread()
8566
 
-        debugprint ("Devices thread started")
8567
 
-
8568
 
-    def fetchDevices(self, parent=None):
8569
 
-        debugprint ("fetchDevices")
8570
 
-        self.queryDevices ()
8571
 
-        time.sleep (0.1)
8572
 
-
8573
 
-        # Keep the UI refreshed while we wait for the devices to load.
8574
 
-        waiting = False
8575
 
-        while (self.devices_lock.locked()):
8576
 
-            if not waiting:
8577
 
-                waiting = True
8578
 
-                self.WaitWindow.setText (i18n('<b>Searching</b>') + '<br/><br/>' +
8579
 
-                                         i18n('Searching for printers'))
8580
 
-                #if not parent:
8581
 
-                #    parent = self.mainapp.MainWindow
8582
 
-                #self.WaitWindow.set_transient_for (parent)
8583
 
-                #self.WaitWindow.show ()
8584
 
-                self.WaitWindow.show()
8585
 
-
8586
 
-            QApplication.processEvents()
8587
 
-
8588
 
-            time.sleep (0.1)
8589
 
-
8590
 
-        if waiting:
8591
 
-            #self.WaitWindow.hide ()
8592
 
-            self.WaitWindow.hide()
8593
 
-
8594
 
-        debugprint ("Got devices")
8595
 
-        result = self.devices_result # atomic operation
8596
 
-        if isinstance (result, cups.IPPError):
8597
 
-            # Propagate exception.
8598
 
-            raise result
8599
 
-        return result
8600
 
-
8601
 
-    def get_hpfax_device_id(self, faxuri):
8602
 
-        os.environ["URI"] = faxuri
8603
 
-        cmd = 'LC_ALL=C DISPLAY= hp-info -d "${URI}"'
8604
 
-        debugprint (faxuri + ": " + cmd)
8605
 
-        try:
8606
 
-            p = subprocess.Popen (cmd, shell=True,
8607
 
-                                  stdin=file("/dev/null"),
8608
 
-                                  stdout=subprocess.PIPE,
8609
 
-                                  stderr=subprocess.PIPE)
8610
 
-            (stdout, stderr) = p.communicate ()
8611
 
-        except:
8612
 
-            # Problem executing command.
8613
 
-            return None
8614
 
-
8615
 
-        for line in stdout.split ("\n"):
8616
 
-            if line.find ("fax-type") == -1:
8617
 
-                continue
8618
 
-            faxtype = -1
8619
 
-            res = re.search ("(\d+)", line)
8620
 
-            if res:
8621
 
-                resg = res.groups()
8622
 
-                faxtype = resg[0]
8623
 
-            if faxtype >= 0: break
8624
 
-        if faxtype < 0:
8625
 
-            return None
8626
 
-        elif faxtype == 4:
8627
 
-            return cupshelpers.parseDeviceID ('MFG:HP;MDL:Fax 2;DES:HP Fax 2;')
8628
 
-        else:
8629
 
-            return cupshelpers.parseDeviceID ('MFG:HP;MDL:Fax;DES:HP Fax;')
8630
 
-
8631
 
-    def get_hplip_uri_for_network_printer(self, host, mode):
8632
 
-        os.environ["HOST"] = host
8633
 
-        if mode == "print": mod = "-c"
8634
 
-        elif mode == "fax": mod = "-f"
8635
 
-        else: mod = "-c"
8636
 
-        cmd = 'hp-makeuri ' + mod + ' "${HOST}"'
8637
 
-        debugprint (host + ": " + cmd)
8638
 
-        uri = None
8639
 
-        try:
8640
 
-            p = subprocess.Popen (cmd, shell=True,
8641
 
-                                  stdin=file("/dev/null"),
8642
 
-                                  stdout=subprocess.PIPE,
8643
 
-                                  stderr=subprocess.PIPE)
8644
 
-            (stdout, stderr) = p.communicate ()
8645
 
-        except:
8646
 
-            # Problem executing command.
8647
 
-            return None
8648
 
-
8649
 
-        uri = stdout.strip ()
8650
 
-        return uri
8651
 
-
8652
 
-    def getNetworkPrinterMakeModel(self, device):
8653
 
-        # Determine host name/IP
8654
 
-        host = None
8655
 
-        s = device.uri.find ("://")
8656
 
-        if s != -1:
8657
 
-            s += 3
8658
 
-            e = device.uri[s:].find (":")
8659
 
-            if e == -1: e = device.uri[s:].find ("/")
8660
 
-            if e == -1: e = device.uri[s:].find ("?")
8661
 
-            if e == -1: e = len (device.uri)
8662
 
-            host = device.uri[s:s+e]
8663
 
-        # Try to get make and model via SNMP
8664
 
-        if host:
8665
 
-            os.environ["HOST"] = host
8666
 
-            cmd = '/usr/lib/cups/backend/snmp "${HOST}"'
8667
 
-            debugprint (host + ": " + cmd)
8668
 
-            stdout = None
8669
 
-            try:
8670
 
-                p = subprocess.Popen (cmd, shell=True,
8671
 
-                                      stdin=file("/dev/null"),
8672
 
-                                      stdout=subprocess.PIPE,
8673
 
-                                      stderr=subprocess.PIPE)
8674
 
-                (stdout, stderr) = p.communicate ()
8675
 
-            except:
8676
 
-                # Problem executing command.
8677
 
-                pass
8678
 
-
8679
 
-            if stdout != None:
8680
 
-                mm = re.sub("^\s*\S+\s+\S+\s+\"", "", stdout)
8681
 
-                mm = re.sub("\"\s+.*$", "", mm)
8682
 
-                if mm and mm != "": device.make_and_model = mm
8683
 
-        # Extract make and model and create a pseudo device ID, so
8684
 
-        # that a PPD/driver can be assigned to the device
8685
 
-        make_and_model = None
8686
 
-        if len (device.make_and_model) > 7:
8687
 
-            make_and_model = device.make_and_model
8688
 
-        elif len (device.info) > 7:
8689
 
-            make_and_model = device.info
8690
 
-            make_and_model = re.sub("\s*(\(|\d+\.\d+\.\d+\.\d+).*$", "", make_and_model)
8691
 
-        if make_and_model and not device.id:
8692
 
-            mk = None
8693
 
-            md = None
8694
 
-            (mk, md) = cupshelpers.ppds.ppdMakeModelSplit (make_and_model)
8695
 
-            device.id = "MFG:" + mk + ";MDL:" + md + ";DES:" + mk + " " + md + ";"
8696
 
-            device.id_dict = cupshelpers.parseDeviceID (device.id)
8697
 
-        # Check whether the device is supported by HPLIP and replace
8698
 
-        # its URI by an HPLIP URI
8699
 
-        if host:
8700
 
-            hplipuri = self.get_hplip_uri_for_network_printer(host, "print")
8701
 
-            if hplipuri:
8702
 
-                device.uri = hplipuri
8703
 
-                s = hplipuri.find ("/usb/")
8704
 
-                if s == -1: s = hplipuri.find ("/par/")
8705
 
-                if s == -1: s = hplipuri.find ("/net/")
8706
 
-                if s != -1:
8707
 
-                    s += 5
8708
 
-                    e = hplipuri[s:].find ("?")
8709
 
-                    if e == -1: e = len (hplipuri)
8710
 
-                    mdl = hplipuri[s:s+e].replace ("_", " ")
8711
 
-                    if mdl.startswith ("hp ") or mdl.startswith ("HP "):
8712
 
-                        mdl = mdl[3:]
8713
 
-                        device.make_and_model = "HP " + mdl
8714
 
-                        device.id = "MFG:HP;MDL:" + mdl + ";DES:HP " + mdl + ";"
8715
 
-                        device.id_dict = cupshelpers.parseDeviceID (device.id)
8716
 
-        # Return the host name/IP for further actions
8717
 
-        return host
8718
 
-
8719
 
-    def fillDeviceTab(self, current_uri=None, query=True):
8720
 
-        if query:
8721
 
-            try:
8722
 
-                devices = self.fetchDevices()
8723
 
-            except cups.IPPError, (e, msg):
8724
 
-                self.show_IPP_Error(e, msg)
8725
 
-                devices = {}
8726
 
-            except:
8727
 
-                nonfatalException()
8728
 
-                devices = {}
8729
 
-
8730
 
-            if current_uri:
8731
 
-                if devices.has_key (current_uri):
8732
 
-                    current = devices.pop(current_uri)
8733
 
-                else:
8734
 
-                    current = cupshelpers.Device (current_uri)
8735
 
-                    current.info = "Current device"
8736
 
-
8737
 
-            self.devices = devices.values()
8738
 
-
8739
 
-        for device in self.devices:
8740
 
-            if device.type == "usb":
8741
 
-                # Find USB URIs with corresponding HPLIP URIs and mark them
8742
 
-                # for deleting, so that the user will only get the HPLIP
8743
 
-                # URIs for full device support in the list
8744
 
-                ser = None
8745
 
-                s = device.uri.find ("?serial=")
8746
 
-                if s != -1:
8747
 
-                    s += 8
8748
 
-                    e = device.uri[s:].find ("?")
8749
 
-                    if e == -1: e = len (device.uri)
8750
 
-                    ser = device.uri[s:s+e]
8751
 
-                mod = None
8752
 
-                s = device.uri[6:].find ("/")
8753
 
-                if s != -1:
8754
 
-                    s += 7
8755
 
-                    e = device.uri[s:].find ("?")
8756
 
-                    if e == -1: e = len (device.uri)
8757
 
-                    mod = device.uri[s:s+e].lower ().replace ("%20", "_")
8758
 
-                    if mod.startswith ("hp_"):
8759
 
-                        mod = mod[3:]
8760
 
-                matchfound = 0
8761
 
-                for hpdevice in self.devices:
8762
 
-                    hpser = None
8763
 
-                    hpmod = None
8764
 
-                    uri = hpdevice.uri
8765
 
-                    if not uri.startswith ("hp:"): continue
8766
 
-                    if ser:
8767
 
-                        s = uri.find ("?serial=")
8768
 
-                        if s != -1:
8769
 
-                            s += 8
8770
 
-                            e = uri[s:].find ("?")
8771
 
-                            if e == -1: e = len (uri)
8772
 
-                            hpser = uri[s:s+e]
8773
 
-                            if hpser != ser: continue
8774
 
-                            matchfound = 1
8775
 
-                    if mod and not (ser and hpser):
8776
 
-                        s = uri.find ("/usb/")
8777
 
-                        if s != -1:
8778
 
-                            s += 5
8779
 
-                            e = uri[s:].find ("?")
8780
 
-                            if e == -1: e = len (uri)
8781
 
-                            hpmod = uri[s:s+e].lower ()
8782
 
-                            if hpmod.startswith ("hp_"):
8783
 
-                                hpmod = hpmod[3:]
8784
 
-                            if hpmod != mod: continue
8785
 
-                            matchfound = 1
8786
 
-                    if matchfound == 1: break
8787
 
-                if matchfound == 1:
8788
 
-                    device.uri = "delete"
8789
 
-            if device.type == "hal":
8790
 
-                # Remove HAL USB URIs, for these printers there are already
8791
 
-                # USB URIs
8792
 
-                if device.uri.startswith("hal:///org/freedesktop/Hal/devices/usb_device"):
8793
 
-                    device.uri = "delete"
8794
 
-            if device.type == "socket":
8795
 
-                # Remove default port to more easily find duplicate URIs
8796
 
-                device.uri = device.uri.replace (":9100", "")
8797
 
-            try:
8798
 
-                ## XXX This needs to be moved to *after* the device is
8799
 
-                # selected.  Looping through all the network printers like
8800
 
-                # this is far too slow.
8801
 
-                if False and device.type in ("socket", "lpd", "ipp", "bluetooth"):
8802
 
-                    host = self.getNetworkPrinterMakeModel(device)
8803
 
-                    faxuri = None
8804
 
-                    if host:
8805
 
-                        faxuri = self.get_hplip_uri_for_network_printer(host,
8806
 
-                                                                        "fax")
8807
 
-                    if faxuri:
8808
 
-                        self.devices.append(cupshelpers.Device(faxuri,
8809
 
-                              **{'device-class' : "direct",
8810
 
-                                 'device-info' : device.info + " HP Fax HPLIP",
8811
 
-                                 'device-device-make-and-model' : "HP Fax",
8812
 
-                                 'device-id' : "MFG:HP;MDL:Fax;DES:HP Fax;"}))
8813
 
-                    if device.uri.startswith ("hp:"):
8814
 
-                        device.type = "hp" 
8815
 
-                        device.info += (" HPLIP")
8816
 
-            except:
8817
 
-                nonfatalException ()
8818
 
-        # Mark duplicate URIs for deletion
8819
 
-        for i in range (len (self.devices)):
8820
 
-            for j in range (len (self.devices)):
8821
 
-                if i == j: continue
8822
 
-                device1 = self.devices[i]
8823
 
-                device2 = self.devices[j]
8824
 
-                if device1.uri == "delete" or device2.uri == "delete":
8825
 
-                    continue
8826
 
-                if device1.uri == device2.uri:
8827
 
-                    # Keep the one with the longer (better) device ID
8828
 
-                    if (not device1.id):
8829
 
-                        device1.uri = "delete"
8830
 
-                    elif (not device2.id):
8831
 
-                        device2.uri = "delete"
8832
 
-                    elif (len (device1.id) < len (device2.id)):
8833
 
-                        device1.uri = "delete"
8834
 
-                    else:
8835
 
-                        device2.uri = "delete"
8836
 
-        self.devices = filter(lambda x: x.uri not in ("hp:/no_device_found",
8837
 
-                                                      "hpfax:/no_device_found",
8838
 
-                                                      "hp", "hpfax",
8839
 
-                                                      "hal", "beh",
8840
 
-                                                      "scsi", "http", "delete"),
8841
 
-                              self.devices)
8842
 
-        self.devices.sort()
8843
 
-
8844
 
-        self.devices.append(cupshelpers.Device('',
8845
 
-             **{'device-info' :i18nc("Other device", "Other")}))
8846
 
-        if current_uri:
8847
 
-            current.info = i18nc("Current device", "%1 (Current)", current.info)
8848
 
-            self.devices.insert(0, current)
8849
 
-            self.device = current
8850
 
-        self.tvNPDevices.clear()
8851
 
-
8852
 
-        for device in self.devices:
8853
 
-            self.tvNPDevices.addItem(device.info)
8854
 
-
8855
 
-        #self.tvNPDevices.get_selection().select_path(0)
8856
 
-        self.tvNPDevices.setCurrentRow(0)
8857
 
-        self.on_tvNPDevices_cursor_changed()
8858
 
-
8859
 
-    def on_entNPTDevice_changed(self, entry):
8860
 
-        self.setNPButtons()
8861
 
-
8862
 
-    #TODO
8863
 
-    ## SMB browsing
8864
 
-    def on_entSMBURI_changed (self, text):
8865
 
-        uri = unicode(text)
8866
 
-        (group, host, share, user, password) = SMBURI (uri=uri).separate ()
8867
 
-        if user:
8868
 
-            self.entSMBUsername.setText(user)
8869
 
-        if password:
8870
 
-            self.entSMBPassword.setText(password)
8871
 
-        if user or password:
8872
 
-            uri = SMBURI (group=group, host=host, share=share).get_uri ()
8873
 
-            self.entSMBURI.setText(uri)
8874
 
-            self.rbtnSMBAuthSet.setChecked(True)
8875
 
-        elif unicode(self.entSMBUsername.text()) == '':
8876
 
-            self.rbtnSMBAuthPrompt.setChecked(True)
8877
 
-
8878
 
-        self.btnSMBVerify.setEnabled(bool(uri))
8879
 
-
8880
 
-    def on_rbtnSMBAuthSet_toggled(self, ticked):
8881
 
-        self.tblSMBAuth.setEnabled(ticked)
8882
 
-
8883
 
-    def on_entNPTIPPHostname_textChanged(self):
8884
 
-        valid = len (self.entNPTIPPHostname.text ()) > 0
8885
 
-        self.btnIPPFindQueue.setEnabled(valid)
8886
 
-        self.update_IPP_URI_label ()
8887
 
-
8888
 
-    ### IPP Browsing
8889
 
-    def update_IPP_URI_label(self):
8890
 
-        hostname = unicode(self.entNPTIPPHostname.text())
8891
 
-        queue = unicode(self.entNPTIPPQueuename.text())
8892
 
-        valid = len (hostname) > 0 and queue != '/printers/'
8893
 
-
8894
 
-        if valid:
8895
 
-            uri = "ipp://%s%s" % (hostname, queue)
8896
 
-            self.lblIPPURI.setText(uri)
8897
 
-            self.lblIPPURI.show ()
8898
 
-            self.entNPTIPPQueuename.show ()
8899
 
-        else:
8900
 
-            self.lblIPPURI.hide ()
8901
 
-
8902
 
-        self.btnIPPVerify.setEnabled(valid)
8903
 
-        self.setNPButtons ()
8904
 
-
8905
 
-    #FIXME this seems totally different from the Gnome one
8906
 
-    @pyqtSignature("")
8907
 
-    def on_btnIPPFindQueue_clicked(self):
8908
 
-        self.IPPBrowseBox.clear()
8909
 
-        host = str(self.entNPTIPPHostname.text())
8910
 
-        cups.setServer (host)
8911
 
-        printers = classes = {}
8912
 
-        try:
8913
 
-            c = cups.Connection()
8914
 
-            printers = c.getPrinters ()
8915
 
-            classes = c.getClasses ()
8916
 
-            del c
8917
 
-        except RuntimeError:
8918
 
-            pass
8919
 
-        except cups.IPP_Error, (e, msg):
8920
 
-            pass
8921
 
-
8922
 
-        for printer, dict in printers.iteritems ():
8923
 
-
8924
 
-            self.IPPBrowseBox.addItem(printer)
8925
 
-#            store.set_value (iter, 0, printer)
8926
 
-#            store.set_value (iter, 1, dict.get ('printer-location', ''))
8927
 
-#            store.set_value (iter, 2, dict)
8928
 
-        for pclass, dict in classes.iteritems ():
8929
 
-            pass
8930
 
-#            iter = store.append (None)
8931
 
-#            store.set_value (iter, 0, pclass)
8932
 
-#            store.set_value (iter, 1, dict.get ('printer-location', ''))
8933
 
-#            store.set_value (iter, 2, dict)
8934
 
-
8935
 
-        if len (printers) + len (classes) == 0:
8936
 
-            # Display 'No queues' dialog
8937
 
-            QMessageBox.information(self, i18n("No queues"),i18n("There are no queues available."))
8938
 
-
8939
 
-    def on_tvNPDevices_cursor_changed(self):
8940
 
-        device = self.devices[self.tvNPDevices.currentRow()]
8941
 
-        self.device = device
8942
 
-        self.lblNPDeviceDescription.setText('')
8943
 
-        page = self.new_printer_device_tabs.get(device.type, 1)
8944
 
-        self.ntbkNPType.setCurrentIndex(page)
8945
 
-
8946
 
-        type = device.type
8947
 
-        url = device.uri.split(":", 1)[-1]
8948
 
-        if page == 0:
8949
 
-            # This is the "no options" page, with just a label to describe
8950
 
-            # the selected device.
8951
 
-            if device.type == "parallel":
8952
 
-                text = i18n("A printer connected to the parallel port.")
8953
 
-            elif device.type == "usb":
8954
 
-                text = i18n("A printer connected to a USB port.")
8955
 
-            elif device.type == "hp":
8956
 
-                text = i18n("HPLIP software driving a printer, "
8957
 
-                         "or the printer function of a multi-function device.")
8958
 
-            elif device.type == "hpfax":
8959
 
-                text = i18n("HPLIP software driving a fax machine, "
8960
 
-                         "or the fax function of a multi-function device.")
8961
 
-            elif device.type == "hal":
8962
 
-                text = i18n("Local printer detected by the "
8963
 
-                         "Hardware Abstraction Layer (HAL).")
8964
 
-            else:
8965
 
-                text = device.uri
8966
 
-
8967
 
-            self.lblNPDeviceDescription.setText(text)
8968
 
-        elif device.type=="socket":
8969
 
-            if device.uri.startswith ("socket"):
8970
 
-                host = device.uri[9:]
8971
 
-                i = host.find (":")
8972
 
-                if i != -1:
8973
 
-                    port = int (host[i + 1:])
8974
 
-                    host = host[:i]
8975
 
-                else:
8976
 
-                    port = 9100
8977
 
-
8978
 
-                self.entNPTDirectJetHostname.setText(host)
8979
 
-                self.entNPTDirectJetPort.setText(str (port))
8980
 
-        elif device.type=="serial":
8981
 
-            if not device.is_class:
8982
 
-                options = device.uri.split("?")[1]
8983
 
-                options = options.split("+")
8984
 
-                option_dict = {}
8985
 
-                for option in options:
8986
 
-                    name, value = option.split("=")
8987
 
-                    option_dict[name] = value
8988
 
-                    
8989
 
-                for widget, name, optionvalues in (
8990
 
-                    (self.cmbNPTSerialBaud, "baud", None),
8991
 
-                    (self.cmbNPTSerialBits, "bits", None),
8992
 
-                    (self.cmbNPTSerialParity, "parity",
8993
 
-                     ["none", "odd", "even"]),
8994
 
-                    (self.cmbNPTSerialFlow, "flow",
8995
 
-                     ["none", "soft", "hard", "hard"])):
8996
 
-                    if option_dict.has_key(name): # option given in URI?
8997
 
-                        if optionvalues is None: # use text in widget
8998
 
-                            model = widget.get_model()
8999
 
-                            iter = model.get_iter_first()
9000
 
-                            nr = 0
9001
 
-                            while iter:
9002
 
-                                value = model.get(iter,0)[0]
9003
 
-                                if value == option_dict[name]:
9004
 
-                                    widget.set_active(nr)
9005
 
-                                    break
9006
 
-                                iter = model.iter_next(iter)
9007
 
-                                nr += 1
9008
 
-                        else: # use optionvalues
9009
 
-                            nr = optionvalues.index(
9010
 
-                                option_dict[name])
9011
 
-                            widget.set_active(nr+1) # compensate "Default"
9012
 
-                    else:
9013
 
-                        widget.set_active(0)
9014
 
-
9015
 
-        # XXX FILL TABS FOR VALID DEVICE URIs
9016
 
-        elif device.type in ("ipp", "http"):
9017
 
-            if (device.uri.startswith ("ipp:") or
9018
 
-                device.uri.startswith ("http:")):
9019
 
-                match = re.match ("(ipp|https?)://([^/]+)(.*)", device.uri)
9020
 
-                if match:
9021
 
-                    server = match.group (2)
9022
 
-                    printer = match.group (3)
9023
 
-                else:
9024
 
-                    server = ""
9025
 
-                    printer = ""
9026
 
-
9027
 
-                self.entNPTIPPHostname.setText(server)
9028
 
-                self.entNPTIPPQueuename.setText(printer)
9029
 
-                self.lblIPPURI.setText(device.uri)
9030
 
-                self.lblIPPURI.show()
9031
 
-                self.entNPTIPPQueuename.show()
9032
 
-            else:
9033
 
-                self.entNPTIPPHostname.setText('')
9034
 
-                self.entNPTIPPQueuename.setText('/printers/')
9035
 
-                self.entNPTIPPQueuename.show()
9036
 
-                self.lblIPPURI.hide()
9037
 
-        elif device.type=="lpd":
9038
 
-            if device.uri.startswith ("lpd"):
9039
 
-                host = device.uri[6:]
9040
 
-                i = host.find ("/")
9041
 
-                if i != -1:
9042
 
-                    printer = host[i + 1:]
9043
 
-                    host = host[:i]
9044
 
-                else:
9045
 
-                    printer = ""
9046
 
-                self.cmbentNPTLpdHost.addItem(host)
9047
 
-                self.cmbentNPTLpdQueue.addItem(printer)
9048
 
-        elif device.uri == "lpd":
9049
 
-            pass
9050
 
-        elif device.uri == "smb":
9051
 
-            self.entSMBURI.setText('')
9052
 
-            self.btnSMBVerify.setEnabled(False)
9053
 
-        elif device.type == "smb":
9054
 
-            self.entSMBUsername.setText('')
9055
 
-            self.entSMBPassword.setText('')
9056
 
-            self.entSMBURI.setText(device.uri[6:])
9057
 
-            self.btnSMBVerify.setEnabled(True)
9058
 
-        else:
9059
 
-            self.entNPTDevice.setText(device.uri)
9060
 
-
9061
 
-        self.setNPButtons()
9062
 
-
9063
 
-    def getDeviceURI(self):
9064
 
-        type = self.device.type
9065
 
-        if type == "socket": # DirectJet
9066
 
-            host = unicode(self.entNPTDirectJetHostname.text())
9067
 
-            port = unicode(self.entNPTDirectJetPort.text())
9068
 
-            device = "socket://" + host
9069
 
-            if port:
9070
 
-                device = device + ':' + port
9071
 
-        elif type in ("http", "ipp"): # IPP
9072
 
-            if self.lblIPPURI.isVisible:
9073
 
-                device = unicode(self.lblIPPURI.text())
9074
 
-            else:
9075
 
-                device = "ipp"
9076
 
-        elif type == "lpd": # LPD
9077
 
-            host = unicode(self.cmbentNPTLpdHost.currentText())
9078
 
-            printer = unicode(self.cmbentNPTLpdQueue.currentText())
9079
 
-            device = "lpd://" + host
9080
 
-            if printer:
9081
 
-                device = device + "/" + printer
9082
 
-        elif type == "parallel": # Parallel
9083
 
-            device = self.device.uri
9084
 
-        elif type == "scsi": # SCSII
9085
 
-            device = ""
9086
 
-        elif type == "serial": # Serial
9087
 
-            options = []
9088
 
-            for widget, name, optionvalues in (
9089
 
-                (self.cmbNPTSerialBaud, "baud", None),
9090
 
-                (self.cmbNPTSerialBits, "bits", None),
9091
 
-                (self.cmbNPTSerialParity, "parity",
9092
 
-                 ("none", "odd", "even")),
9093
 
-                (self.cmbNPTSerialFlow, "flow",
9094
 
-                 ("none", "soft", "hard", "hard"))):
9095
 
-                nr = widget.get_active()
9096
 
-                if nr:
9097
 
-                    if optionvalues is not None:
9098
 
-                        option = optionvalues[nr-1]
9099
 
-                    else:
9100
 
-                        option = widget.get_active_text()
9101
 
-                    options.append(name + "=" + option)
9102
 
-            options = "+".join(options)
9103
 
-            device =  self.device.uri.split("?")[0] #"serial:/dev/ttyS%s" 
9104
 
-            if options:
9105
 
-                device = device + "?" + options
9106
 
-        elif type == "smb":
9107
 
-            uri = unicode(self.entSMBURI.text())
9108
 
-            (group, host, share, u, p) = SMBURI (uri=uri).separate ()
9109
 
-            user = ''
9110
 
-            password = ''
9111
 
-            if self.rbtnSMBAuthSet.isChecked():
9112
 
-                user = unicode(self.entSMBUsername.text())
9113
 
-                password = unicode(self.entSMBPassword.text())
9114
 
-            uri = SMBURI (group=group, host=host, share=share,
9115
 
-                          user=user, password=password).get_uri ()
9116
 
-            device = "smb://" + uri
9117
 
-        elif not self.device.is_class:
9118
 
-            device = self.device.uri
9119
 
-        else:
9120
 
-            device = str(self.entNPTDevice.text())
9121
 
-        return device
9122
 
-        # class/printer
9123
 
-
9124
 
-        if nr == self.ntbkNewPrinterPages["device"]: # Device
9125
 
-            valid = False
9126
 
-            try:
9127
 
-                uri = self.getDeviceURI ()
9128
 
-                valid = validDeviceURI (uri)
9129
 
-            except:
9130
 
-                debugprint("exception in getDeviceURI()")
9131
 
-                pass
9132
 
-            self.btnNPForward.setEnabled(valid)
9133
 
-            self.btnNPBack.hide ()
9134
 
-        else:
9135
 
-            self.btnNPBack.show()
9136
 
-
9137
 
-        self.btnNPForward.show()
9138
 
-        self.btnNPApply.hide()
9139
 
-
9140
 
-        if nr == self.ntbkNewPrinterPages["name"]: # Name
9141
 
-            self.btnNPBack.show()
9142
 
-            if self.dialog_mode == "printer":
9143
 
-                self.btnNPForward.hide()
9144
 
-                self.btnNPApply.show()
9145
 
-                self.btnNPApply.setEnabled(
9146
 
-                    self.mainapp.checkNPName(self.entNPName.getText()))
9147
 
-        if nr == self.ntbkNewPrinterPages["make"]: # Make/PPD file
9148
 
-            downloadable_selected = False
9149
 
-            if self.rbtnNPDownloadableDriverSearch.get_active ():
9150
 
-                combobox = self.cmbNPDownloadableDriverFoundPrinters
9151
 
-                iter = combobox.get_active_iter ()
9152
 
-                if iter and combobox.get_model ().get_value (iter, 1):
9153
 
-                    downloadable_selected = True
9154
 
-
9155
 
-            self.btnNPForward.setEnabled(bool(
9156
 
-                self.rbtnNPFoomatic.get_active() or
9157
 
-                not self.filechooserPPD.text().isEmpty() or
9158
 
-                downloadable_selected))
9159
 
-        if nr == self.ntbkNewPrinterPages["model"]: # Model/Driver
9160
 
-            model, iter = self.tvNPDrivers.get_selection().get_selected()
9161
 
-            self.btnNPForward.set_sensitive(bool(iter))
9162
 
-        if nr == self.ntbkNewPrinterPages["class-members"]: # Class Members
9163
 
-            self.btnNPForward.hide()
9164
 
-            self.btnNPApply.show()
9165
 
-            self.btnNPApply.setEnabled(
9166
 
-                bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
9167
 
-        if nr == self.ntbkNewPrinterPages["downloadable"]: # Downloadable drivers
9168
 
-            if self.ntbkNPDownloadableDriverProperties.get_current_page() == 1:
9169
 
-                accepted = self.rbtnNPDownloadLicenseYes.get_active ()
9170
 
-            else:
9171
 
-                accepted = True
9172
 
-
9173
 
-            self.btnNPForward.set_sensitive(accepted)
9174
 
-
9175
 
-    # PPD
9176
 
-
9177
 
-    def on_rbtnNPFoomatic_toggled(self):
9178
 
-        rbtn1 = self.rbtnNPFoomatic.isChecked()
9179
 
-        rbtn2 = self.rbtnNPPPD.isChecked()
9180
 
-        rbtn3 = self.rbtnNPDownloadableDriverSearch.isChecked()
9181
 
-        self.tvNPMakes.setEnabled(rbtn1)
9182
 
-        self.filechooserPPD.setEnabled(rbtn2)
9183
 
-
9184
 
-        """FIXME
9185
 
-        if not rbtn3 and self.openprinting_query_handle:
9186
 
-            # Need to cancel a search in progress.
9187
 
-            self.openprinting.cancelOperation (self.openprinting_query_handle)
9188
 
-            self.openprinting_query_handle = None
9189
 
-            self.btnNPDownloadableDriverSearch_label.setText(_("Search"))
9190
 
-            # Clear printer list.
9191
 
-            self.cmbNPDownloadableDriverFoundPrinters.clear()
9192
 
-        """
9193
 
-
9194
 
-        for widget in [self.entNPDownloadableDriverSearch,
9195
 
-                       self.cmbNPDownloadableDriverFoundPrinters]:
9196
 
-            widget.setEnabled(rbtn3)
9197
 
-        self.btnNPDownloadableDriverSearch.\
9198
 
-            setEnabled(rbtn3 and (self.openprinting_query_handle == None))
9199
 
-
9200
 
-        self.setNPButtons()
9201
 
-
9202
 
-    # PPD from foomatic
9203
 
-
9204
 
-    def fillMakeList(self):
9205
 
-        makes = self.ppds.getMakes()
9206
 
-        self.tvNPMakes.clear()
9207
 
-        found = False
9208
 
-        index = 0
9209
 
-        for make in makes:
9210
 
-            self.tvNPMakes.addItem(make)
9211
 
-            index = index + 1
9212
 
-            if make==self.auto_make:
9213
 
-                self.tvNPMakes.setCurrentRow(index-1)
9214
 
-                found = True
9215
 
-
9216
 
-        self.on_tvNPMakes_cursor_changed()
9217
 
-
9218
 
-    def on_tvNPMakes_cursor_changed(self):
9219
 
-        items = self.tvNPMakes.selectedItems()
9220
 
-        if len(items) > 0:
9221
 
-            self.NPMake = unicode(items[0].text())
9222
 
-            self.fillModelList()
9223
 
-
9224
 
-    def fillModelList(self):
9225
 
-        models = self.ppds.getModels(self.NPMake)
9226
 
-        self.tvNPModels.clear()
9227
 
-        selected = False
9228
 
-        index = 0
9229
 
-        selected = False
9230
 
-        for pmodel in models:
9231
 
-            self.tvNPModels.addItem(pmodel)
9232
 
-            if self.NPMake==self.auto_make and pmodel==self.auto_model:
9233
 
-                self.tvNPModels.setCurrentRow(index)
9234
 
-                selected = True
9235
 
-            index = index + 1
9236
 
-        if not selected:
9237
 
-            self.tvNPModels.setCurrentRow(0)
9238
 
-        ##self.tvNPModels.columns_autosize()
9239
 
-        self.on_tvNPModels_cursor_changed()
9240
 
-
9241
 
-    def fillDriverList(self, pmake, pmodel):
9242
 
-        self.NPModel = pmodel
9243
 
-        self.tvNPDrivers.clear()
9244
 
-
9245
 
-        ppds = self.ppds.getInfoFromModel(pmake, pmodel)
9246
 
-
9247
 
-        self.NPDrivers = self.ppds.orderPPDNamesByPreference(ppds.keys()) 
9248
 
-        for i in range (len(self.NPDrivers)):
9249
 
-            ppd = ppds[self.NPDrivers[i]]
9250
 
-            driver = ppd["ppd-make-and-model"]
9251
 
-            driver = driver.replace(" (recommended)", "")
9252
 
-
9253
 
-            try:
9254
 
-                lpostfix = " [%s]" % ppd["ppd-natural-language"]
9255
 
-                driver += lpostfix
9256
 
-            except KeyError:
9257
 
-                pass
9258
 
-
9259
 
-            if i == 0:
9260
 
-                self.tvNPDrivers.addItem(i18nc("Recommended driver", "%1 (recommended)", driver))
9261
 
-                self.tvNPDrivers.setCurrentRow(0)
9262
 
-            else:
9263
 
-                self.tvNPDrivers.addItem(driver)
9264
 
-        ##self.tvNPDrivers.columns_autosize()
9265
 
-
9266
 
-    def on_tvNPModels_cursor_changed(self):
9267
 
-        items = self.tvNPModels.selectedItems()
9268
 
-        if len(items) > 0:
9269
 
-            pmodel = unicode(items[0].text())
9270
 
-            self.fillDriverList(self.NPMake, pmodel)
9271
 
-
9272
 
-    def getNPPPD(self):
9273
 
-        try:
9274
 
-            if self.rbtnNPFoomatic.isChecked():
9275
 
-                #items = self.tvNPDrivers.selectedItems()
9276
 
-                #nr = unicode(items[0])
9277
 
-                nr = self.tvNPDrivers.currentRow()
9278
 
-                ppd = self.NPDrivers[nr]
9279
 
-            elif self.rbtnNPPPD.isChecked():
9280
 
-                ppd = cups.PPD(unicode(self.filechooserPPD.text()))
9281
 
-            else:
9282
 
-                """FIXME
9283
 
-                # PPD of the driver downloaded from OpenPrinting XXX
9284
 
-                treeview = self.tvNPDownloadableDrivers
9285
 
-                model, iter = treeview.get_selection ().get_selected ()
9286
 
-                driver = model.get_value (iter, 1)
9287
 
-                if driver.has_key ('ppds'):
9288
 
-                    # Only need to download a PPD.
9289
 
-                    file_to_download = driver
9290
 
-                """
9291
 
-
9292
 
-                ppd = "XXX"
9293
 
-
9294
 
-        except RuntimeError, e:
9295
 
-            if self.rbtnNPFoomatic.isChecked():
9296
 
-                # Foomatic database problem of some sort.
9297
 
-                err_title = i18n('Database error')
9298
 
-                model, iter = (self.tvNPDrivers.get_selection().
9299
 
-                               get_selected())
9300
 
-                nr = model.get_path(iter)[0]
9301
 
-                driver = self.NPDrivers[nr]
9302
 
-                if driver.startswith ("gutenprint"):
9303
 
-                    # This printer references some XML that is not
9304
 
-                    # installed by default.  Point the user at the
9305
 
-                    # package they need to install.
9306
 
-                    err = i18n("You will need to install the '%1' package "
9307
 
-                            "in order to use this driver.",
9308
 
-                            "gutenprint-foomatic")
9309
 
-                else:
9310
 
-                    err = i18n("The '%1' driver cannot be "
9311
 
-                             "used with printer '%2 %3'.", driver, self.NPMake, self.NPModel)
9312
 
-            elif self.rbtnNPPPD.isChecked():
9313
 
-                # This error came from trying to open the PPD file.
9314
 
-                err_title = i18n('PPD error')
9315
 
-                filename = self.filechooserPPD.text()
9316
 
-                err = i18n('Failed to read PPD file.  Possible reason '
9317
 
-                        'follows:') + '\n'
9318
 
-                os.environ["PPD"] = filename
9319
 
-                # We want this to be in the current natural language,
9320
 
-                # so we intentionally don't set LC_ALL=C here.
9321
 
-                p = os.popen ('/usr/bin/cupstestppd -rvv "$PPD"', 'r')
9322
 
-                output = p.readlines ()
9323
 
-                p.close ()
9324
 
-                err += reduce (lambda x, y: x + y, output)
9325
 
-            else:
9326
 
-                # Failed to get PPD downloaded from OpenPrinting XXX
9327
 
-                err_title = i18n('Downloadable drivers')
9328
 
-                err_text = i18n("Support for downloadable "
9329
 
-                             "drivers is not yet completed.")
9330
 
-
9331
 
-            error_text = ('<span size="larger">' +
9332
 
-                          i18nc("Error title", "<b>%1</b>", err_title) + '</span>\n\n' + err)
9333
 
-            QMessageBox.critical(self, err_title, error_text)
9334
 
-            return None
9335
 
-
9336
 
-        if isinstance(ppd, str) or isinstance(ppd, unicode):
9337
 
-            try:
9338
 
-                if (ppd != "raw"):
9339
 
-                    f = self.mainapp.cups.getServerPPD(ppd)
9340
 
-                    ppd = cups.PPD(f)
9341
 
-                    os.unlink(f)
9342
 
-            except AttributeError:
9343
 
-                nonfatalException()
9344
 
-                debugprint ("pycups function getServerPPD not available: never mind")
9345
 
-            except RuntimeError:
9346
 
-                nonfatalException()
9347
 
-                debugprint ("libcups from CUPS 1.3 not available: never mind")
9348
 
-            except cups.IPPError:
9349
 
-                nonfatalException()
9350
 
-                debugprint ("CUPS 1.3 server not available: never mind")
9351
 
-
9352
 
-        return ppd
9353
 
-
9354
 
-    # Create new Printer
9355
 
-    @pyqtSignature("")
9356
 
-    def on_btnNPApply_clicked(self):
9357
 
-        if self.dialog_mode in ("class", "printer"):
9358
 
-            name = unicode(self.entNPName.text())
9359
 
-            location = unicode(self.entNPLocation.text())
9360
 
-            info = unicode(self.entNPDescription.text())
9361
 
-        else:
9362
 
-            name = self.mainapp.printer.name
9363
 
-
9364
 
-       #replace any whitespace in printer name with underscore otherwise
9365
 
-       #CUPS throws an error
9366
 
-       name = name.replace(" ", "_")
9367
 
-       
9368
 
-        # Whether to check for missing drivers.
9369
 
-        check = False
9370
 
-        checkppd = None
9371
 
-        ppd = self.ppd
9372
 
-
9373
 
-        if self.dialog_mode=="class":
9374
 
-            members = self.mainapp.getCurrentClassMembers(self.tvNCMembers)
9375
 
-            try:
9376
 
-                for member in members:
9377
 
-                    self.passwd_retry = False # use cached Passwd 
9378
 
-                    self.mainapp.cups.addPrinterToClass(str(member), name)
9379
 
-            except cups.IPPError, (e, msg):
9380
 
-                self.show_IPP_Error(e, msg)
9381
 
-                return
9382
 
-        elif self.dialog_mode=="printer":
9383
 
-            self.device.uri = unicode(self.device.uri)
9384
 
-            uri = None
9385
 
-            if self.device.uri:
9386
 
-                uri = self.device.uri
9387
 
-            else:
9388
 
-                uri = self.getDeviceURI()
9389
 
-            if not self.ppd: # XXX needed?
9390
 
-                # Go back to previous page to re-select driver.
9391
 
-                self.nextNPTab(-1)
9392
 
-                return
9393
 
-
9394
 
-            # write Installable Options to ppd
9395
 
-            for option in self.options.itervalues():
9396
 
-                option.writeback()
9397
 
-
9398
 
-            #self.busy(self)
9399
 
-            self.WaitWindow.setText(i18n('<b>Adding</b>') + '<br /><br />' +
9400
 
-                                    i18n('Adding printer'))
9401
 
-            #self.WaitWindow.set_transient_for (self.NewPrinterWindow)
9402
 
-            self.WaitWindow.show ()
9403
 
-            QApplication.processEvents()
9404
 
-            try:
9405
 
-                self.passwd_retry = False # use cached Passwd
9406
 
-                if isinstance(ppd, str) or isinstance(ppd, unicode):
9407
 
-                    self.mainapp.cups.addPrinter(name, ppdname=ppd,
9408
 
-                         device=uri, info=info, location=location)
9409
 
-                    check = True
9410
 
-                elif ppd is None: # raw queue
9411
 
-                    self.mainapp.cups.addPrinter(name, device=uri,
9412
 
-                                         info=info, location=location)
9413
 
-                else:
9414
 
-                    cupshelpers.setPPDPageSize(ppd, self.language[0])
9415
 
-                    self.mainapp.cups.addPrinter(name, ppd=ppd,
9416
 
-                         device=uri, info=info, location=location)
9417
 
-                    check = True
9418
 
-                    checkppd = ppd
9419
 
-                cupshelpers.activateNewPrinter (self.mainapp.cups, name)
9420
 
-            except cups.IPPError, (e, msg):
9421
 
-                #self.ready(self)
9422
 
-                self.WaitWindow.hide ()
9423
 
-                self.show_IPP_Error(e, msg)
9424
 
-                return
9425
 
-            except:
9426
 
-                ##self.ready (self.NewPrinterWindow)
9427
 
-                self.WaitWindow.hide ()
9428
 
-                fatalException (1)
9429
 
-            self.WaitWindow.hide ()
9430
 
-            ##self.ready (self.NewPrinterWindow)
9431
 
-    #comment  
9432
 
-        if self.dialog_mode in ("class", "printer"):
9433
 
-            try:
9434
 
-                self.passwd_retry = False # use cached Passwd 
9435
 
-                self.mainapp.cups.setPrinterLocation(name, location)
9436
 
-                self.passwd_retry = False # use cached Passwd 
9437
 
-                self.mainapp.cups.setPrinterInfo(name, info)
9438
 
-            except cups.IPPError, (e, msg):
9439
 
-                self.show_IPP_Error(e, msg)
9440
 
-                return
9441
 
-        elif self.dialog_mode == "device":
9442
 
-            try:
9443
 
-                uri = self.getDeviceURI()
9444
 
-                self.mainapp.cups.addPrinter(name, device=uri)
9445
 
-            except cups.IPPError, (e, msg):
9446
 
-                self.show_IPP_Error(e, msg)
9447
 
-                return 
9448
 
-        elif self.dialog_mode == "ppd":
9449
 
-            if not ppd:
9450
 
-                ppd = self.ppd = self.getNPPPD()
9451
 
-                if not ppd:
9452
 
-                    # Go back to previous page to re-select driver.
9453
 
-                    self.nextNPTab(-1)
9454
 
-                    return
9455
 
-
9456
 
-            # set ppd on server and retrieve it
9457
 
-            # cups doesn't offer a way to just download a ppd ;(=
9458
 
-            raw = False
9459
 
-            if isinstance(ppd, str) or isinstance(ppd, unicode):
9460
 
-                if self.rbtnChangePPDasIs.isChecked():
9461
 
-                    # To use the PPD as-is we need to prevent CUPS copying
9462
 
-                    # the old options over.  Do this by setting it to a
9463
 
-                    # raw queue (no PPD) first.
9464
 
-                    try:
9465
 
-                        self.mainapp.cups.addPrinter(name, ppdname='raw')
9466
 
-                    except cups.IPPError, (e, msg):
9467
 
-                        self.show_IPP_Error(e, msg)
9468
 
-                try:
9469
 
-                    self.mainapp.cups.addPrinter(name, ppdname=ppd)
9470
 
-                except cups.IPPError, (e, msg):
9471
 
-                    self.show_IPP_Error(e, msg)
9472
 
-                    return
9473
 
-
9474
 
-                try:
9475
 
-                    filename = self.mainapp.cups.getPPD(name)
9476
 
-                    ppd = cups.PPD(filename)
9477
 
-                    os.unlink(filename)
9478
 
-                except cups.IPPError, (e, msg):
9479
 
-                    if e == cups.IPP_NOT_FOUND:
9480
 
-                        raw = True
9481
 
-                    else:
9482
 
-                        self.show_IPP_Error(e, msg)
9483
 
-                        return
9484
 
-            else:
9485
 
-                # We have an actual PPD to upload, not just a name.
9486
 
-                if not self.rbtnChangePPDasIs.isChecked():
9487
 
-                    cupshelpers.copyPPDOptions(self.mainapp.ppd, ppd) # XXX
9488
 
-                else:
9489
 
-                    # write Installable Options to ppd
9490
 
-                    for option in self.options.itervalues():
9491
 
-                        option.writeback()
9492
 
-                    cupshelpers.setPPDPageSize(ppd, self.language[0])
9493
 
-
9494
 
-                try:
9495
 
-                    self.mainapp.cups.addPrinter(name, ppd=ppd)
9496
 
-                except cups.IPPError, (e, msg):
9497
 
-                    self.show_IPP_Error(e, msg)
9498
 
-
9499
 
-            if not raw:
9500
 
-                check = True
9501
 
-                checkppd = ppd
9502
 
-
9503
 
-        self.accept()
9504
 
-        self.mainapp.populateList(start_printer=name)
9505
 
-        if check:
9506
 
-            try:
9507
 
-                self.checkDriverExists (name, ppd=checkppd)
9508
 
-            except:
9509
 
-                nonfatalException()
9510
 
-
9511
 
-            # Also check to see whether the media option has become
9512
 
-            # invalid.  This can happen if it had previously been
9513
 
-            # explicitly set to a page size that is not offered with
9514
 
-            # the new PPD (see bug #441836).
9515
 
-            """
9516
 
-            try:
9517
 
-                option = self.mainapp.server_side_options['media']
9518
 
-                if option.get_current_value () == None:
9519
 
-                    debugprint ("Invalid media option: resetting")
9520
 
-                    option.reset ()
9521
 
-                    self.mainapp.changed.add (option)
9522
 
-                    self.mainapp.save_printer (self.mainapp.printer)
9523
 
-            except KeyError:
9524
 
-                pass
9525
 
-            except:
9526
 
-                print "exception in check to see whether the media option has become invalid"
9527
 
-                nonfatalException()
9528
 
-            """
9529
 
-
9530
 
-    def show_IPP_Error(self, exception, message):
9531
 
-           if exception == cups.IPP_NOT_AUTHORIZED:
9532
 
-               QMessageBox.critical(self, i18n('Not authorized'), i18n('The password may be incorrect.'))
9533
 
-           else:
9534
 
-               QMessageBox.critical(self, i18n('CUPS server error'), i18n("There was an error during the CUPS "\
9535
 
-                                                               "operation: '%1'.", message))
9536
 
-
9537
 
-    def checkDriverExists(self, name, ppd=None):
9538
 
-        """Check that the driver for an existing queue actually
9539
 
-        exists, and prompt to install the appropriate package
9540
 
-        if not.
9541
 
-
9542
 
-        ppd: cups.PPD object, if already created"""
9543
 
-
9544
 
-        # Is this queue on the local machine?  If not, we can't check
9545
 
-        # anything at all.
9546
 
-        server = cups.getServer ()
9547
 
-        if not (server == 'localhost' or server == '127.0.0.1' or
9548
 
-                server == '::1' or server[0] == '/'):
9549
 
-            return
9550
 
-
9551
 
-        # Fetch the PPD if we haven't already.
9552
 
-        if not ppd:
9553
 
-            try:
9554
 
-                filename = self.mainapp.cups.getPPD(name)
9555
 
-            except cups.IPPError, (e, msg):
9556
 
-                if e == cups.IPP_NOT_FOUND:
9557
 
-                    # This is a raw queue.  Nothing to check.
9558
 
-                    return
9559
 
-                else:
9560
 
-                    self.show_IPP_Error(e, msg)
9561
 
-                    return
9562
 
-
9563
 
-            ppd = cups.PPD(filename)
9564
 
-            os.unlink(filename)
9565
 
-
9566
 
-        (pkgs, exes) = cupshelpers.missingPackagesAndExecutables (ppd)
9567
 
-        if len (pkgs) > 0 or len (exes) > 0:
9568
 
-            # We didn't find a necessary executable.  Complain.
9569
 
-            install = "/usr/bin/system-install-packages"
9570
 
-            if len (pkgs) > 0 and os.access (install, os.X_OK):
9571
 
-                pkg = pkgs[0]
9572
 
-                install_text = ('<span weight="bold" size="larger">' +
9573
 
-                                i18n('Install driver') + '</span>\n\n' +
9574
 
-                                i18n("Printer '%1' requires the %2 package but "
9575
 
-                                  "it is not currently installed.", name, pkg))
9576
 
-                dialog = self.InstallDialog
9577
 
-                self.lblInstall.set_markup(install_text)
9578
 
-            else:
9579
 
-                error_text = ('<span weight="bold" size="larger">' +
9580
 
-                              i18n('Missing driver') + '</span>\n\n' +
9581
 
-                              i18n("Printer '%1' requires the '%2' program but "
9582
 
-                                "it is not currently installed.  Please "
9583
 
-                                "install it before using this printer.", name, (exes + pkgs)[0]))
9584
 
-                QMessageBox.error(self, "", error_text)
9585
 
-
9586
 
-            """
9587
 
-            if pkg and response == gtk.RESPONSE_OK:
9588
 
-                # Install the package.
9589
 
-                def wait_child (sig, stack):
9590
 
-                    (pid, status) = os.wait ()
9591
 
-
9592
 
-                signal.signal (signal.SIGCHLD, wait_child)
9593
 
-                pid = os.fork ()
9594
 
-                if pid == 0:
9595
 
-                    # Child.
9596
 
-                    try:
9597
 
-                        os.execv (install, [install, pkg])
9598
 
-                    except:
9599
 
-                        pass
9600
 
-                    sys.exit (1)
9601
 
-                elif pid == -1:
9602
 
-                    pass # should handle error
9603
 
-            """
9604
 
-
9605
 
-    #FIXME obsolete?
9606
 
-    def on_entNPTIPPQueuename_textChanged(self, ent):
9607
 
-        self.update_IPP_URI_label ()
9608
 
-
9609
 
-    #FIXME obsolete?
9610
 
-    def on_IPPBrowseBox_currentTextChanged(self, text):
9611
 
-        self.update_IPP_URI_label()
9612
 
-
9613
 
-    #FIXME not in gnome?
9614
 
-    @pyqtSignature("")
9615
 
-    def on_btnNPCancel_clicked(self):
9616
 
-        self.hide()
9617
 
-#end of class NewPrinterGUI
9618
 
-
9619
 
-if __name__ == "__main__":
9620
 
-    """start the application"""
9621
 
-
9622
 
-    appName     = "system-config-printer-kde"
9623
 
-    catalogue   = "system-config-printer-kde"
9624
 
-    programName = ki18n("System Config Printer KDE")
9625
 
-    version     = "1.0"
9626
 
-    description = ki18n("Printer configuration tool")
9627
 
-    license     = KAboutData.License_GPL
9628
 
-    copyright   = ki18n("2007 Tim Waugh, Red Hat Inc, 2007-2008 Canonical Ltd")
9629
 
-    text        = KLocalizedString()
9630
 
-    homePage    = "https://launchpad.net/system-config-printer"
9631
 
-    bugEmail    = ""
9632
 
-
9633
 
-    aboutData   = KAboutData (appName, catalogue, programName, version, description,
9634
 
-                                license, copyright, text, homePage, bugEmail)
9635
 
-
9636
 
-    aboutData.addAuthor(ki18n("Jonathan Riddell"), ki18n("Author"))
9637
 
-    aboutData.addAuthor(ki18n("Tim Waugh/Red Hat"), ki18n("System Config Printer Author"))
9638
 
-
9639
 
-    options = KCmdLineOptions()
9640
 
-
9641
 
-    KCmdLineArgs.init(sys.argv, aboutData)
9642
 
-    KCmdLineArgs.addCmdLineOptions(options)
9643
 
-
9644
 
-    app = KApplication()
9645
 
-    args = KCmdLineArgs.parsedArgs()
9646
 
-
9647
 
-    applet = GUI()
9648
 
-    sys.exit(app.exec_())
9649
 
diff -urN orig/kdeadmin-4.2.2/system-config-printer-kde/system-config-printer.ui kdeadmin-4.2.2/system-config-printer-kde/system-config-printer.ui
9650
 
--- orig/kdeadmin-4.2.2/system-config-printer-kde/system-config-printer.ui      2008-12-10 16:14:00.000000000 +0000
9651
 
+++ kdeadmin-4.2.2/system-config-printer-kde/system-config-printer.ui   2009-04-09 22:56:08.000000000 +0100
9652
 
@@ -1,179 +1,230 @@
9653
 
-<ui version="4.0" >
9654
 
+<?xml version="1.0" encoding="UTF-8"?>
9655
 
+<ui version="4.0">
9656
 
  <class>form</class>
9657
 
- <widget class="QWidget" name="form" >
9658
 
-  <property name="geometry" >
9659
 
+ <widget class="QWidget" name="form">
9660
 
+  <property name="geometry">
9661
 
    <rect>
9662
 
     <x>0</x>
9663
 
     <y>0</y>
9664
 
-    <width>878</width>
9665
 
-    <height>444</height>
9666
 
+    <width>826</width>
9667
 
+    <height>509</height>
9668
 
    </rect>
9669
 
   </property>
9670
 
-  <property name="windowIcon" >
9671
 
+  <property name="windowIcon">
9672
 
    <iconset>
9673
 
     <normaloff>../../../../.designer/backup/printer-128.png</normaloff>../../../../.designer/backup/printer-128.png</iconset>
9674
 
   </property>
9675
 
-  <layout class="QGridLayout" name="gridLayout" >
9676
 
-   <item rowspan="2" row="0" column="0" >
9677
 
-    <widget class="QTreeWidget" name="mainlist" >
9678
 
-     <property name="sizePolicy" >
9679
 
-      <sizepolicy vsizetype="Expanding" hsizetype="Fixed" >
9680
 
+  <layout class="QGridLayout" name="gridLayout_4">
9681
 
+   <item row="0" column="0">
9682
 
+    <widget class="QTreeWidget" name="mainlist">
9683
 
+     <property name="sizePolicy">
9684
 
+      <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
9685
 
        <horstretch>0</horstretch>
9686
 
        <verstretch>0</verstretch>
9687
 
       </sizepolicy>
9688
 
      </property>
9689
 
-     <property name="rootIsDecorated" >
9690
 
+     <property name="rootIsDecorated">
9691
 
       <bool>true</bool>
9692
 
      </property>
9693
 
      <column>
9694
 
-      <property name="text" >
9695
 
+      <property name="text">
9696
 
        <string/>
9697
 
       </property>
9698
 
      </column>
9699
 
     </widget>
9700
 
    </item>
9701
 
-   <item row="0" column="1" colspan="3" >
9702
 
-    <widget class="QStackedWidget" name="ntbkMain" >
9703
 
-     <property name="currentIndex" >
9704
 
+   <item row="0" column="1">
9705
 
+    <widget class="QStackedWidget" name="ntbkMain">
9706
 
+     <property name="sizePolicy">
9707
 
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
9708
 
+       <horstretch>0</horstretch>
9709
 
+       <verstretch>0</verstretch>
9710
 
+      </sizepolicy>
9711
 
+     </property>
9712
 
+     <property name="currentIndex">
9713
 
       <number>2</number>
9714
 
      </property>
9715
 
-     <widget class="QWidget" name="page" >
9716
 
-      <layout class="QGridLayout" >
9717
 
-       <item row="0" column="0" >
9718
 
-        <widget class="QLabel" name="label" >
9719
 
-         <property name="text" >
9720
 
-          <string>Add New Printer</string>
9721
 
-         </property>
9722
 
-        </widget>
9723
 
-       </item>
9724
 
-       <item row="1" column="0" >
9725
 
-        <widget class="QPushButton" name="btnNewPrinter" >
9726
 
-         <property name="text" >
9727
 
-          <string>New Local Printer</string>
9728
 
-         </property>
9729
 
-        </widget>
9730
 
-       </item>
9731
 
-       <item row="1" column="1" >
9732
 
-        <widget class="QLabel" name="newPrinterLabel" >
9733
 
-         <property name="text" >
9734
 
-          <string>New printer attached to this computer.</string>
9735
 
-         </property>
9736
 
-        </widget>
9737
 
-       </item>
9738
 
-       <item row="2" column="0" >
9739
 
-        <widget class="QPushButton" name="btnNewPrinterNetwork" >
9740
 
-         <property name="text" >
9741
 
-          <string>New Network Printer</string>
9742
 
-         </property>
9743
 
-        </widget>
9744
 
-       </item>
9745
 
-       <item row="2" column="1" >
9746
 
-        <widget class="QLabel" name="newPrinterNetworkLabel" >
9747
 
-         <property name="text" >
9748
 
-          <string>New remote printer</string>
9749
 
+     <widget class="QWidget" name="page">
9750
 
+      <layout class="QVBoxLayout" name="verticalLayout_4">
9751
 
+       <item>
9752
 
+        <widget class="QLabel" name="label">
9753
 
+         <property name="sizePolicy">
9754
 
+          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
9755
 
+           <horstretch>0</horstretch>
9756
 
+           <verstretch>0</verstretch>
9757
 
+          </sizepolicy>
9758
 
          </property>
9759
 
-        </widget>
9760
 
-       </item>
9761
 
-       <item row="3" column="0" >
9762
 
-        <widget class="QPushButton" name="btnNewPrinterSpecial" >
9763
 
-         <property name="text" >
9764
 
-          <string>New Special Printer</string>
9765
 
+         <property name="font">
9766
 
+          <font>
9767
 
+           <weight>75</weight>
9768
 
+           <bold>true</bold>
9769
 
+          </font>
9770
 
          </property>
9771
 
-        </widget>
9772
 
-       </item>
9773
 
-       <item row="3" column="1" >
9774
 
-        <widget class="QLabel" name="newPrinterSpecialLabel" >
9775
 
-         <property name="text" >
9776
 
-          <string comment="KDE::DoNotExtract" >TextLabel</string>
9777
 
-         </property>
9778
 
-        </widget>
9779
 
-       </item>
9780
 
-       <item row="4" column="0" >
9781
 
-        <widget class="QPushButton" name="btnNewClass" >
9782
 
-         <property name="text" >
9783
 
-          <string>New Printer Class</string>
9784
 
+         <property name="text">
9785
 
+          <string>Add New Printer</string>
9786
 
          </property>
9787
 
         </widget>
9788
 
        </item>
9789
 
-       <item row="4" column="1" >
9790
 
-        <widget class="QLabel" name="label_5" >
9791
 
-         <property name="text" >
9792
 
-          <string>Add a new printer group.</string>
9793
 
-         </property>
9794
 
-        </widget>
9795
 
+       <item>
9796
 
+        <layout class="QGridLayout" name="gridLayout">
9797
 
+         <item row="0" column="0">
9798
 
+          <widget class="KPushButton" name="btnNewPrinter">
9799
 
+           <property name="text">
9800
 
+            <string>New Local Printer</string>
9801
 
+           </property>
9802
 
+          </widget>
9803
 
+         </item>
9804
 
+         <item row="0" column="1">
9805
 
+          <widget class="QLabel" name="newPrinterLabel">
9806
 
+           <property name="sizePolicy">
9807
 
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
9808
 
+             <horstretch>0</horstretch>
9809
 
+             <verstretch>0</verstretch>
9810
 
+            </sizepolicy>
9811
 
+           </property>
9812
 
+           <property name="text">
9813
 
+            <string>Add a new printer which is directly connected to your
9814
 
+computer.</string>
9815
 
+           </property>
9816
 
+          </widget>
9817
 
+         </item>
9818
 
+         <item row="1" column="0">
9819
 
+          <widget class="KPushButton" name="btnNewPrinterNetwork">
9820
 
+           <property name="text">
9821
 
+            <string>New Network Printer</string>
9822
 
+           </property>
9823
 
+          </widget>
9824
 
+         </item>
9825
 
+         <item row="1" column="1">
9826
 
+          <widget class="QLabel" name="newPrinterNetworkLabel">
9827
 
+           <property name="sizePolicy">
9828
 
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
9829
 
+             <horstretch>0</horstretch>
9830
 
+             <verstretch>0</verstretch>
9831
 
+            </sizepolicy>
9832
 
+           </property>
9833
 
+           <property name="text">
9834
 
+            <string>Add a new printer which is connected to your home
9835
 
+network or on the Internet.</string>
9836
 
+           </property>
9837
 
+          </widget>
9838
 
+         </item>
9839
 
+         <item row="2" column="0">
9840
 
+          <widget class="KPushButton" name="btnNewPrinterSpecial">
9841
 
+           <property name="text">
9842
 
+            <string>New Special Printer</string>
9843
 
+           </property>
9844
 
+          </widget>
9845
 
+         </item>
9846
 
+         <item row="2" column="1">
9847
 
+          <widget class="QLabel" name="newPrinterSpecialLabel">
9848
 
+           <property name="sizePolicy">
9849
 
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
9850
 
+             <horstretch>0</horstretch>
9851
 
+             <verstretch>0</verstretch>
9852
 
+            </sizepolicy>
9853
 
+           </property>
9854
 
+           <property name="text">
9855
 
+            <string>Add a new special printer such as a Fax or PDF by
9856
 
+specifying an executable command.</string>
9857
 
+           </property>
9858
 
+          </widget>
9859
 
+         </item>
9860
 
+         <item row="3" column="0">
9861
 
+          <widget class="KPushButton" name="btnNewClass">
9862
 
+           <property name="text">
9863
 
+            <string>New Printer Class</string>
9864
 
+           </property>
9865
 
+          </widget>
9866
 
+         </item>
9867
 
+         <item row="3" column="1">
9868
 
+          <widget class="QLabel" name="label_5">
9869
 
+           <property name="sizePolicy">
9870
 
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
9871
 
+             <horstretch>0</horstretch>
9872
 
+             <verstretch>0</verstretch>
9873
 
+            </sizepolicy>
9874
 
+           </property>
9875
 
+           <property name="text">
9876
 
+            <string>Add a new printer class to specify a group of computers to
9877
 
+print to.</string>
9878
 
+           </property>
9879
 
+          </widget>
9880
 
+         </item>
9881
 
+        </layout>
9882
 
        </item>
9883
 
-       <item row="5" column="0" >
9884
 
-        <spacer>
9885
 
-         <property name="orientation" >
9886
 
+       <item>
9887
 
+        <spacer name="verticalSpacer_4">
9888
 
+         <property name="orientation">
9889
 
           <enum>Qt::Vertical</enum>
9890
 
          </property>
9891
 
-         <property name="sizeHint" stdset="0" >
9892
 
+         <property name="sizeHint" stdset="0">
9893
 
           <size>
9894
 
-           <width>20</width>
9895
 
-           <height>40</height>
9896
 
+           <width>528</width>
9897
 
+           <height>317</height>
9898
 
           </size>
9899
 
          </property>
9900
 
         </spacer>
9901
 
        </item>
9902
 
       </layout>
9903
 
      </widget>
9904
 
-     <widget class="QWidget" name="page_3" >
9905
 
-      <layout class="QGridLayout" >
9906
 
-       <item row="0" column="0" colspan="2" >
9907
 
-        <layout class="QHBoxLayout" >
9908
 
+     <widget class="QWidget" name="page_3">
9909
 
+      <layout class="QGridLayout">
9910
 
+       <item row="0" column="0" colspan="2">
9911
 
+        <layout class="QHBoxLayout">
9912
 
          <item>
9913
 
-          <widget class="QLabel" name="label_6" >
9914
 
-           <property name="text" >
9915
 
+          <widget class="QLabel" name="label_6">
9916
 
+           <property name="text">
9917
 
             <string>Basic Server Settings</string>
9918
 
            </property>
9919
 
           </widget>
9920
 
          </item>
9921
 
          <item>
9922
 
-          <widget class="QLabel" name="lblClassMembers" >
9923
 
-           <property name="text" >
9924
 
+          <widget class="QLabel" name="lblClassMembers">
9925
 
+           <property name="text">
9926
 
             <string/>
9927
 
            </property>
9928
 
           </widget>
9929
 
          </item>
9930
 
          <item>
9931
 
-          <widget class="QLabel" name="lblPInstallOptions" >
9932
 
-           <property name="text" >
9933
 
+          <widget class="QLabel" name="lblPInstallOptions">
9934
 
+           <property name="text">
9935
 
             <string/>
9936
 
            </property>
9937
 
           </widget>
9938
 
          </item>
9939
 
          <item>
9940
 
-          <widget class="QLabel" name="lblPOptions" >
9941
 
-           <property name="text" >
9942
 
+          <widget class="QLabel" name="lblPOptions">
9943
 
+           <property name="text">
9944
 
             <string/>
9945
 
            </property>
9946
 
           </widget>
9947
 
          </item>
9948
 
         </layout>
9949
 
        </item>
9950
 
-       <item row="1" column="0" colspan="2" >
9951
 
-        <widget class="QCheckBox" name="chkServerBrowse" >
9952
 
-         <property name="text" >
9953
 
+       <item row="1" column="0" colspan="2">
9954
 
+        <widget class="QCheckBox" name="chkServerBrowse">
9955
 
+         <property name="text">
9956
 
           <string>Show printers shared by other systems</string>
9957
 
          </property>
9958
 
         </widget>
9959
 
        </item>
9960
 
-       <item row="2" column="0" colspan="2" >
9961
 
-        <widget class="QCheckBox" name="chkServerShare" >
9962
 
-         <property name="text" >
9963
 
+       <item row="2" column="0" colspan="2">
9964
 
+        <widget class="QCheckBox" name="chkServerShare">
9965
 
+         <property name="text">
9966
 
           <string>Share published printers connected to this system</string>
9967
 
          </property>
9968
 
         </widget>
9969
 
        </item>
9970
 
-       <item row="3" column="0" >
9971
 
+       <item row="3" column="0">
9972
 
         <spacer>
9973
 
-         <property name="orientation" >
9974
 
+         <property name="orientation">
9975
 
           <enum>Qt::Horizontal</enum>
9976
 
          </property>
9977
 
-         <property name="sizeType" >
9978
 
+         <property name="sizeType">
9979
 
           <enum>QSizePolicy::Fixed</enum>
9980
 
          </property>
9981
 
-         <property name="sizeHint" stdset="0" >
9982
 
+         <property name="sizeHint" stdset="0">
9983
 
           <size>
9984
 
            <width>16</width>
9985
 
            <height>24</height>
9986
 
@@ -181,46 +232,46 @@
9987
 
          </property>
9988
 
         </spacer>
9989
 
        </item>
9990
 
-       <item row="3" column="1" >
9991
 
-        <widget class="QCheckBox" name="chkServerShareAny" >
9992
 
-         <property name="sizePolicy" >
9993
 
-          <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
9994
 
+       <item row="3" column="1">
9995
 
+        <widget class="QCheckBox" name="chkServerShareAny">
9996
 
+         <property name="sizePolicy">
9997
 
+          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
9998
 
            <horstretch>0</horstretch>
9999
 
            <verstretch>0</verstretch>
10000
 
           </sizepolicy>
10001
 
          </property>
10002
 
-         <property name="text" >
10003
 
+         <property name="text">
10004
 
           <string>Allow printing from the internet</string>
10005
 
          </property>
10006
 
         </widget>
10007
 
        </item>
10008
 
-       <item row="4" column="0" colspan="2" >
10009
 
-        <widget class="QCheckBox" name="chkServerRemoteAdmin" >
10010
 
-         <property name="text" >
10011
 
+       <item row="4" column="0" colspan="2">
10012
 
+        <widget class="QCheckBox" name="chkServerRemoteAdmin">
10013
 
+         <property name="text">
10014
 
           <string>Allow remote administration</string>
10015
 
          </property>
10016
 
         </widget>
10017
 
        </item>
10018
 
-       <item row="5" column="0" colspan="2" >
10019
 
-        <widget class="QCheckBox" name="chkServerAllowCancelAll" >
10020
 
-         <property name="text" >
10021
 
+       <item row="5" column="0" colspan="2">
10022
 
+        <widget class="QCheckBox" name="chkServerAllowCancelAll">
10023
 
+         <property name="text">
10024
 
           <string>Allow users to cancel any job (not just their own)</string>
10025
 
          </property>
10026
 
         </widget>
10027
 
        </item>
10028
 
-       <item row="6" column="0" colspan="2" >
10029
 
-        <widget class="QCheckBox" name="chkServerLogDebug" >
10030
 
-         <property name="text" >
10031
 
+       <item row="6" column="0" colspan="2">
10032
 
+        <widget class="QCheckBox" name="chkServerLogDebug">
10033
 
+         <property name="text">
10034
 
           <string>Save debugging information for troubleshooting</string>
10035
 
          </property>
10036
 
         </widget>
10037
 
        </item>
10038
 
-       <item row="7" column="1" >
10039
 
+       <item row="7" column="1">
10040
 
         <spacer>
10041
 
-         <property name="orientation" >
10042
 
+         <property name="orientation">
10043
 
           <enum>Qt::Vertical</enum>
10044
 
          </property>
10045
 
-         <property name="sizeHint" stdset="0" >
10046
 
+         <property name="sizeHint" stdset="0">
10047
 
           <size>
10048
 
            <width>505</width>
10049
 
            <height>131</height>
10050
 
@@ -230,325 +281,1503 @@
10051
 
        </item>
10052
 
       </layout>
10053
 
      </widget>
10054
 
-     <widget class="QWidget" name="page_2" >
10055
 
-      <layout class="QGridLayout" >
10056
 
-       <item row="0" column="0" >
10057
 
-        <widget class="QTabWidget" name="tabWidget" >
10058
 
-         <property name="sizePolicy" >
10059
 
-          <sizepolicy vsizetype="Expanding" hsizetype="Minimum" >
10060
 
-           <horstretch>1</horstretch>
10061
 
-           <verstretch>0</verstretch>
10062
 
-          </sizepolicy>
10063
 
-         </property>
10064
 
-         <property name="currentIndex" >
10065
 
-          <number>0</number>
10066
 
-         </property>
10067
 
-         <widget class="QWidget" name="settings" >
10068
 
-          <attribute name="title" >
10069
 
-           <string>Settings</string>
10070
 
-          </attribute>
10071
 
-          <layout class="QGridLayout" name="gridLayout_2" >
10072
 
-           <item row="0" column="0" >
10073
 
-            <widget class="QLabel" name="lblPDescription" >
10074
 
-             <property name="text" >
10075
 
-              <string>Description:</string>
10076
 
-             </property>
10077
 
-            </widget>
10078
 
-           </item>
10079
 
-           <item row="0" column="1" colspan="5" >
10080
 
-            <widget class="QLineEdit" name="entPDescription" />
10081
 
-           </item>
10082
 
-           <item row="1" column="0" >
10083
 
-            <widget class="QLabel" name="lblPLocation" >
10084
 
-             <property name="text" >
10085
 
-              <string>Location:</string>
10086
 
-             </property>
10087
 
-            </widget>
10088
 
-           </item>
10089
 
-           <item row="1" column="1" colspan="5" >
10090
 
-            <widget class="QLineEdit" name="entPLocation" />
10091
 
-           </item>
10092
 
-           <item row="2" column="0" >
10093
 
-            <widget class="QLabel" name="lblPDevice2" >
10094
 
-             <property name="text" >
10095
 
-              <string>Device URI:</string>
10096
 
-             </property>
10097
 
-            </widget>
10098
 
-           </item>
10099
 
-           <item row="2" column="1" colspan="4" >
10100
 
-            <widget class="QLineEdit" name="entPDevice" />
10101
 
-           </item>
10102
 
-           <item row="2" column="5" >
10103
 
-            <widget class="QPushButton" name="btnSelectDevice" >
10104
 
-             <property name="text" >
10105
 
-              <string>Change</string>
10106
 
-             </property>
10107
 
-            </widget>
10108
 
-           </item>
10109
 
-           <item row="3" column="0" colspan="2" >
10110
 
-            <widget class="QLabel" name="lblPMakeModel2" >
10111
 
-             <property name="text" >
10112
 
-              <string>Make and Model:</string>
10113
 
-             </property>
10114
 
-            </widget>
10115
 
-           </item>
10116
 
-           <item row="3" column="2" colspan="3" >
10117
 
-            <widget class="QLabel" name="lblPMakeModel" >
10118
 
-             <property name="text" >
10119
 
-              <string>-</string>
10120
 
-             </property>
10121
 
-             <property name="wordWrap" >
10122
 
-              <bool>true</bool>
10123
 
-             </property>
10124
 
-            </widget>
10125
 
-           </item>
10126
 
-           <item row="3" column="5" >
10127
 
-            <widget class="QPushButton" name="btnChangePPD" >
10128
 
-             <property name="text" >
10129
 
-              <string>Change</string>
10130
 
-             </property>
10131
 
-            </widget>
10132
 
-           </item>
10133
 
-           <item row="4" column="0" colspan="2" >
10134
 
-            <widget class="QLabel" name="lblPState2" >
10135
 
-             <property name="text" >
10136
 
-              <string>Printer State:</string>
10137
 
-             </property>
10138
 
-            </widget>
10139
 
-           </item>
10140
 
-           <item row="4" column="2" colspan="4" >
10141
 
-            <widget class="QLabel" name="lblPState" >
10142
 
-             <property name="text" >
10143
 
-              <string>-</string>
10144
 
-             </property>
10145
 
-            </widget>
10146
 
-           </item>
10147
 
-           <item row="5" column="0" colspan="2" >
10148
 
-            <widget class="QLabel" name="label_12" >
10149
 
-             <property name="text" >
10150
 
-              <string>Default Printer:</string>
10151
 
-             </property>
10152
 
-            </widget>
10153
 
-           </item>
10154
 
-           <item row="5" column="2" colspan="3" >
10155
 
-            <widget class="QLabel" name="lblPDefault" >
10156
 
-             <property name="text" >
10157
 
-              <string>-</string>
10158
 
-             </property>
10159
 
-            </widget>
10160
 
-           </item>
10161
 
-           <item row="5" column="5" >
10162
 
-            <widget class="QPushButton" name="btnPMakeDefault" >
10163
 
-             <property name="text" >
10164
 
-              <string>Make Default</string>
10165
 
-             </property>
10166
 
-            </widget>
10167
 
-           </item>
10168
 
-           <item row="6" column="0" colspan="2" >
10169
 
-            <widget class="QPushButton" name="btnDelete" >
10170
 
-             <property name="text" >
10171
 
-              <string>Remove Printer</string>
10172
 
+     <widget class="QWidget" name="page_2">
10173
 
+      <layout class="QGridLayout" name="gridLayout_3">
10174
 
+       <item row="0" column="0">
10175
 
+        <layout class="QVBoxLayout" name="verticalLayout">
10176
 
+         <item>
10177
 
+          <layout class="QHBoxLayout" name="horizontalLayout">
10178
 
+           <item>
10179
 
+            <widget class="QLabel" name="printerNameLabel">
10180
 
+             <property name="font">
10181
 
+              <font>
10182
 
+               <weight>75</weight>
10183
 
+               <bold>true</bold>
10184
 
+              </font>
10185
 
+             </property>
10186
 
+             <property name="text">
10187
 
+              <string>My Printer</string>
10188
 
              </property>
10189
 
             </widget>
10190
 
            </item>
10191
 
-           <item row="6" column="2" colspan="4" >
10192
 
-            <spacer name="horizontalSpacer" >
10193
 
-             <property name="orientation" >
10194
 
+           <item>
10195
 
+            <spacer name="horizontalSpacer_2">
10196
 
+             <property name="orientation">
10197
 
               <enum>Qt::Horizontal</enum>
10198
 
              </property>
10199
 
-             <property name="sizeHint" stdset="0" >
10200
 
+             <property name="sizeHint" stdset="0">
10201
 
               <size>
10202
 
-               <width>432</width>
10203
 
+               <width>468</width>
10204
 
                <height>20</height>
10205
 
               </size>
10206
 
              </property>
10207
 
             </spacer>
10208
 
            </item>
10209
 
-           <item row="7" column="0" colspan="6" >
10210
 
-            <spacer name="verticalSpacer" >
10211
 
-             <property name="orientation" >
10212
 
-              <enum>Qt::Vertical</enum>
10213
 
-             </property>
10214
 
-             <property name="sizeHint" stdset="0" >
10215
 
-              <size>
10216
 
-               <width>548</width>
10217
 
-               <height>84</height>
10218
 
-              </size>
10219
 
-             </property>
10220
 
-            </spacer>
10221
 
-           </item>
10222
 
-           <item row="8" column="0" colspan="3" >
10223
 
-            <widget class="QPushButton" name="btnPrintTestPage" >
10224
 
-             <property name="text" >
10225
 
-              <string>Print Test Page</string>
10226
 
-             </property>
10227
 
-            </widget>
10228
 
-           </item>
10229
 
-           <item row="8" column="3" >
10230
 
-            <widget class="QPushButton" name="btnSelfTest" >
10231
 
-             <property name="text" >
10232
 
-              <string>Print Self-Test Page</string>
10233
 
-             </property>
10234
 
-            </widget>
10235
 
-           </item>
10236
 
-           <item row="8" column="4" colspan="2" >
10237
 
-            <widget class="QPushButton" name="btnCleanHeads" >
10238
 
-             <property name="text" >
10239
 
-              <string>Clean Print Heads</string>
10240
 
-             </property>
10241
 
-            </widget>
10242
 
-           </item>
10243
 
           </layout>
10244
 
-         </widget>
10245
 
-         <widget class="QWidget" name="policies" >
10246
 
-          <attribute name="title" >
10247
 
-           <string>Policies</string>
10248
 
-          </attribute>
10249
 
-          <layout class="QGridLayout" >
10250
 
-           <item row="0" column="0" >
10251
 
-            <widget class="QCheckBox" name="chkPEnabled" >
10252
 
-             <property name="text" >
10253
 
-              <string comment="Printer policy">Enabled</string>
10254
 
-             </property>
10255
 
-            </widget>
10256
 
-           </item>
10257
 
-           <item rowspan="3" row="0" column="1" >
10258
 
-            <widget class="QLabel" name="lblNotPublished" >
10259
 
-             <property name="sizePolicy" >
10260
 
-              <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
10261
 
-               <horstretch>0</horstretch>
10262
 
-               <verstretch>0</verstretch>
10263
 
-              </sizepolicy>
10264
 
-             </property>
10265
 
-             <property name="text" >
10266
 
-              <string comment="Printer policy">Not published
10267
 
-See server settings</string>
10268
 
-             </property>
10269
 
-            </widget>
10270
 
-           </item>
10271
 
-           <item row="1" column="0" >
10272
 
-            <widget class="QCheckBox" name="chkPAccepting" >
10273
 
-             <property name="text" >
10274
 
-              <string comment="Printer policy">Accepting Jobs</string>
10275
 
-             </property>
10276
 
-            </widget>
10277
 
-           </item>
10278
 
-           <item row="2" column="0" >
10279
 
-            <widget class="QCheckBox" name="chkPShared" >
10280
 
-             <property name="text" >
10281
 
-              <string comment="Printer policy">Shared</string>
10282
 
-             </property>
10283
 
-            </widget>
10284
 
-           </item>
10285
 
-           <item row="3" column="0" >
10286
 
-            <widget class="QLabel" name="label_8" >
10287
 
-             <property name="sizePolicy" >
10288
 
-              <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
10289
 
-               <horstretch>0</horstretch>
10290
 
-               <verstretch>0</verstretch>
10291
 
-              </sizepolicy>
10292
 
-             </property>
10293
 
-             <property name="text" >
10294
 
-              <string>Error Policy</string>
10295
 
-             </property>
10296
 
-            </widget>
10297
 
-           </item>
10298
 
-           <item row="3" column="1" >
10299
 
-            <widget class="QComboBox" name="cmbPErrorPolicy" />
10300
 
-           </item>
10301
 
-           <item row="4" column="0" >
10302
 
-            <widget class="QLabel" name="label_9" >
10303
 
-             <property name="sizePolicy" >
10304
 
-              <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
10305
 
-               <horstretch>0</horstretch>
10306
 
-               <verstretch>0</verstretch>
10307
 
-              </sizepolicy>
10308
 
-             </property>
10309
 
-             <property name="text" >
10310
 
-              <string>Operation Policy</string>
10311
 
-             </property>
10312
 
-            </widget>
10313
 
-           </item>
10314
 
-           <item row="4" column="1" >
10315
 
-            <widget class="QComboBox" name="cmbPOperationPolicy" />
10316
 
-           </item>
10317
 
-           <item row="5" column="0" >
10318
 
-            <widget class="QLabel" name="label_10" >
10319
 
-             <property name="sizePolicy" >
10320
 
-              <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
10321
 
-               <horstretch>0</horstretch>
10322
 
-               <verstretch>0</verstretch>
10323
 
-              </sizepolicy>
10324
 
-             </property>
10325
 
-             <property name="text" >
10326
 
-              <string>Starting Banner</string>
10327
 
-             </property>
10328
 
-            </widget>
10329
 
-           </item>
10330
 
-           <item row="5" column="1" >
10331
 
-            <widget class="QComboBox" name="cmbPStartBanner" />
10332
 
-           </item>
10333
 
-           <item row="6" column="0" >
10334
 
-            <widget class="QLabel" name="label_11" >
10335
 
-             <property name="sizePolicy" >
10336
 
-              <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
10337
 
-               <horstretch>0</horstretch>
10338
 
-               <verstretch>0</verstretch>
10339
 
-              </sizepolicy>
10340
 
-             </property>
10341
 
-             <property name="text" >
10342
 
-              <string>Ending Banner</string>
10343
 
-             </property>
10344
 
-            </widget>
10345
 
-           </item>
10346
 
-           <item row="6" column="1" >
10347
 
-            <widget class="QComboBox" name="cmbPEndBanner" />
10348
 
-           </item>
10349
 
-           <item row="7" column="0" colspan="2" >
10350
 
-            <spacer>
10351
 
-             <property name="orientation" >
10352
 
-              <enum>Qt::Vertical</enum>
10353
 
-             </property>
10354
 
-             <property name="sizeHint" stdset="0" >
10355
 
-              <size>
10356
 
-               <width>521</width>
10357
 
-               <height>20</height>
10358
 
-              </size>
10359
 
-             </property>
10360
 
-            </spacer>
10361
 
-           </item>
10362
 
-          </layout>
10363
 
-         </widget>
10364
 
-        </widget>
10365
 
+         </item>
10366
 
+         <item>
10367
 
+          <widget class="QTabWidget" name="ntbkPrinter">
10368
 
+           <property name="sizePolicy">
10369
 
+            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
10370
 
+             <horstretch>0</horstretch>
10371
 
+             <verstretch>0</verstretch>
10372
 
+            </sizepolicy>
10373
 
+           </property>
10374
 
+           <property name="currentIndex">
10375
 
+            <number>0</number>
10376
 
+           </property>
10377
 
+           <widget class="QWidget" name="settings">
10378
 
+            <attribute name="title">
10379
 
+             <string>Settings</string>
10380
 
+            </attribute>
10381
 
+            <layout class="QVBoxLayout" name="verticalLayout_5">
10382
 
+             <item>
10383
 
+              <widget class="QLabel" name="label_3">
10384
 
+               <property name="font">
10385
 
+                <font>
10386
 
+                 <weight>75</weight>
10387
 
+                 <bold>true</bold>
10388
 
+                </font>
10389
 
+               </property>
10390
 
+               <property name="text">
10391
 
+                <string>Printer Description</string>
10392
 
+               </property>
10393
 
+              </widget>
10394
 
+             </item>
10395
 
+             <item>
10396
 
+              <layout class="QGridLayout" name="gridLayout_8">
10397
 
+               <item row="0" column="0">
10398
 
+                <widget class="QLabel" name="lblPName">
10399
 
+                 <property name="text">
10400
 
+                  <string>Printer Name:</string>
10401
 
+                 </property>
10402
 
+                 <property name="alignment">
10403
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10404
 
+                 </property>
10405
 
+                </widget>
10406
 
+               </item>
10407
 
+               <item row="0" column="1">
10408
 
+                <widget class="KLineEdit" name="entPName"/>
10409
 
+               </item>
10410
 
+               <item row="1" column="0">
10411
 
+                <widget class="QLabel" name="lblPLocation">
10412
 
+                 <property name="text">
10413
 
+                  <string>Location:</string>
10414
 
+                 </property>
10415
 
+                 <property name="alignment">
10416
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10417
 
+                 </property>
10418
 
+                </widget>
10419
 
+               </item>
10420
 
+               <item row="1" column="1">
10421
 
+                <widget class="KLineEdit" name="entPLocation"/>
10422
 
+               </item>
10423
 
+               <item row="2" column="0">
10424
 
+                <widget class="QLabel" name="lblPDescription">
10425
 
+                 <property name="text">
10426
 
+                  <string>Printer Description:</string>
10427
 
+                 </property>
10428
 
+                 <property name="alignment">
10429
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10430
 
+                 </property>
10431
 
+                </widget>
10432
 
+               </item>
10433
 
+               <item row="2" column="1">
10434
 
+                <widget class="KLineEdit" name="entPDescription"/>
10435
 
+               </item>
10436
 
+               <item row="3" column="0">
10437
 
+                <widget class="QLabel" name="lblPDevice2">
10438
 
+                 <property name="text">
10439
 
+                  <string>Device Uri:</string>
10440
 
+                 </property>
10441
 
+                 <property name="alignment">
10442
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10443
 
+                 </property>
10444
 
+                </widget>
10445
 
+               </item>
10446
 
+               <item row="3" column="1">
10447
 
+                <widget class="KLineEdit" name="entPDevice"/>
10448
 
+               </item>
10449
 
+              </layout>
10450
 
+             </item>
10451
 
+             <item>
10452
 
+              <widget class="QCheckBox" name="chkPMakeDefault">
10453
 
+               <property name="enabled">
10454
 
+                <bool>true</bool>
10455
 
+               </property>
10456
 
+               <property name="text">
10457
 
+                <string>Make Default (Current Default is Foo at Bar)</string>
10458
 
+               </property>
10459
 
+              </widget>
10460
 
+             </item>
10461
 
+             <item>
10462
 
+              <widget class="Line" name="line">
10463
 
+               <property name="orientation">
10464
 
+                <enum>Qt::Horizontal</enum>
10465
 
+               </property>
10466
 
+              </widget>
10467
 
+             </item>
10468
 
+             <item>
10469
 
+              <widget class="QLabel" name="label_7">
10470
 
+               <property name="font">
10471
 
+                <font>
10472
 
+                 <weight>75</weight>
10473
 
+                 <bold>true</bold>
10474
 
+                </font>
10475
 
+               </property>
10476
 
+               <property name="text">
10477
 
+                <string>Driver Details</string>
10478
 
+               </property>
10479
 
+              </widget>
10480
 
+             </item>
10481
 
+             <item>
10482
 
+              <layout class="QGridLayout" name="gridLayout_16">
10483
 
+               <item row="0" column="0">
10484
 
+                <widget class="QLabel" name="lblPMakeModel2">
10485
 
+                 <property name="sizePolicy">
10486
 
+                  <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
10487
 
+                   <horstretch>0</horstretch>
10488
 
+                   <verstretch>0</verstretch>
10489
 
+                  </sizepolicy>
10490
 
+                 </property>
10491
 
+                 <property name="text">
10492
 
+                  <string>Printer Model:</string>
10493
 
+                 </property>
10494
 
+                 <property name="alignment">
10495
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10496
 
+                 </property>
10497
 
+                </widget>
10498
 
+               </item>
10499
 
+               <item row="0" column="1">
10500
 
+                <widget class="QLabel" name="lblPMakeModel">
10501
 
+                 <property name="sizePolicy">
10502
 
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
10503
 
+                   <horstretch>0</horstretch>
10504
 
+                   <verstretch>0</verstretch>
10505
 
+                  </sizepolicy>
10506
 
+                 </property>
10507
 
+                 <property name="text">
10508
 
+                  <string>-</string>
10509
 
+                 </property>
10510
 
+                 <property name="wordWrap">
10511
 
+                  <bool>true</bool>
10512
 
+                 </property>
10513
 
+                </widget>
10514
 
+               </item>
10515
 
+               <item row="0" column="2">
10516
 
+                <widget class="KPushButton" name="btnChangePPD">
10517
 
+                 <property name="text">
10518
 
+                  <string>Change...</string>
10519
 
+                 </property>
10520
 
+                </widget>
10521
 
+               </item>
10522
 
+               <item row="1" column="0">
10523
 
+                <widget class="QLabel" name="lblPType2">
10524
 
+                 <property name="sizePolicy">
10525
 
+                  <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
10526
 
+                   <horstretch>0</horstretch>
10527
 
+                   <verstretch>0</verstretch>
10528
 
+                  </sizepolicy>
10529
 
+                 </property>
10530
 
+                 <property name="text">
10531
 
+                  <string>Printer State:</string>
10532
 
+                 </property>
10533
 
+                 <property name="alignment">
10534
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10535
 
+                 </property>
10536
 
+                </widget>
10537
 
+               </item>
10538
 
+               <item row="1" column="1" colspan="2">
10539
 
+                <widget class="QLabel" name="lblPState">
10540
 
+                 <property name="sizePolicy">
10541
 
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
10542
 
+                   <horstretch>0</horstretch>
10543
 
+                   <verstretch>0</verstretch>
10544
 
+                  </sizepolicy>
10545
 
+                 </property>
10546
 
+                 <property name="text">
10547
 
+                  <string>-</string>
10548
 
+                 </property>
10549
 
+                </widget>
10550
 
+               </item>
10551
 
+              </layout>
10552
 
+             </item>
10553
 
+             <item>
10554
 
+              <widget class="Line" name="line_2">
10555
 
+               <property name="orientation">
10556
 
+                <enum>Qt::Horizontal</enum>
10557
 
+               </property>
10558
 
+              </widget>
10559
 
+             </item>
10560
 
+             <item>
10561
 
+              <widget class="QLabel" name="label_12">
10562
 
+               <property name="font">
10563
 
+                <font>
10564
 
+                 <weight>75</weight>
10565
 
+                 <bold>true</bold>
10566
 
+                </font>
10567
 
+               </property>
10568
 
+               <property name="text">
10569
 
+                <string>Printer Status</string>
10570
 
+               </property>
10571
 
+              </widget>
10572
 
+             </item>
10573
 
+             <item>
10574
 
+              <layout class="QHBoxLayout" name="horizontalLayout_4">
10575
 
+               <item>
10576
 
+                <widget class="QCheckBox" name="chkPEnabled">
10577
 
+                 <property name="text">
10578
 
+                  <string>enable</string>
10579
 
+                 </property>
10580
 
+                </widget>
10581
 
+               </item>
10582
 
+               <item>
10583
 
+                <widget class="QCheckBox" name="chkPAccepting">
10584
 
+                 <property name="text">
10585
 
+                  <string>accepting</string>
10586
 
+                 </property>
10587
 
+                </widget>
10588
 
+               </item>
10589
 
+               <item>
10590
 
+                <widget class="QCheckBox" name="chkPShared">
10591
 
+                 <property name="text">
10592
 
+                  <string>sharing</string>
10593
 
+                 </property>
10594
 
+                </widget>
10595
 
+               </item>
10596
 
+               <item>
10597
 
+                <widget class="QLabel" name="lblNotPublished">
10598
 
+                 <property name="text">
10599
 
+                  <string>TextLabel</string>
10600
 
+                 </property>
10601
 
+                </widget>
10602
 
+               </item>
10603
 
+               <item>
10604
 
+                <spacer name="horizontalSpacer_10">
10605
 
+                 <property name="orientation">
10606
 
+                  <enum>Qt::Horizontal</enum>
10607
 
+                 </property>
10608
 
+                 <property name="sizeHint" stdset="0">
10609
 
+                  <size>
10610
 
+                   <width>40</width>
10611
 
+                   <height>20</height>
10612
 
+                  </size>
10613
 
+                 </property>
10614
 
+                </spacer>
10615
 
+               </item>
10616
 
+              </layout>
10617
 
+             </item>
10618
 
+             <item>
10619
 
+              <layout class="QHBoxLayout" name="horizontalLayout_5">
10620
 
+               <item>
10621
 
+                <widget class="KPushButton" name="btnPrintTestPage">
10622
 
+                 <property name="text">
10623
 
+                  <string>Print Test Page</string>
10624
 
+                 </property>
10625
 
+                </widget>
10626
 
+               </item>
10627
 
+               <item>
10628
 
+                <widget class="KPushButton" name="btnSelfTest">
10629
 
+                 <property name="text">
10630
 
+                  <string>Print Self Test</string>
10631
 
+                 </property>
10632
 
+                </widget>
10633
 
+               </item>
10634
 
+               <item>
10635
 
+                <widget class="KPushButton" name="btnCleanHeads">
10636
 
+                 <property name="text">
10637
 
+                  <string>Clean Print Heads</string>
10638
 
+                 </property>
10639
 
+                </widget>
10640
 
+               </item>
10641
 
+               <item>
10642
 
+                <spacer name="horizontalSpacer_5">
10643
 
+                 <property name="orientation">
10644
 
+                  <enum>Qt::Horizontal</enum>
10645
 
+                 </property>
10646
 
+                 <property name="sizeHint" stdset="0">
10647
 
+                  <size>
10648
 
+                   <width>99</width>
10649
 
+                   <height>17</height>
10650
 
+                  </size>
10651
 
+                 </property>
10652
 
+                </spacer>
10653
 
+               </item>
10654
 
+              </layout>
10655
 
+             </item>
10656
 
+             <item>
10657
 
+              <layout class="QHBoxLayout" name="horizontalLayout_6">
10658
 
+               <item>
10659
 
+                <widget class="KPushButton" name="btnDelete">
10660
 
+                 <property name="text">
10661
 
+                  <string>Remove Printer</string>
10662
 
+                 </property>
10663
 
+                </widget>
10664
 
+               </item>
10665
 
+               <item>
10666
 
+                <spacer name="horizontalSpacer_6">
10667
 
+                 <property name="orientation">
10668
 
+                  <enum>Qt::Horizontal</enum>
10669
 
+                 </property>
10670
 
+                 <property name="sizeHint" stdset="0">
10671
 
+                  <size>
10672
 
+                   <width>371</width>
10673
 
+                   <height>17</height>
10674
 
+                  </size>
10675
 
+                 </property>
10676
 
+                </spacer>
10677
 
+               </item>
10678
 
+              </layout>
10679
 
+             </item>
10680
 
+            </layout>
10681
 
+           </widget>
10682
 
+           <widget class="QWidget" name="policies">
10683
 
+            <attribute name="title">
10684
 
+             <string>Policies</string>
10685
 
+            </attribute>
10686
 
+            <layout class="QVBoxLayout" name="verticalLayout_6">
10687
 
+             <item>
10688
 
+              <widget class="QLabel" name="label_8">
10689
 
+               <property name="font">
10690
 
+                <font>
10691
 
+                 <weight>75</weight>
10692
 
+                 <bold>true</bold>
10693
 
+                </font>
10694
 
+               </property>
10695
 
+               <property name="text">
10696
 
+                <string>Banner Settings</string>
10697
 
+               </property>
10698
 
+              </widget>
10699
 
+             </item>
10700
 
+             <item>
10701
 
+              <layout class="QGridLayout" name="gridLayout_7">
10702
 
+               <item row="0" column="0">
10703
 
+                <widget class="QLabel" name="label_10">
10704
 
+                 <property name="sizePolicy">
10705
 
+                  <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
10706
 
+                   <horstretch>0</horstretch>
10707
 
+                   <verstretch>0</verstretch>
10708
 
+                  </sizepolicy>
10709
 
+                 </property>
10710
 
+                 <property name="text">
10711
 
+                  <string>Starting Banner:</string>
10712
 
+                 </property>
10713
 
+                 <property name="alignment">
10714
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10715
 
+                 </property>
10716
 
+                </widget>
10717
 
+               </item>
10718
 
+               <item row="0" column="1">
10719
 
+                <widget class="KComboBox" name="cmbPStartBanner"/>
10720
 
+               </item>
10721
 
+               <item row="0" column="2">
10722
 
+                <spacer name="horizontalSpacer">
10723
 
+                 <property name="orientation">
10724
 
+                  <enum>Qt::Horizontal</enum>
10725
 
+                 </property>
10726
 
+                 <property name="sizeHint" stdset="0">
10727
 
+                  <size>
10728
 
+                   <width>314</width>
10729
 
+                   <height>13</height>
10730
 
+                  </size>
10731
 
+                 </property>
10732
 
+                </spacer>
10733
 
+               </item>
10734
 
+               <item row="1" column="0">
10735
 
+                <widget class="QLabel" name="label_11">
10736
 
+                 <property name="sizePolicy">
10737
 
+                  <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
10738
 
+                   <horstretch>0</horstretch>
10739
 
+                   <verstretch>0</verstretch>
10740
 
+                  </sizepolicy>
10741
 
+                 </property>
10742
 
+                 <property name="text">
10743
 
+                  <string>Ending Banner:</string>
10744
 
+                 </property>
10745
 
+                 <property name="alignment">
10746
 
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
10747
 
+                 </property>
10748
 
+                </widget>
10749
 
+               </item>
10750
 
+               <item row="1" column="1">
10751
 
+                <widget class="KComboBox" name="cmbPEndBanner"/>
10752
 
+               </item>
10753
 
+               <item row="1" column="2">
10754
 
+                <spacer name="horizontalSpacer_3">
10755
 
+                 <property name="orientation">
10756
 
+                  <enum>Qt::Horizontal</enum>
10757
 
+                 </property>
10758
 
+                 <property name="sizeHint" stdset="0">
10759
 
+                  <size>
10760
 
+                   <width>314</width>
10761
 
+                   <height>13</height>
10762
 
+                  </size>
10763
 
+                 </property>
10764
 
+                </spacer>
10765
 
+               </item>
10766
 
+              </layout>
10767
 
+             </item>
10768
 
+             <item>
10769
 
+              <widget class="Line" name="line_3">
10770
 
+               <property name="orientation">
10771
 
+                <enum>Qt::Horizontal</enum>
10772
 
+               </property>
10773
 
+              </widget>
10774
 
+             </item>
10775
 
+             <item>
10776
 
+              <widget class="QLabel" name="label_9">
10777
 
+               <property name="font">
10778
 
+                <font>
10779
 
+                 <weight>75</weight>
10780
 
+                 <bold>true</bold>
10781
 
+                </font>
10782
 
+               </property>
10783
 
+               <property name="text">
10784
 
+                <string>User and Group Permissions</string>
10785
 
+               </property>
10786
 
+              </widget>
10787
 
+             </item>
10788
 
+             <item>
10789
 
+              <widget class="QRadioButton" name="rbtnPAllow">
10790
 
+               <property name="text">
10791
 
+                <string>Allow printing for everyone except these users.</string>
10792
 
+               </property>
10793
 
+              </widget>
10794
 
+             </item>
10795
 
+             <item>
10796
 
+              <widget class="QRadioButton" name="rbtnPDeny">
10797
 
+               <property name="text">
10798
 
+                <string>Deny printing for everyone except these users</string>
10799
 
+               </property>
10800
 
+              </widget>
10801
 
+             </item>
10802
 
+             <item>
10803
 
+              <widget class="QTreeWidget" name="tvPUsers">
10804
 
+               <property name="rootIsDecorated">
10805
 
+                <bool>false</bool>
10806
 
+               </property>
10807
 
+               <property name="headerHidden">
10808
 
+                <bool>true</bool>
10809
 
+               </property>
10810
 
+               <column>
10811
 
+                <property name="text">
10812
 
+                 <string>1</string>
10813
 
+                </property>
10814
 
+               </column>
10815
 
+              </widget>
10816
 
+             </item>
10817
 
+             <item>
10818
 
+              <layout class="QHBoxLayout" name="horizontalLayout_7">
10819
 
+               <item>
10820
 
+                <widget class="KPushButton" name="btnPAddUser">
10821
 
+                 <property name="text">
10822
 
+                  <string>Add</string>
10823
 
+                 </property>
10824
 
+                </widget>
10825
 
+               </item>
10826
 
+               <item>
10827
 
+                <widget class="KPushButton" name="btnPDelUser">
10828
 
+                 <property name="text">
10829
 
+                  <string>Remove</string>
10830
 
+                 </property>
10831
 
+                </widget>
10832
 
+               </item>
10833
 
+               <item>
10834
 
+                <spacer name="horizontalSpacer_4">
10835
 
+                 <property name="orientation">
10836
 
+                  <enum>Qt::Horizontal</enum>
10837
 
+                 </property>
10838
 
+                 <property name="sizeHint" stdset="0">
10839
 
+                  <size>
10840
 
+                   <width>354</width>
10841
 
+                   <height>20</height>
10842
 
+                  </size>
10843
 
+                 </property>
10844
 
+                </spacer>
10845
 
+               </item>
10846
 
+              </layout>
10847
 
+             </item>
10848
 
+            </layout>
10849
 
+           </widget>
10850
 
+           <widget class="QWidget" name="tab_3">
10851
 
+            <attribute name="title">
10852
 
+             <string>Members</string>
10853
 
+            </attribute>
10854
 
+            <layout class="QGridLayout" name="gridLayout_15">
10855
 
+             <item row="0" column="0" colspan="3">
10856
 
+              <widget class="QLabel" name="label_47">
10857
 
+               <property name="text">
10858
 
+                <string>Add or Remove Members</string>
10859
 
+               </property>
10860
 
+              </widget>
10861
 
+             </item>
10862
 
+             <item row="1" column="0" rowspan="4">
10863
 
+              <widget class="QListWidget" name="tvClassMembers"/>
10864
 
+             </item>
10865
 
+             <item row="1" column="1">
10866
 
+              <spacer name="verticalSpacer_2">
10867
 
+               <property name="orientation">
10868
 
+                <enum>Qt::Vertical</enum>
10869
 
+               </property>
10870
 
+               <property name="sizeHint" stdset="0">
10871
 
+                <size>
10872
 
+                 <width>20</width>
10873
 
+                 <height>125</height>
10874
 
+                </size>
10875
 
+               </property>
10876
 
+              </spacer>
10877
 
+             </item>
10878
 
+             <item row="1" column="2" rowspan="4">
10879
 
+              <widget class="QListWidget" name="tvClassNotMembers"/>
10880
 
+             </item>
10881
 
+             <item row="2" column="1">
10882
 
+              <widget class="QPushButton" name="btnClassAddMember">
10883
 
+               <property name="text">
10884
 
+                <string/>
10885
 
+               </property>
10886
 
+              </widget>
10887
 
+             </item>
10888
 
+             <item row="3" column="1">
10889
 
+              <widget class="QPushButton" name="btnClassDelMember">
10890
 
+               <property name="text">
10891
 
+                <string/>
10892
 
+               </property>
10893
 
+              </widget>
10894
 
+             </item>
10895
 
+             <item row="4" column="1">
10896
 
+              <spacer name="verticalSpacer_3">
10897
 
+               <property name="orientation">
10898
 
+                <enum>Qt::Vertical</enum>
10899
 
+               </property>
10900
 
+               <property name="sizeHint" stdset="0">
10901
 
+                <size>
10902
 
+                 <width>20</width>
10903
 
+                 <height>358</height>
10904
 
+                </size>
10905
 
+               </property>
10906
 
+              </spacer>
10907
 
+             </item>
10908
 
+            </layout>
10909
 
+           </widget>
10910
 
+           <widget class="QWidget" name="tab_2">
10911
 
+            <attribute name="title">
10912
 
+             <string>Options</string>
10913
 
+            </attribute>
10914
 
+            <layout class="QVBoxLayout" name="verticalLayout_3">
10915
 
+             <item>
10916
 
+              <widget class="QWidget" name="optionsPageWidget" native="true">
10917
 
+               <layout class="QGridLayout" name="gridLayout_5">
10918
 
+                <item row="0" column="0">
10919
 
+                 <layout class="QVBoxLayout" name="vbPOptions"/>
10920
 
+                </item>
10921
 
+               </layout>
10922
 
+              </widget>
10923
 
+             </item>
10924
 
+             <item>
10925
 
+              <spacer name="verticalSpacer">
10926
 
+               <property name="orientation">
10927
 
+                <enum>Qt::Vertical</enum>
10928
 
+               </property>
10929
 
+               <property name="sizeHint" stdset="0">
10930
 
+                <size>
10931
 
+                 <width>20</width>
10932
 
+                 <height>531</height>
10933
 
+                </size>
10934
 
+               </property>
10935
 
+              </spacer>
10936
 
+             </item>
10937
 
+            </layout>
10938
 
+           </widget>
10939
 
+           <widget class="QWidget" name="joboptions">
10940
 
+            <attribute name="title">
10941
 
+             <string>Job Options</string>
10942
 
+            </attribute>
10943
 
+            <layout class="QGridLayout" name="gridLayout_9">
10944
 
+             <item row="0" column="0">
10945
 
+              <widget class="QScrollArea" name="scrollArea">
10946
 
+               <property name="verticalScrollBarPolicy">
10947
 
+                <enum>Qt::ScrollBarAlwaysOn</enum>
10948
 
+               </property>
10949
 
+               <property name="widgetResizable">
10950
 
+                <bool>true</bool>
10951
 
+               </property>
10952
 
+               <widget class="QWidget" name="scrollAreaWidgetContents">
10953
 
+                <property name="geometry">
10954
 
+                 <rect>
10955
 
+                  <x>0</x>
10956
 
+                  <y>0</y>
10957
 
+                  <width>509</width>
10958
 
+                  <height>1026</height>
10959
 
+                 </rect>
10960
 
+                </property>
10961
 
+                <layout class="QHBoxLayout" name="horizontalLayout_3">
10962
 
+                 <item>
10963
 
+                  <widget class="QWidget" name="optionsPageWidget2" native="true">
10964
 
+                   <layout class="QVBoxLayout" name="verticalLayout_2">
10965
 
+                    <item>
10966
 
+                     <widget class="QLabel" name="label136">
10967
 
+                      <property name="text">
10968
 
+                       <string>Specify the default job options for this printer.  Jobs
10969
 
+arriving at this print server will have these options added
10970
 
+if they are not already set by the application.</string>
10971
 
+                      </property>
10972
 
+                     </widget>
10973
 
+                    </item>
10974
 
+                    <item>
10975
 
+                     <widget class="QLabel" name="label_13">
10976
 
+                      <property name="text">
10977
 
+                       <string>&lt;b&gt;Common Options&lt;/b&gt;</string>
10978
 
+                      </property>
10979
 
+                     </widget>
10980
 
+                    </item>
10981
 
+                    <item>
10982
 
+                     <layout class="QGridLayout" name="gridLayout_11">
10983
 
+                      <item row="0" column="0">
10984
 
+                       <widget class="QLabel" name="label_14">
10985
 
+                        <property name="text">
10986
 
+                         <string>Copies</string>
10987
 
+                        </property>
10988
 
+                       </widget>
10989
 
+                      </item>
10990
 
+                      <item row="0" column="1">
10991
 
+                       <widget class="QSpinBox" name="sbJOCopies"/>
10992
 
+                      </item>
10993
 
+                      <item row="0" column="2">
10994
 
+                       <widget class="QPushButton" name="btnJOResetCopies">
10995
 
+                        <property name="text">
10996
 
+                         <string>Reset</string>
10997
 
+                        </property>
10998
 
+                       </widget>
10999
 
+                      </item>
11000
 
+                      <item row="1" column="0">
11001
 
+                       <widget class="QLabel" name="label_15">
11002
 
+                        <property name="text">
11003
 
+                         <string>Orientation</string>
11004
 
+                        </property>
11005
 
+                       </widget>
11006
 
+                      </item>
11007
 
+                      <item row="1" column="1">
11008
 
+                       <widget class="QComboBox" name="cmbJOOrientationRequested">
11009
 
+                        <item>
11010
 
+                         <property name="text">
11011
 
+                          <string>Portrait (no rotation)</string>
11012
 
+                         </property>
11013
 
+                        </item>
11014
 
+                        <item>
11015
 
+                         <property name="text">
11016
 
+                          <string>Landscape (90°)</string>
11017
 
+                         </property>
11018
 
+                        </item>
11019
 
+                        <item>
11020
 
+                         <property name="text">
11021
 
+                          <string>Reverse landscape (270°)</string>
11022
 
+                         </property>
11023
 
+                        </item>
11024
 
+                        <item>
11025
 
+                         <property name="text">
11026
 
+                          <string>Reverse portrait (180°)</string>
11027
 
+                         </property>
11028
 
+                        </item>
11029
 
+                       </widget>
11030
 
+                      </item>
11031
 
+                      <item row="1" column="2">
11032
 
+                       <widget class="QPushButton" name="btnJOResetOrientationRequested">
11033
 
+                        <property name="text">
11034
 
+                         <string>Reset</string>
11035
 
+                        </property>
11036
 
+                       </widget>
11037
 
+                      </item>
11038
 
+                      <item row="2" column="0" colspan="2">
11039
 
+                       <widget class="QCheckBox" name="cbJOFitplot">
11040
 
+                        <property name="text">
11041
 
+                         <string>Scale to fit</string>
11042
 
+                        </property>
11043
 
+                       </widget>
11044
 
+                      </item>
11045
 
+                      <item row="2" column="2">
11046
 
+                       <widget class="QPushButton" name="btnJOResetFitplot">
11047
 
+                        <property name="text">
11048
 
+                         <string>Reset</string>
11049
 
+                        </property>
11050
 
+                       </widget>
11051
 
+                      </item>
11052
 
+                      <item row="3" column="0">
11053
 
+                       <widget class="QLabel" name="label_17">
11054
 
+                        <property name="text">
11055
 
+                         <string>Pages per slide</string>
11056
 
+                        </property>
11057
 
+                       </widget>
11058
 
+                      </item>
11059
 
+                      <item row="3" column="1">
11060
 
+                       <widget class="QComboBox" name="cmbJONumberUp">
11061
 
+                        <item>
11062
 
+                         <property name="text">
11063
 
+                          <string>1</string>
11064
 
+                         </property>
11065
 
+                        </item>
11066
 
+                        <item>
11067
 
+                         <property name="text">
11068
 
+                          <string>2</string>
11069
 
+                         </property>
11070
 
+                        </item>
11071
 
+                        <item>
11072
 
+                         <property name="text">
11073
 
+                          <string>4</string>
11074
 
+                         </property>
11075
 
+                        </item>
11076
 
+                        <item>
11077
 
+                         <property name="text">
11078
 
+                          <string>6</string>
11079
 
+                         </property>
11080
 
+                        </item>
11081
 
+                        <item>
11082
 
+                         <property name="text">
11083
 
+                          <string>9</string>
11084
 
+                         </property>
11085
 
+                        </item>
11086
 
+                        <item>
11087
 
+                         <property name="text">
11088
 
+                          <string>16</string>
11089
 
+                         </property>
11090
 
+                        </item>
11091
 
+                       </widget>
11092
 
+                      </item>
11093
 
+                      <item row="3" column="2">
11094
 
+                       <widget class="QPushButton" name="btnJOResetNumberUp">
11095
 
+                        <property name="text">
11096
 
+                         <string>Reset</string>
11097
 
+                        </property>
11098
 
+                       </widget>
11099
 
+                      </item>
11100
 
+                      <item row="4" column="0" colspan="2">
11101
 
+                       <layout class="QGridLayout" name="gridLayout_2">
11102
 
+                        <item row="0" column="0">
11103
 
+                         <widget class="QLabel" name="label_37">
11104
 
+                          <property name="text">
11105
 
+                           <string>Pages per side layout:</string>
11106
 
+                          </property>
11107
 
+                         </widget>
11108
 
+                        </item>
11109
 
+                        <item row="0" column="1" colspan="2">
11110
 
+                         <widget class="QComboBox" name="cmbJONumberUpLayout">
11111
 
+                          <item>
11112
 
+                           <property name="text">
11113
 
+                            <string>Left to right, top to bottom</string>
11114
 
+                           </property>
11115
 
+                          </item>
11116
 
+                          <item>
11117
 
+                           <property name="text">
11118
 
+                            <string>Left to right, bottom to top</string>
11119
 
+                           </property>
11120
 
+                          </item>
11121
 
+                          <item>
11122
 
+                           <property name="text">
11123
 
+                            <string>Right to left, top to bottom</string>
11124
 
+                           </property>
11125
 
+                          </item>
11126
 
+                         </widget>
11127
 
+                        </item>
11128
 
+                        <item row="0" column="3">
11129
 
+                         <widget class="QPushButton" name="btnJOResetNumberUpLayout">
11130
 
+                          <property name="text">
11131
 
+                           <string>Reset</string>
11132
 
+                          </property>
11133
 
+                         </widget>
11134
 
+                        </item>
11135
 
+                        <item row="1" column="0">
11136
 
+                         <widget class="QLabel" name="label_38">
11137
 
+                          <property name="text">
11138
 
+                           <string>Brightness:</string>
11139
 
+                          </property>
11140
 
+                         </widget>
11141
 
+                        </item>
11142
 
+                        <item row="1" column="1">
11143
 
+                         <widget class="QSpinBox" name="sbJOBrightness"/>
11144
 
+                        </item>
11145
 
+                        <item row="1" column="2">
11146
 
+                         <widget class="QLabel" name="label_44">
11147
 
+                          <property name="text">
11148
 
+                           <string>%</string>
11149
 
+                          </property>
11150
 
+                         </widget>
11151
 
+                        </item>
11152
 
+                        <item row="1" column="3">
11153
 
+                         <widget class="QPushButton" name="btnJOResetBrightness">
11154
 
+                          <property name="text">
11155
 
+                           <string>Reset</string>
11156
 
+                          </property>
11157
 
+                         </widget>
11158
 
+                        </item>
11159
 
+                        <item row="2" column="0">
11160
 
+                         <widget class="QLabel" name="label_39">
11161
 
+                          <property name="text">
11162
 
+                           <string>Finishings:</string>
11163
 
+                          </property>
11164
 
+                         </widget>
11165
 
+                        </item>
11166
 
+                        <item row="2" column="1" colspan="2">
11167
 
+                         <widget class="QComboBox" name="cmbJOFinishings">
11168
 
+                          <item>
11169
 
+                           <property name="text">
11170
 
+                            <string>None</string>
11171
 
+                           </property>
11172
 
+                          </item>
11173
 
+                          <item>
11174
 
+                           <property name="text">
11175
 
+                            <string>Staple</string>
11176
 
+                           </property>
11177
 
+                          </item>
11178
 
+                          <item>
11179
 
+                           <property name="text">
11180
 
+                            <string>Punch</string>
11181
 
+                           </property>
11182
 
+                          </item>
11183
 
+                          <item>
11184
 
+                           <property name="text">
11185
 
+                            <string>Cover</string>
11186
 
+                           </property>
11187
 
+                          </item>
11188
 
+                          <item>
11189
 
+                           <property name="text">
11190
 
+                            <string>Bind</string>
11191
 
+                           </property>
11192
 
+                          </item>
11193
 
+                          <item>
11194
 
+                           <property name="text">
11195
 
+                            <string>Saddle stitch</string>
11196
 
+                           </property>
11197
 
+                          </item>
11198
 
+                          <item>
11199
 
+                           <property name="text">
11200
 
+                            <string>Edge stitch</string>
11201
 
+                           </property>
11202
 
+                          </item>
11203
 
+                          <item>
11204
 
+                           <property name="text">
11205
 
+                            <string>Fold</string>
11206
 
+                           </property>
11207
 
+                          </item>
11208
 
+                          <item>
11209
 
+                           <property name="text">
11210
 
+                            <string>Trim</string>
11211
 
+                           </property>
11212
 
+                          </item>
11213
 
+                          <item>
11214
 
+                           <property name="text">
11215
 
+                            <string>Bale</string>
11216
 
+                           </property>
11217
 
+                          </item>
11218
 
+                          <item>
11219
 
+                           <property name="text">
11220
 
+                            <string>Booklet maker</string>
11221
 
+                           </property>
11222
 
+                          </item>
11223
 
+                          <item>
11224
 
+                           <property name="text">
11225
 
+                            <string>Job offset</string>
11226
 
+                           </property>
11227
 
+                          </item>
11228
 
+                          <item>
11229
 
+                           <property name="text">
11230
 
+                            <string>Staple (top left)</string>
11231
 
+                           </property>
11232
 
+                          </item>
11233
 
+                          <item>
11234
 
+                           <property name="text">
11235
 
+                            <string>Staple (bottom left)</string>
11236
 
+                           </property>
11237
 
+                          </item>
11238
 
+                          <item>
11239
 
+                           <property name="text">
11240
 
+                            <string>Staple (top right)</string>
11241
 
+                           </property>
11242
 
+                          </item>
11243
 
+                          <item>
11244
 
+                           <property name="text">
11245
 
+                            <string>Staple (bottom right)</string>
11246
 
+                           </property>
11247
 
+                          </item>
11248
 
+                          <item>
11249
 
+                           <property name="text">
11250
 
+                            <string>Edge stitch (left)</string>
11251
 
+                           </property>
11252
 
+                          </item>
11253
 
+                          <item>
11254
 
+                           <property name="text">
11255
 
+                            <string>Edge stitch (top)</string>
11256
 
+                           </property>
11257
 
+                          </item>
11258
 
+                          <item>
11259
 
+                           <property name="text">
11260
 
+                            <string>Edge stitch (right)</string>
11261
 
+                           </property>
11262
 
+                          </item>
11263
 
+                          <item>
11264
 
+                           <property name="text">
11265
 
+                            <string>Edge stitch (bottom)</string>
11266
 
+                           </property>
11267
 
+                          </item>
11268
 
+                          <item>
11269
 
+                           <property name="text">
11270
 
+                            <string>Staple dual (left)</string>
11271
 
+                           </property>
11272
 
+                          </item>
11273
 
+                          <item>
11274
 
+                           <property name="text">
11275
 
+                            <string>Staple dual (top)</string>
11276
 
+                           </property>
11277
 
+                          </item>
11278
 
+                          <item>
11279
 
+                           <property name="text">
11280
 
+                            <string>Staple dual (right)</string>
11281
 
+                           </property>
11282
 
+                          </item>
11283
 
+                          <item>
11284
 
+                           <property name="text">
11285
 
+                            <string>Staple dual (bottom)</string>
11286
 
+                           </property>
11287
 
+                          </item>
11288
 
+                          <item>
11289
 
+                           <property name="text">
11290
 
+                            <string>Bind (left)</string>
11291
 
+                           </property>
11292
 
+                          </item>
11293
 
+                          <item>
11294
 
+                           <property name="text">
11295
 
+                            <string>Bind (top)</string>
11296
 
+                           </property>
11297
 
+                          </item>
11298
 
+                          <item>
11299
 
+                           <property name="text">
11300
 
+                            <string>Bind (right)</string>
11301
 
+                           </property>
11302
 
+                          </item>
11303
 
+                          <item>
11304
 
+                           <property name="text">
11305
 
+                            <string>Bind (bottom)</string>
11306
 
+                           </property>
11307
 
+                          </item>
11308
 
+                         </widget>
11309
 
+                        </item>
11310
 
+                        <item row="2" column="3">
11311
 
+                         <widget class="QPushButton" name="btnJOResetFinishings">
11312
 
+                          <property name="text">
11313
 
+                           <string>Reset</string>
11314
 
+                          </property>
11315
 
+                         </widget>
11316
 
+                        </item>
11317
 
+                        <item row="3" column="0">
11318
 
+                         <widget class="QLabel" name="label_42">
11319
 
+                          <property name="text">
11320
 
+                           <string>Job priority:</string>
11321
 
+                          </property>
11322
 
+                         </widget>
11323
 
+                        </item>
11324
 
+                        <item row="3" column="1" colspan="2">
11325
 
+                         <widget class="QSpinBox" name="sbJOJobPriority"/>
11326
 
+                        </item>
11327
 
+                        <item row="3" column="3">
11328
 
+                         <widget class="QPushButton" name="btnJOResetJobPriority">
11329
 
+                          <property name="text">
11330
 
+                           <string>Reset</string>
11331
 
+                          </property>
11332
 
+                         </widget>
11333
 
+                        </item>
11334
 
+                        <item row="4" column="0">
11335
 
+                         <widget class="QLabel" name="label_40">
11336
 
+                          <property name="text">
11337
 
+                           <string>Media:</string>
11338
 
+                          </property>
11339
 
+                         </widget>
11340
 
+                        </item>
11341
 
+                        <item row="4" column="1" colspan="2">
11342
 
+                         <widget class="QComboBox" name="cmbJOMedia"/>
11343
 
+                        </item>
11344
 
+                        <item row="4" column="3">
11345
 
+                         <widget class="QPushButton" name="btnJOResetMedia">
11346
 
+                          <property name="text">
11347
 
+                           <string>Reset</string>
11348
 
+                          </property>
11349
 
+                         </widget>
11350
 
+                        </item>
11351
 
+                        <item row="5" column="0">
11352
 
+                         <widget class="QLabel" name="label_41">
11353
 
+                          <property name="text">
11354
 
+                           <string>Sides:</string>
11355
 
+                          </property>
11356
 
+                         </widget>
11357
 
+                        </item>
11358
 
+                        <item row="5" column="1" colspan="2">
11359
 
+                         <widget class="QComboBox" name="cmbJOSides">
11360
 
+                          <item>
11361
 
+                           <property name="text">
11362
 
+                            <string>One-sided</string>
11363
 
+                           </property>
11364
 
+                          </item>
11365
 
+                          <item>
11366
 
+                           <property name="text">
11367
 
+                            <string>Two-sided (long edge)</string>
11368
 
+                           </property>
11369
 
+                          </item>
11370
 
+                          <item>
11371
 
+                           <property name="text">
11372
 
+                            <string>Two-sided (short edge)</string>
11373
 
+                           </property>
11374
 
+                          </item>
11375
 
+                         </widget>
11376
 
+                        </item>
11377
 
+                        <item row="5" column="3">
11378
 
+                         <widget class="QPushButton" name="btnJOResetSides">
11379
 
+                          <property name="text">
11380
 
+                           <string>Reset</string>
11381
 
+                          </property>
11382
 
+                         </widget>
11383
 
+                        </item>
11384
 
+                        <item row="6" column="0">
11385
 
+                         <widget class="QLabel" name="label_43">
11386
 
+                          <property name="text">
11387
 
+                           <string>Hold until:</string>
11388
 
+                          </property>
11389
 
+                         </widget>
11390
 
+                        </item>
11391
 
+                        <item row="6" column="1" colspan="2">
11392
 
+                         <widget class="QComboBox" name="cmbJOHoldUntil"/>
11393
 
+                        </item>
11394
 
+                        <item row="6" column="3">
11395
 
+                         <widget class="QPushButton" name="btnJOResetHoldUntil">
11396
 
+                          <property name="text">
11397
 
+                           <string>Reset</string>
11398
 
+                          </property>
11399
 
+                         </widget>
11400
 
+                        </item>
11401
 
+                       </layout>
11402
 
+                      </item>
11403
 
+                     </layout>
11404
 
+                    </item>
11405
 
+                    <item>
11406
 
+                     <widget class="QLabel" name="label_16">
11407
 
+                      <property name="text">
11408
 
+                       <string>&lt;b&gt;Image Options&lt;/b&gt;</string>
11409
 
+                      </property>
11410
 
+                     </widget>
11411
 
+                    </item>
11412
 
+                    <item>
11413
 
+                     <layout class="QGridLayout" name="gridLayout_6">
11414
 
+                      <item row="0" column="0" colspan="4">
11415
 
+                       <widget class="QCheckBox" name="cbJOMirror">
11416
 
+                        <property name="text">
11417
 
+                         <string>Mirror</string>
11418
 
+                        </property>
11419
 
+                       </widget>
11420
 
+                      </item>
11421
 
+                      <item row="0" column="4">
11422
 
+                       <widget class="QPushButton" name="btnJOResetMirror">
11423
 
+                        <property name="text">
11424
 
+                         <string>Reset</string>
11425
 
+                        </property>
11426
 
+                       </widget>
11427
 
+                      </item>
11428
 
+                      <item row="1" column="0">
11429
 
+                       <widget class="QLabel" name="label_18">
11430
 
+                        <property name="text">
11431
 
+                         <string>Scaling</string>
11432
 
+                        </property>
11433
 
+                       </widget>
11434
 
+                      </item>
11435
 
+                      <item row="1" column="1">
11436
 
+                       <widget class="QSpinBox" name="sbJOScaling"/>
11437
 
+                      </item>
11438
 
+                      <item row="1" column="2">
11439
 
+                       <widget class="QLabel" name="label_30">
11440
 
+                        <property name="text">
11441
 
+                         <string>%</string>
11442
 
+                        </property>
11443
 
+                       </widget>
11444
 
+                      </item>
11445
 
+                      <item row="1" column="3" colspan="2">
11446
 
+                       <widget class="QPushButton" name="btnJOResetScaling">
11447
 
+                        <property name="text">
11448
 
+                         <string>Reset</string>
11449
 
+                        </property>
11450
 
+                       </widget>
11451
 
+                      </item>
11452
 
+                      <item row="2" column="0" colspan="3">
11453
 
+                       <layout class="QGridLayout" name="gridLayout_13">
11454
 
+                        <item row="0" column="0">
11455
 
+                         <widget class="QLabel" name="label_31">
11456
 
+                          <property name="text">
11457
 
+                           <string>Saturation</string>
11458
 
+                          </property>
11459
 
+                         </widget>
11460
 
+                        </item>
11461
 
+                        <item row="0" column="1">
11462
 
+                         <widget class="QSpinBox" name="sbJOSaturation"/>
11463
 
+                        </item>
11464
 
+                        <item row="0" column="2">
11465
 
+                         <widget class="QLabel" name="label_34">
11466
 
+                          <property name="text">
11467
 
+                           <string>%</string>
11468
 
+                          </property>
11469
 
+                         </widget>
11470
 
+                        </item>
11471
 
+                        <item row="0" column="3">
11472
 
+                         <widget class="QPushButton" name="btnJOResetSaturation">
11473
 
+                          <property name="text">
11474
 
+                           <string>Reset</string>
11475
 
+                          </property>
11476
 
+                         </widget>
11477
 
+                        </item>
11478
 
+                        <item row="1" column="0">
11479
 
+                         <widget class="QLabel" name="label_32">
11480
 
+                          <property name="text">
11481
 
+                           <string>Hue adjustment</string>
11482
 
+                          </property>
11483
 
+                         </widget>
11484
 
+                        </item>
11485
 
+                        <item row="1" column="1">
11486
 
+                         <widget class="QSpinBox" name="sbJOHue"/>
11487
 
+                        </item>
11488
 
+                        <item row="1" column="2">
11489
 
+                         <widget class="QLabel" name="label_35">
11490
 
+                          <property name="text">
11491
 
+                           <string>°</string>
11492
 
+                          </property>
11493
 
+                         </widget>
11494
 
+                        </item>
11495
 
+                        <item row="1" column="3">
11496
 
+                         <widget class="QPushButton" name="btnJOResetHue">
11497
 
+                          <property name="text">
11498
 
+                           <string>Reset</string>
11499
 
+                          </property>
11500
 
+                         </widget>
11501
 
+                        </item>
11502
 
+                        <item row="2" column="0">
11503
 
+                         <widget class="QLabel" name="label_33">
11504
 
+                          <property name="text">
11505
 
+                           <string>Gamme</string>
11506
 
+                          </property>
11507
 
+                         </widget>
11508
 
+                        </item>
11509
 
+                        <item row="2" column="1">
11510
 
+                         <widget class="QSpinBox" name="sbJOGamma"/>
11511
 
+                        </item>
11512
 
+                        <item row="2" column="3">
11513
 
+                         <widget class="QPushButton" name="btnJOResetGamma">
11514
 
+                          <property name="text">
11515
 
+                           <string>Reset</string>
11516
 
+                          </property>
11517
 
+                         </widget>
11518
 
+                        </item>
11519
 
+                       </layout>
11520
 
+                      </item>
11521
 
+                      <item row="2" column="3" colspan="2">
11522
 
+                       <spacer name="horizontalSpacer_7">
11523
 
+                        <property name="orientation">
11524
 
+                         <enum>Qt::Horizontal</enum>
11525
 
+                        </property>
11526
 
+                        <property name="sizeHint" stdset="0">
11527
 
+                         <size>
11528
 
+                          <width>97</width>
11529
 
+                          <height>94</height>
11530
 
+                         </size>
11531
 
+                        </property>
11532
 
+                       </spacer>
11533
 
+                      </item>
11534
 
+                     </layout>
11535
 
+                    </item>
11536
 
+                    <item>
11537
 
+                     <widget class="QLabel" name="label_19">
11538
 
+                      <property name="text">
11539
 
+                       <string>&lt;b&gt;Text Options&lt;/b&gt;</string>
11540
 
+                      </property>
11541
 
+                     </widget>
11542
 
+                    </item>
11543
 
+                    <item>
11544
 
+                     <layout class="QGridLayout" name="gridLayout_10">
11545
 
+                      <item row="0" column="0">
11546
 
+                       <widget class="QLabel" name="label_20">
11547
 
+                        <property name="text">
11548
 
+                         <string>Character per inch:</string>
11549
 
+                        </property>
11550
 
+                        <property name="textFormat">
11551
 
+                         <enum>Qt::PlainText</enum>
11552
 
+                        </property>
11553
 
+                       </widget>
11554
 
+                      </item>
11555
 
+                      <item row="0" column="1">
11556
 
+                       <widget class="QSpinBox" name="sbJOCpi"/>
11557
 
+                      </item>
11558
 
+                      <item row="0" column="3">
11559
 
+                       <widget class="QPushButton" name="btnJOResetCpi">
11560
 
+                        <property name="text">
11561
 
+                         <string>Reset</string>
11562
 
+                        </property>
11563
 
+                       </widget>
11564
 
+                      </item>
11565
 
+                      <item row="1" column="0">
11566
 
+                       <widget class="QLabel" name="label_21">
11567
 
+                        <property name="text">
11568
 
+                         <string>Lines per inch</string>
11569
 
+                        </property>
11570
 
+                       </widget>
11571
 
+                      </item>
11572
 
+                      <item row="1" column="1">
11573
 
+                       <widget class="QSpinBox" name="sbJOLpi"/>
11574
 
+                      </item>
11575
 
+                      <item row="1" column="3">
11576
 
+                       <widget class="QPushButton" name="btnJOResetLpi">
11577
 
+                        <property name="text">
11578
 
+                         <string>Reset</string>
11579
 
+                        </property>
11580
 
+                       </widget>
11581
 
+                      </item>
11582
 
+                      <item row="2" column="0">
11583
 
+                       <widget class="QLabel" name="label_22">
11584
 
+                        <property name="text">
11585
 
+                         <string>Left margin</string>
11586
 
+                        </property>
11587
 
+                       </widget>
11588
 
+                      </item>
11589
 
+                      <item row="2" column="1">
11590
 
+                       <widget class="QSpinBox" name="sbJOPageLeft"/>
11591
 
+                      </item>
11592
 
+                      <item row="2" column="2">
11593
 
+                       <widget class="QLabel" name="label_26">
11594
 
+                        <property name="text">
11595
 
+                         <string>Points</string>
11596
 
+                        </property>
11597
 
+                       </widget>
11598
 
+                      </item>
11599
 
+                      <item row="2" column="3">
11600
 
+                       <widget class="QPushButton" name="btnJOResetPageLeft">
11601
 
+                        <property name="text">
11602
 
+                         <string>Reset</string>
11603
 
+                        </property>
11604
 
+                       </widget>
11605
 
+                      </item>
11606
 
+                      <item row="3" column="0">
11607
 
+                       <widget class="QLabel" name="label_23">
11608
 
+                        <property name="text">
11609
 
+                         <string>Right margin</string>
11610
 
+                        </property>
11611
 
+                       </widget>
11612
 
+                      </item>
11613
 
+                      <item row="3" column="1">
11614
 
+                       <widget class="QSpinBox" name="sbJOPageRight"/>
11615
 
+                      </item>
11616
 
+                      <item row="3" column="2">
11617
 
+                       <widget class="QLabel" name="label_27">
11618
 
+                        <property name="text">
11619
 
+                         <string>Points</string>
11620
 
+                        </property>
11621
 
+                       </widget>
11622
 
+                      </item>
11623
 
+                      <item row="3" column="3">
11624
 
+                       <widget class="QPushButton" name="btnJOResetPageRight">
11625
 
+                        <property name="text">
11626
 
+                         <string>Reset</string>
11627
 
+                        </property>
11628
 
+                       </widget>
11629
 
+                      </item>
11630
 
+                      <item row="4" column="0">
11631
 
+                       <widget class="QLabel" name="label_24">
11632
 
+                        <property name="text">
11633
 
+                         <string>Top margin</string>
11634
 
+                        </property>
11635
 
+                       </widget>
11636
 
+                      </item>
11637
 
+                      <item row="4" column="1">
11638
 
+                       <widget class="QSpinBox" name="sbJOPageTop"/>
11639
 
+                      </item>
11640
 
+                      <item row="4" column="2">
11641
 
+                       <widget class="QLabel" name="label_28">
11642
 
+                        <property name="text">
11643
 
+                         <string>Points</string>
11644
 
+                        </property>
11645
 
+                       </widget>
11646
 
+                      </item>
11647
 
+                      <item row="4" column="3">
11648
 
+                       <widget class="QPushButton" name="btnJOResetPageTop">
11649
 
+                        <property name="text">
11650
 
+                         <string>Reset</string>
11651
 
+                        </property>
11652
 
+                       </widget>
11653
 
+                      </item>
11654
 
+                      <item row="5" column="0">
11655
 
+                       <widget class="QLabel" name="label_25">
11656
 
+                        <property name="text">
11657
 
+                         <string>Bottom margin</string>
11658
 
+                        </property>
11659
 
+                       </widget>
11660
 
+                      </item>
11661
 
+                      <item row="5" column="1">
11662
 
+                       <widget class="QSpinBox" name="sbJOPageBottom"/>
11663
 
+                      </item>
11664
 
+                      <item row="5" column="2">
11665
 
+                       <widget class="QLabel" name="label_29">
11666
 
+                        <property name="text">
11667
 
+                         <string>Points</string>
11668
 
+                        </property>
11669
 
+                       </widget>
11670
 
+                      </item>
11671
 
+                      <item row="5" column="3">
11672
 
+                       <widget class="QPushButton" name="btnJOResetPageBottom">
11673
 
+                        <property name="text">
11674
 
+                         <string>Reset</string>
11675
 
+                        </property>
11676
 
+                       </widget>
11677
 
+                      </item>
11678
 
+                      <item row="6" column="0" colspan="2">
11679
 
+                       <layout class="QGridLayout" name="gridLayout_14">
11680
 
+                        <item row="0" column="0" colspan="2">
11681
 
+                         <widget class="QCheckBox" name="cbJOPrettyPrint">
11682
 
+                          <property name="text">
11683
 
+                           <string>Pretty print</string>
11684
 
+                          </property>
11685
 
+                         </widget>
11686
 
+                        </item>
11687
 
+                        <item row="0" column="2">
11688
 
+                         <widget class="QPushButton" name="btnJOResetPrettyPrint">
11689
 
+                          <property name="text">
11690
 
+                           <string>Reset</string>
11691
 
+                          </property>
11692
 
+                         </widget>
11693
 
+                        </item>
11694
 
+                        <item row="1" column="0" colspan="2">
11695
 
+                         <widget class="QCheckBox" name="cbJOWrap">
11696
 
+                          <property name="text">
11697
 
+                           <string>Word wrap</string>
11698
 
+                          </property>
11699
 
+                         </widget>
11700
 
+                        </item>
11701
 
+                        <item row="1" column="2">
11702
 
+                         <widget class="QPushButton" name="btnJOResetWrap">
11703
 
+                          <property name="text">
11704
 
+                           <string>Reset</string>
11705
 
+                          </property>
11706
 
+                         </widget>
11707
 
+                        </item>
11708
 
+                        <item row="2" column="0">
11709
 
+                         <widget class="QLabel" name="label_36">
11710
 
+                          <property name="text">
11711
 
+                           <string>Columns</string>
11712
 
+                          </property>
11713
 
+                         </widget>
11714
 
+                        </item>
11715
 
+                        <item row="2" column="1">
11716
 
+                         <widget class="QSpinBox" name="sbJOColumns"/>
11717
 
+                        </item>
11718
 
+                        <item row="2" column="2">
11719
 
+                         <widget class="QPushButton" name="btnJOResetColumns">
11720
 
+                          <property name="text">
11721
 
+                           <string>Reset</string>
11722
 
+                          </property>
11723
 
+                         </widget>
11724
 
+                        </item>
11725
 
+                       </layout>
11726
 
+                      </item>
11727
 
+                     </layout>
11728
 
+                    </item>
11729
 
+                    <item>
11730
 
+                     <widget class="QLabel" name="label_45">
11731
 
+                      <property name="text">
11732
 
+                       <string/>
11733
 
+                      </property>
11734
 
+                     </widget>
11735
 
+                    </item>
11736
 
+                    <item>
11737
 
+                     <widget class="QWidget" name="tblJOOtherWidget" native="true">
11738
 
+                      <layout class="QGridLayout" name="gridLayout_12">
11739
 
+                       <item row="0" column="0">
11740
 
+                        <layout class="QGridLayout" name="tblJOOther"/>
11741
 
+                       </item>
11742
 
+                      </layout>
11743
 
+                     </widget>
11744
 
+                    </item>
11745
 
+                    <item>
11746
 
+                     <widget class="QLabel" name="label_46">
11747
 
+                      <property name="text">
11748
 
+                       <string>To add a new option, enter its name in the box below and click to add.</string>
11749
 
+                      </property>
11750
 
+                     </widget>
11751
 
+                    </item>
11752
 
+                    <item>
11753
 
+                     <layout class="QHBoxLayout" name="horizontalLayout_2">
11754
 
+                      <item>
11755
 
+                       <widget class="QLineEdit" name="entNewJobOption"/>
11756
 
+                      </item>
11757
 
+                      <item>
11758
 
+                       <widget class="QPushButton" name="btnNewJobOption">
11759
 
+                        <property name="text">
11760
 
+                         <string>Add</string>
11761
 
+                        </property>
11762
 
+                       </widget>
11763
 
+                      </item>
11764
 
+                      <item>
11765
 
+                       <spacer name="horizontalSpacer_9">
11766
 
+                        <property name="orientation">
11767
 
+                         <enum>Qt::Horizontal</enum>
11768
 
+                        </property>
11769
 
+                        <property name="sizeHint" stdset="0">
11770
 
+                         <size>
11771
 
+                          <width>40</width>
11772
 
+                          <height>20</height>
11773
 
+                         </size>
11774
 
+                        </property>
11775
 
+                       </spacer>
11776
 
+                      </item>
11777
 
+                     </layout>
11778
 
+                    </item>
11779
 
+                   </layout>
11780
 
+                  </widget>
11781
 
+                 </item>
11782
 
+                 <item>
11783
 
+                  <spacer name="horizontalSpacer_8">
11784
 
+                   <property name="orientation">
11785
 
+                    <enum>Qt::Horizontal</enum>
11786
 
+                   </property>
11787
 
+                   <property name="sizeHint" stdset="0">
11788
 
+                    <size>
11789
 
+                     <width>119</width>
11790
 
+                     <height>1018</height>
11791
 
+                    </size>
11792
 
+                   </property>
11793
 
+                  </spacer>
11794
 
+                 </item>
11795
 
+                </layout>
11796
 
+               </widget>
11797
 
+              </widget>
11798
 
+             </item>
11799
 
+            </layout>
11800
 
+           </widget>
11801
 
+          </widget>
11802
 
+         </item>
11803
 
+        </layout>
11804
 
        </item>
11805
 
       </layout>
11806
 
      </widget>
11807
 
-     <widget class="QWidget" name="page_4" />
11808
 
-    </widget>
11809
 
-   </item>
11810
 
-   <item row="1" column="1" >
11811
 
-    <widget class="QPushButton" name="btnConflict" >
11812
 
-     <property name="text" >
11813
 
-      <string/>
11814
 
-     </property>
11815
 
-    </widget>
11816
 
-   </item>
11817
 
-   <item row="1" column="2" >
11818
 
-    <widget class="QPushButton" name="btnPrinterPropertiesApply" >
11819
 
-     <property name="text" >
11820
 
-      <string>Apply</string>
11821
 
-     </property>
11822
 
-    </widget>
11823
 
-   </item>
11824
 
-   <item row="1" column="3" >
11825
 
-    <widget class="QPushButton" name="btnRevert" >
11826
 
-     <property name="text" >
11827
 
-      <string>Revert</string>
11828
 
-     </property>
11829
 
+     <widget class="QWidget" name="page_4"/>
11830
 
     </widget>
11831
 
    </item>
11832
 
   </layout>
11833
 
  </widget>
11834
 
+ <customwidgets>
11835
 
+  <customwidget>
11836
 
+   <class>KComboBox</class>
11837
 
+   <extends>QComboBox</extends>
11838
 
+   <header>kcombobox.h</header>
11839
 
+  </customwidget>
11840
 
+  <customwidget>
11841
 
+   <class>KLineEdit</class>
11842
 
+   <extends>QLineEdit</extends>
11843
 
+   <header>klineedit.h</header>
11844
 
+  </customwidget>
11845
 
+  <customwidget>
11846
 
+   <class>KPushButton</class>
11847
 
+   <extends>QPushButton</extends>
11848
 
+   <header>kpushbutton.h</header>
11849
 
+  </customwidget>
11850
 
+ </customwidgets>
11851
 
  <resources/>
11852
 
  <connections/>
11853
 
 </ui>