diff --git a/DrPrintBackend.py b/DrPrintBackend.py
index 867396e..c1cedbf 100644
--- a/DrPrintBackend.py
+++ b/DrPrintBackend.py
@@ -1,7 +1,7 @@
## Some useful function to help DrPrint to
# -*- coding: utf-8 -*-
-import paramiko, gobject, select, time
+import paramiko, gobject, select, time, re
class PrintingError(Exception):
@@ -11,13 +11,51 @@ class PrintingError(Exception):
def __str__(self):
return repr(self.value)
+
class Backend(gobject.GObject):
def __init__(self):
super(Backend, self).__init__()
+ def get_queue(self, printer, remote_host, username, password):
- def send_print(self, printer, username, password, page_per_page, filename, page_range, copies, orientation, sides):
+ try:
+ client = paramiko.SSHClient()
+ client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ except:
+ raise RuntimeError('Impossibile inizializzare paramiko')
+
+ try:
+ client.connect(remote_host,
+ port = 22,
+ username = username,
+ password = password)
+ except:
+ raise RuntimeError('Impossibile connettersi a %s' % remote_host)
+
+ stdin, stdout, stderr = client.exec_command("lpq -P%s" % printer)
+ output = stdout.read()
+
+ # Parse output
+ jobs = []
+ for line in re.findall(r"(\d+)\w*\s+(\w+)\s+(\d+)\s+(.+)\s+(\d+) bytes",
+ output):
+ job = {
+ 'position': int(line[0]),
+ 'user': line[1],
+ 'id': line[2],
+ 'filename': line[3].strip(),
+ 'size': line[4]
+ }
+ jobs.append(job)
+ return jobs
+
+
+
+
+ def send_print(self, printer, username, password, page_per_page,
+ filename, page_range, copies, orientation, sides, remote_host):
+
# Get printer name
print "Selected printer: %s" % printer
@@ -29,7 +67,7 @@ class Backend(gobject.GObject):
raise PrintingError('Impossibili inizializzare paramiko')
try:
- client.connect('ssh.dm.unipi.it',
+ client.connect(remote_host,
port=22,
username=username,
password=password)
diff --git a/DrPrintGui/Dialogs.py b/DrPrintGui/Dialogs.py
index d37ea98..cf4f352 100644
--- a/DrPrintGui/Dialogs.py
+++ b/DrPrintGui/Dialogs.py
@@ -23,6 +23,28 @@ class ErrorDialog(Dialog):
self.set_markup(error)
self.format_secondary_markup(message)
+class QueueDialog(Dialog):
+
+ def __init__(self, jobs, printer):
+
+ Dialog.__init__(self,
+ buttons = gtk.BUTTONS_OK,
+ mtype = gtk.MESSAGE_INFO
+ )
+
+ if len(jobs) == 0:
+ self.set_markup("Non ci sono lavori in coda su <b>%s</b>." % printer)
+ else:
+ self.set_markup("Ci sono %d lavori in coda su <b>%s</b>:" % (len(jobs), printer))
+
+ # Lista dei lavori
+ markup = ""
+ for job in jobs:
+ markup += "%d) <b>%s</b> sta stampando <b>%s</b>\n" % (job['position'], job['user'],
+ job['filename'])
+ self.format_secondary_markup (markup)
+
+
class InfoDialog(Dialog):
def __init__(self, error, message):
diff --git a/DrPrintGui/Input.py b/DrPrintGui/Input.py
index 96954b9..c579573 100644
--- a/DrPrintGui/Input.py
+++ b/DrPrintGui/Input.py
@@ -39,8 +39,8 @@ class UsernameField(gtk.Entry):
if user is None:
self.set_text( os.getenv("USER") )
else:
- self.set_text(user)
-
+ self.set_text(user)
+
class PasswordField(gtk.Entry):
@@ -51,9 +51,26 @@ class PasswordField(gtk.Entry):
self.set_text ("")
self.set_visibility(False)
+class RemoteHostComboBox(gtk.HBox):
+
+ def __init__(self, default_hosts):
+
+ gtk.HBox.__init__(self)
+ self.combobox = gtk.combo_box_new_text()
+ for remote_host in default_hosts:
+ self.combobox.append_text(remote_host)
+ # Selezioniamo il primo host
+ self.combobox.set_active(0)
+
+ self.pack_start(self.combobox)
+ self.combobox.show()
+ def get_remote_host(self):
+ return self.combobox.get_active_text()
+
class AuthBlock(gtk.HBox):
- def __init__(self, default_spacing=5, left_padding=0, user = None):
+ def __init__(self, default_spacing=5, left_padding=0, user = None,
+ default_hosts = ['ssh.dm.unipi.it']):
gtk.HBox.__init__(self)
@@ -63,6 +80,17 @@ class AuthBlock(gtk.HBox):
vbox1 = gtk.VBox()
vbox2 = gtk.VBox()
+ label = LeftAlignedLabel("Server SSH", 20)
+ vbox1.pack_start (label)
+ label.show ()
+
+ if len(default_hosts) == 0:
+ raise IndexError('Not remote hosts specified. Aborting')
+
+ self.remote_host = RemoteHostComboBox(default_hosts)
+ vbox2.pack_start(self.remote_host)
+ self.remote_host.show()
+
label = LeftAlignedLabel("Utente", 20)
vbox1.pack_start( label )
label.show()
@@ -89,6 +117,9 @@ class AuthBlock(gtk.HBox):
def get_password(self):
return self.password_field.get_text()
+ def get_remote_host(self):
+ return self.remote_host.get_remote_host()
+
class PrintButton(gtk.Button):
def __init__(self, parent=None):
@@ -107,6 +138,21 @@ class PrintButton(gtk.Button):
else:
raise RuntimeError('Invalid state %s' % state)
+class QueueButton(gtk.Button):
+
+ def __init__(self):
+ gtk.Button.__init__(self, "Visualizza coda")
+
+ def set_state(self, state):
+ if state is "idle":
+ self.set_label("Visualizza coda")
+ else:
+ self.set_label("Recupero coda in corso...")
+ while gtk.events_pending():
+ gtk.main_iteration (False)
+
+
+
class SelectFileWidget(gtk.HBox):
@@ -149,17 +195,14 @@ file .ps da selezionare qui")
class PrinterComboBox(gtk.HBox):
- def __init__(self):
+ def __init__(self, printers = []):
gtk.HBox.__init__(self)
self.combobox = gtk.combo_box_new_text()
- self.combobox.append_text("cdc7")
- self.combobox.append_text("cdcpt")
- self.combobox.append_text("cdc8")
- self.combobox.append_text("cdc4")
- self.combobox.append_text("cdc9")
+ for printer in printers:
+ self.combobox.append_text(printer)
- self.combobox.set_active(1)
+ self.combobox.set_active(0)
self.pack_start( self.combobox )
self.combobox.show()
@@ -187,7 +230,7 @@ class PagePerPageComboBox(gtk.HBox):
class PrinterSettingsBlock(gtk.HBox):
- def __init__(self, default_spacing = 5, left_padding=0, filename = None):
+ def __init__(self, default_spacing = 5, left_padding=0, filename = None, printers = []):
gtk.HBox.__init__(self)
@@ -200,7 +243,7 @@ class PrinterSettingsBlock(gtk.HBox):
vbox1.pack_start(label)
label.show()
- self.printer_chooser = PrinterComboBox()
+ self.printer_chooser = PrinterComboBox(printers = printers)
vbox2.pack_start( self.printer_chooser )
self.printer_chooser.show()
diff --git a/DrPrintGui/MainWin.py b/DrPrintGui/MainWin.py
index b36173d..2c86991 100644
--- a/DrPrintGui/MainWin.py
+++ b/DrPrintGui/MainWin.py
@@ -11,8 +11,9 @@ import gtk, pygtk
import os
import sys
-from Input import AuthBlock, PrinterSettingsBlock, PrintButton, LeftAlignedLabel, PageRangeBlock, OrientationSelect, SidesSelect
-from Dialogs import ErrorDialog, MessageDialog, InfoDialog
+from Input import AuthBlock, PrinterSettingsBlock, PrintButton, LeftAlignedLabel, \
+ PageRangeBlock, OrientationSelect, SidesSelect, QueueButton
+from Dialogs import ErrorDialog, MessageDialog, InfoDialog, QueueDialog
from DrPrintBackend import PrintingError
class MainWin(gtk.Window):
@@ -75,11 +76,14 @@ class MainWin(gtk.Window):
layout_box.pack_start(hbox, 20)
+
label = LeftAlignedLabel("<b>Autenticazione (sui computer dell'Aula 4)</b>")
layout_box.pack_start( label )
label.show()
- self.auth_block = AuthBlock(self.default_spacing, 10, user = self.user)
+ hosts = ['ssh.dm.unipi.it', 'ssh1.dm.unipi.it', 'ssh2.dm.unipi.it']
+ self.auth_block = AuthBlock(self.default_spacing, 10, user = self.user,
+ default_hosts = hosts)
layout_box.pack_start ( self.auth_block )
self.auth_block.show()
@@ -88,8 +92,18 @@ class MainWin(gtk.Window):
layout_box.pack_start(label)
label.show()
+ # Piano terra e secondo piano
+ printers = ['cdcpt', 'cdcpp']
+
+ # Le stampanti numerate
+ printers.extend(map(lambda x : "cdc"+str(x), range(1,10)))
+
+ # Togliamo la cdc2 che sembra non esistere
+ printers.remove("cdc2")
+
self.printer_settings_block = PrinterSettingsBlock(self.default_spacing,
- filename = self.filename)
+ filename = self.filename,
+ printers = printers)
layout_box.pack_start(self.printer_settings_block)
self.printer_settings_block.show()
@@ -113,9 +127,19 @@ class MainWin(gtk.Window):
layout_box.pack_start(self.sides_select)
self.sides_select.show()
+ # Bottoni finali, omogenei :)
+ hbox = gtk.HBox(True)
+
+ self.queue_button = QueueButton()
+ hbox.pack_start(self.queue_button)
+ self.queue_button.show()
+
self.print_button = PrintButton()
- layout_box.pack_start(self.print_button)
+ hbox.pack_start(self.print_button)
self.print_button.show()
+
+ layout_box.pack_start(hbox)
+ hbox.show ()
self.add (layout_box)
@@ -123,8 +147,29 @@ class MainWin(gtk.Window):
def connect_all(self):
+ self.queue_button.connect('clicked', self.queue_button_clicked_callback)
self.print_button.connect('clicked', self.print_button_clicked_callback)
+ def queue_button_clicked_callback(self, widget):
+ self.queue_button.set_state("running")
+ printer = self.printer_settings_block.get_printer()
+ username = self.auth_block.get_username()
+ password = self.auth_block.get_password()
+ remote_host = self.auth_block.get_remote_host()
+ try:
+ jobs = self.backend.get_queue(printer, remote_host, username, password)
+ except RuntimeError, e:
+ dialog = ErrorDialog("<b>Errore di connessione</b>",
+ "Il seguente errore si è verificato durante il recupero della coda: %s" % e)
+ resp = dialog.run()
+ dialog.destroy()
+ self.queue_button.set_state("idle")
+ qd = QueueDialog(jobs, printer)
+ resp = qd.run()
+ qd.destroy()
+
+
+
def print_button_clicked_callback(self, widget):
if not self.backend == None:
@@ -140,6 +185,7 @@ class MainWin(gtk.Window):
copies = self.printer_settings_block.get_copies()
orientation = self.orientation_select.get_orientation()
sides = self.sides_select.get_sides_select()
+ remote_host = self.auth_block.get_remote_host ()
resp = gtk.RESPONSE_OK
@@ -167,7 +213,8 @@ Se vuoi continuare premi OK")
page_range = page_range,
copies = copies,
orientation=orientation,
- sides = sides)
+ sides = sides,
+ remote_host = remote_host)
except PrintingError, e:
# Comunichiamo il fallimento
dialog = ErrorDialog("<b>Errore di stampa</b>",
diff --git a/debian/changelog b/debian/changelog
index 3395b39..db48f50 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+drprint (0.9-0-rc1) lucid; urgency=low
+
+ * Prima implementazione della visualizzazione delle code di stampa
+
+ -- Leonardo Robol <leonardo@debby> Thu, 10 Jun 2010 17:49:08 +0200
+
drprint (0.8-5) jaunty; urgency=low
* Corrette dipendenze.