Autore: Fabio Di Matteo
Ultima revisione: 21/12/2018 - 10:48
#!/usr/bin/env python import gi gi.require_version('Gtk', '3.0') from gi.repository import GLib, Gtk import sys, subprocess, shlex, os import threading class MainWindow (Gtk.Builder): textView=None textbuffer = None def cmdThread(self,cmd): print("Comando: %s" % cmd) txtBuffer="" out="" fileOutErr = open("errors.txt","w") #Lo stdout lo leggo dalla pipe, gli errori li salvo in un file che leggero' dopo proc = subprocess.Popen(shlex.split(cmd), bufsize=0 ,stdout=subprocess.PIPE, stderr=fileOutErr) #leggo la pipe finchè non finisce(proc.poll() is None) while proc.poll() is None : out = proc.stdout.readline() txtBuffer=txtBuffer+str(out.decode("utf-8")) GLib.idle_add(MainWindow.textbuffer.set_text,txtBuffer) print(str(out.decode("utf-8"))) fileOutErr.close() #Stampo gli errori dopo la fine della pipe if (os.stat("errors.txt").st_size != 0): fileOutErr= open("errors.txt","r") listErr=fileOutErr.readlines() txtBuffer=txtBuffer+"\n\nErrori:\n------------------\n\n" for e in listErr: txtBuffer=txtBuffer+e #Aggiungo al text buffer gli errori presi dal file e chiudo il file GLib.idle_add(MainWindow.textbuffer.set_text,txtBuffer) fileOutErr.close() def on_button_clicked(self, textView,entry): cmdt = threading.Thread(target=MainWindow.cmdThread, args=(self,entry.get_text()),) cmdt.daemon = True cmdt.start() def quit(self,win): print ("Exit!") Gtk.main_quit(win) def __init__(self): self = Gtk.Builder() self.add_from_file("builder.ui") window = self.get_object("window") entry = self.get_object("entry") MainWindow.textView = self.get_object("textView") button = self.get_object("button") #Init MainWindow.textbuffer = MainWindow.textView.get_buffer() MainWindow.textbuffer.set_text("This is some text inside of a Gtk.TextView. " + "Select text and click one of the buttons 'bold', 'italic', " + "or 'underline' to modify the text accordingly.") if (sys.platform == "win32"): entry.set_text("./rsync-win/rsync.exe -avz /cygdrive/c/msys64/mingw64/bin /cygdrive/c/users/admin/desktop/tt/") window.show_all() window.connect("delete-event", MainWindow.quit) button.connect("clicked", MainWindow.on_button_clicked, MainWindow.textView,entry) myWindow = MainWindow() Gtk.main()
builder.ui
<?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.22.1 --> <interface> <requires lib="gtk+" version="3.18"/> <object class="GtkWindow" id="window"> <property name="visible">True</property> <property name="can_focus">False</property> <signal name="delete-event" handler="quit" swapped="no"/> <child type="titlebar"> <placeholder/> </child> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkEntry" id="entry"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="text" translatable="yes">rsync -avz /usr/bin/ /home/fabio/Desktop/tt/</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkButton" id="button"> <property name="label" translatable="yes">button</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="can_default">True</property> <property name="has_default">True</property> <property name="receives_default">True</property> <signal name="clicked" handler="on_button_clicked" object="label" swapped="no"/> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <placeholder/> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <property name="min_content_width">400</property> <property name="min_content_height">300</property> <property name="propagate_natural_width">True</property> <property name="propagate_natural_height">True</property> <child> <object class="GtkTextView" id="textView"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="wrap_mode">char</property> </object> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">2</property> </packing> </child> </object> </child> </object> </interface>
Per questo esperimento useremo l'opzione di rsync –info=progress2
get-rsync-progress.py
#!/usr/bin/env python import gi gi.require_version('Gtk', '3.0') from gi.repository import GLib, Gtk import sys, subprocess, shlex, os import threading class MainWindow (Gtk.Builder): textView=None textbuffer = None progressBar=None def getPercent(line): # Example 11,131,595 1% 10.47MB/s 0:00:00 (xfr#16, to-chk=2761/4538) # Splitto la corrente riga dello stdout su una lista con separatore lo spazio line=line.split(" ") # Se uno degli elementi della lista contiene un simbolo di percentuale (%) # allora ritorno solo l'intero (sotto forma di stringa) ,sia esso formato # da 1,2 o tre cifre for l in line: if ('%' in l): if (len(l)==2): return l[0] if (len(l)==3): return l[0]+l[1] if (len(l)==4): return l[0]+l[1]+l[2] def cmdThread(self,cmd): print("Comando: %s" % cmd) txtBuffer="" out="" fileOutErr = open("errors.txt","w") # Lo stdout lo leggo dalla pipe, gli errori li salvo in un file che leggero' dopo proc = subprocess.Popen(shlex.split(cmd), bufsize=0 ,stdout=subprocess.PIPE, stderr=fileOutErr) # leggo la pipe finchè non finisce(proc.poll() is None) while proc.poll() is None : out = proc.stdout.readline() txtBuffer=txtBuffer+str(out.decode("utf-8")) GLib.idle_add(MainWindow.textbuffer.set_text,txtBuffer) # Faccio il parsing della percentuale di progresso e aggiorno la gtkProgressbar # dal metodo MainWindow.getPercent ricevo una stringa del genere "50","10". etc... if (MainWindow.getPercent(str(out.decode("utf-8"))) is not None): p=float(MainWindow.getPercent(str(out.decode("utf-8"))))/100 GLib.idle_add(MainWindow.progressBar.set_fraction,p) fileOutErr.close() GLib.idle_add(MainWindow.progressBar.set_fraction,1.0) #Stampo gli errori dopo la fine della pipe if (os.stat("errors.txt").st_size != 0): fileOutErr= open("errors.txt","r") listErr=fileOutErr.readlines() txtBuffer=txtBuffer+"\n\nErrori:\n------------------\n\n" for e in listErr: txtBuffer=txtBuffer+e #Aggiungo al text buffer gli errori presi dal file e chiudo il file GLib.idle_add(MainWindow.textbuffer.set_text,txtBuffer) fileOutErr.close() def on_button_clicked(self, textView,entry): cmdt = threading.Thread(target=MainWindow.cmdThread, args=(self,entry.get_text()),) cmdt.daemon = True cmdt.start() def quit(self,win): print ("Exit!") Gtk.main_quit(win) def __init__(self): self = Gtk.Builder() self.add_from_file("builder.ui") window = self.get_object("window") entry = self.get_object("entry") MainWindow.textView = self.get_object("textView") button = self.get_object("button") MainWindow.progressBar=self.get_object("progressBar") #Init MainWindow.textbuffer = MainWindow.textView.get_buffer() MainWindow.textbuffer.set_text("testo libero") if (sys.platform == "win32"): entry.set_text("./rsync-win/rsync.exe --info=progress2 -avz /cygdrive/c/msys64/mingw64/bin /cygdrive/c/users/admin/desktop/tt/") window.show_all() window.connect("delete-event", MainWindow.quit) button.connect("clicked", MainWindow.on_button_clicked, MainWindow.textView,entry) myWindow = MainWindow() Gtk.main()
builder.ui
<?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.22.1 --> <interface> <requires lib="gtk+" version="3.18"/> <object class="GtkWindow" id="window"> <property name="width_request">700</property> <property name="visible">True</property> <property name="can_focus">False</property> <signal name="delete-event" handler="quit" swapped="no"/> <child type="titlebar"> <placeholder/> </child> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkEntry" id="entry"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="text" translatable="yes">rsync --info=progress2 -avz /usr/share/applications/ /home/fabio/Desktop/tt/</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkButton" id="button"> <property name="label" translatable="yes">button</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="can_default">True</property> <property name="has_default">True</property> <property name="receives_default">True</property> <signal name="clicked" handler="on_button_clicked" object="label" swapped="no"/> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkProgressBar" id="progressBar"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="show_text">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">2</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkScrolledWindow" id="scrolledWindow"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <property name="min_content_width">400</property> <property name="min_content_height">300</property> <property name="propagate_natural_width">True</property> <property name="propagate_natural_height">True</property> <child> <object class="GtkTextView" id="textView"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="wrap_mode">char</property> </object> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">2</property> </packing> </child> </object> </child> </object> </interface>