14 may. 2011

GtkBuilder y Python 8

Si estas mirando esta entrada, es buena idea que revises las anteriores.

En este nueva entrada vamos a trabajar sobre el dialogo de guardar, vamos a refinarlo y vamos dejarlo listo para configurar los últimos elementos de la interfaz, lo demás sera refinar el código en algunas partes.
Voy entonces a explicar cada uno de los elementos del codigo.
Las lineas 3, 4, 5, 6 Básicamente están definiendo un formato de archivo a guardar, este caso el formato tiene como nombre Lista Multimedia y la extensión es pls que es básicamente una extensión que programas como Banshee y Totem usan para contenido multimedia diverso.

Como en el caso de los diálogos de abrir y seleccionar carpeta si la respuesta es afirmativa (-5) lo primero que tenemos que hacer es obtener el nombre que el usuario le ponga a la lista, esto se hace con la linea 12 usando el comando .get_filename().
La linea 13 es particularmente importante porque se utiliza para crear cualquier tipo de archivos, ya sea de texto, lista de música, base de datos y todo lo que se puedan imaginar, el comando open(filename + ".pls", w) lo que hace es crear un archivo con el nombre que se obtenga de la variable filename y lo terminara con la extensión .pls, la letra W quiere decir Write lo que significa que le damos permiso a este archivo de escribir.
La linea 14 le va a poner un header o titulo al archivo que hemos creado, el formato pls siempre tiene un titulo en corchetes con el nombre playlist y el valor que le sigue es básicamente es igual a dar un enter dentro del archivo.

#Definicion del comando Guardar Permite guardar una lista def showSave(self, widget): self.filterbox.set_name("Lista Multimedia") self.filterbox.add_pattern("*.pls") self.save.add_filter(self.filterbox) respt = self.save.run() self.save.remove_filter(self.filterbox) self.save.hide() if respt == -5: n = 0 filename = self.save.get_filename() playlistsaved = open(filename + '.pls', 'w') playlistsaved.write("[playlist]" + "\n") iter=self.medialist.get_iter_first() while iter: n+=1 rutas = self.medialist.get_value(iter,1) archivoss = self.medialist.get_value(iter,0) allmusicfiles = rutas+"/"+archivos pathname = urllib.pathname2url(os.path.abspath(allmusicfiles)) playlistsaved.write("File"+str(n)+"=file://"+pathname.encode('utf-8') + "\n") iter = self.medialist.iter_next(iter)


En la linea 16 vamos a crear un iter de la medialist y vamos iterar por cada uno de los elementos de la lista y vamos a obtener de esta la columna 0 y 1, para crear un listado completo de los archivos con nombre y ruta.

En la linea 23 vamos a transformar todos las rutas a Uris. Yo se alguien me puede preguntar porque vamos a hacer esta transformación y porque en vez de hacer esto no usamos desde el principio get_uris() en vez de get_filenames(), voy a explicar con un ejemplo y dare la respuesta con el ejemplo.

Ejemplo:
El resultado del comando get_filenames() es este: /home/geojorg/Música/Pink/Pink - Just Like a Pill.mp3
El resultado del comando get_uris() es: file:///home/geojorg/M%C3%BAsica/Pink/Pink%20%26%20-Just%20Like%20a%20Pill.mp3

Ambos resultados son archivos y ambos son validos en todo el sentido de la palabra, el problema de trabajar con Uris es que toca hacerles una pequeña transformación antes de poder usarlos, lo primero seria eliminar file:// y pasar el resto del  nombre a utf8 y para exportarlos nuevamente toca transformarlos. Por recomendación la mayoría de las personas que saben del tema recomiendan trabajar con Uris, pero yo tengo una aproximación distinta y voy a dar la explicación. Yo siempre prefiero agregar código a quitar código, cuando uno ve un código por primera vez es muy difícil quitar cosas. Si quitas algo puedes dañar lo demás y se vuelve un lió.

Con agregar la linea 23 convertimos el nombre de los archivos a Uris, esto se hace con dos comandos.
os.path.abspath() Este convierte cualquier ruta a un archivo en un elemento absoluto que este ligado desde la raiz / o c: si se trabaja en windows.
urllib.pathname2url() es un comando que convierte cualquier /home/geojorg en file:///home/geojorg es decir de pathname a url, para ello tenemos que importar el modulo urllib de python con el comando

import urllib

Finalmente la linea 24 guarda un vinculo a un archivo de la siguiente forma, n es un valor iterativo numérico que se usa en este formato de archivo .pls

File1=file:///home/geojorg/M%C3%BAsica/Pink/Pink%20%26%20-Just%20Like%20a%20Pill.mp3

La linea 25 lo que hace es iterar al siguiente elemento y termina cuando ya no hay mas elementos porque todos estos están dentro de un while, pueden guardar alguna lista y usar totem para reproducir lo que acaban de guardar y verán que funciona perfectamente.

En la próxima entrada vamos a configurar los botones de play, stop y cerrar.

El código final es el siguiente:
#!/usr/bin/python import os from gi.repository import Gtk from random import shuffle import urllib filepattern = ( ("MP3","*.mp3"), ("AVI","*.avi"), ("MPEG-4","*.mp4"), ("FLV ","*.flv"), ("OGG","*.ogg"), ) pattern = (".mp3",".mp4",".avi",".flv",".ogg") class main: def __init__(self): # Crea la ventana de trabajo Principal y obtiene los objetos en Glade builder = Gtk.Builder() builder.add_from_file("Multiplay.ui") self.addfile = builder.get_object("Add") self.addfolder = builder.get_object("AddFolder") self.save = builder.get_object("Save") self.about = builder.get_object("About") self.medialist = builder.get_object("MediaList") self.combolist = builder.get_object("combobox1") self.treeview = builder.get_object("TextView") self.up = builder.get_object("Up") self.down = builder.get_object("Down") self.filterbox = Gtk.FileFilter() # Diccionario de eventos y Conexion de los mismos. dict = {"on_Add_clicked": self.showAddFile, "on_AddFolder_clicked": self.showAddFolder, "on_Saved_clicked": self.showSave, "on_About_clicked": self.showAbout, "on_Clearone_clicked": self.clearone, "on_Clearlist_clicked": self.clearlist, "on_Up_clicked": self.updown_move, "on_Down_clicked": self.updown_move, "on_ComboOrder_changed": self.newList, } builder.connect_signals(dict) #Definicion del comando Agregar def showAddFile(self, widget): self.filterbox.set_name("Media Files") for name, pattern in filepattern: self.filterbox.add_pattern(pattern) self.addfile.add_filter(self.filterbox) respt = self.addfile.run() self.addfile.remove_filter(self.filterbox) self.addfile.hide() if respt == -5: fileselected = self.addfile.get_filenames() for files in fileselected: (dirs,files)= os.path.split(files) self.medialist.append([files,dirs]) #Definicion del comando Abrir Carpeta def showAddFolder(self, widget): self.filterbox.set_name("All Media Files") for names, patterns in filepattern: self.filterbox.add_pattern(patterns) self.addfolder.add_filter(self.filterbox) respt = self.addfolder.run() self.addfolder.remove_filter(self.filterbox) self.addfolder.hide() if respt == -5: addmultiple = self.addfolder.get_filename() for root, dirs, filelist in os.walk(addmultiple): for allfiles in [f for f in filelist if f.endswith(pattern)]: self.medialist.append([allfiles,root]) #Definicion del comando Borrar un Archivo def clearone(self, *args): clearone = self.treeview.get_selection() (model, rows) = clearone.get_selected_rows() for i in rows: iteration=model.get_iter(i) print iteration self.medialist.remove(iteration) #Definicion del comando Borrar Lista def clearlist(self, *args): self.medialist.clear() #Definicion del comando Arriba y Abajo def updown_move(self, button): line = self.treeview.get_selection() (model, rows) = line.get_selected_rows() if button == self.up: for path1 in rows: path2 = int(str(path1))-1 if path2 < 0: return else: iter1 = model.get_iter(path1) iter2 = model.get_iter(path2) model.swap(iter1,iter2) if button == self.down: for path1 in rows: iter1 = model.get_iter(path1) iter2 = model.iter_next(iter1) if iter2 == None: return else: model.swap(iter1,iter2) #Definicion para ordernar la lista def newList(self, widget): var = self.combolist.get_active() #Si se activa Aleatorio if var == 0: n = 0 for musicfiles in self.medialist: n += 1 index = range(0, n) shuffle(index) #Reorganiza la lista de musica llamad medialist if len(index) > 1: self.medialist.reorder(index) #Si se activa Alfabetico if var == 1: iter=self.medialist.get_iter_first() newlistfiles = [] while iter: files = self.medialist.get_value(iter,0) source = self.medialist.get_value(iter,1) newlistfiles.append([files,source]) iter = self.medialist.iter_next(iter) newlistfiles = sorted(newlistfiles) self.medialist.clear() for files,source in newlistfiles: self.medialist.append([files,source]) #Definicion del comando Guardar Permite guardar una lista def showSave(self, widget): self.filterbox.set_name("Lista Multimedia") self.filterbox.add_pattern("*.pls") self.save.add_filter(self.filterbox) respt = self.save.run() self.save.remove_filter(self.filterbox) self.save.hide() if respt == -5: n = 0 filename = self.save.get_filename() playlistsaved = open(filename + '.pls', 'w') playlistsaved.write("[playlist]" + "\n") iter=self.medialist.get_iter_first() while iter: n+=1 rutas = self.medialist.get_value(iter,1) archivos = self.medialist.get_value(iter,0) allmusicfiles = rutas+"/"+archivos pathname = urllib.pathname2url(os.path.abspath(allmusicfiles)) playlistsaved.write("File"+str(n)+"=file://"+pathname.encode('utf-8') + "\n") iter = self.medialist.iter_next(iter) #Definicion del Comando Acerca de: def showAbout(self, widget, data=None): self.about.run() self.about.hide() #Ejecucion del programa if __name__ == "__main__": main() Gtk.main()

2 comentarios:

  1. Muy bueno el tuto.
    Sería mucho pedirlo en pdf? (todas las partes)

    ResponderEliminar
  2. Claro que no, lo organizo con el ultimo tuto que quedo faltando jejeje. Lo publico pronto.

    ResponderEliminar