Nuova versione (bump a 0.9) , release candidate per la

Leonardo [2010-06-10 15:50]
Nuova versione (bump a 0.9) , release candidate per la
gestione delle code di stampa.
Filename
DrPrintBackend.py
DrPrintGui/Dialogs.py
DrPrintGui/Input.py
DrPrintGui/MainWin.py
debian/changelog
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.
ViewGit