Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre pyqt (publicaciones antiguas, página 11)

Charla: aplicaciones extensibles con PyQt

Span­ish on­ly, since it's about a video in span­ish ;-)

Acá es­tá, gra­cias a la gente de Junín, un video de mi char­la "Apli­ca­ciones ex­ten­si­bles us­an­do PyQt", en la que in­ten­to mostrar co­mo de­sar­rol­lar una apli­cación con PyQt y yap­sy.

No es una char­la con la que es­té muy con­tento. La otra sal­ió mejor, pero no se filmó, así que quedará so­lo en la memo­ria de los cu­a­tro gatos lo­cos que es­tábamos ahí ;-)

El resto de las char­las: http://un­no­ba.blip.tv/

Modularizando tu aplicación: Yapsy

Una ma­ne­ra (si es­tás pro­gra­man­do en Py­tho­n) es usar Yap­sy..

Yap­sy es asom­bro­so. Tam­bién, ca­re­ce com­ple­ta­men­te de do­cu­men­ta­ción en­ten­di­ble. Vea­mos si es­te post arre­gla un po­co esa par­te y de­ja só­lo lo asom­bro­so.

Up­da­te: No ha­bía vis­to la do­cu­men­ta­ción nue­va de Yap­s­y. Es mu­cho me­jor que la que ha­bía an­tes :-)

Es­ta es la idea ge­ne­ral con yap­s­y:

  • Creás un Plu­­gin Ma­­na­­ger que pue­­de en­­co­n­­trar y ca­r­­gar plu­­gins de una lis­­ta de lu­­ga­­res (por eje­m­­plo, de ["/us­­r/s­ha­­re/a­­pp­­na­­me/­­plu­­gi­n­s", "~/.a­­pp­­na­­me/­­plu­­gi­n­s"]).

  • Una ca­­te­­go­­­ría de plu­­gins es una cla­­se.

  • Hay un ma­­peo en­­tre no­m­­bres de ca­­te­­go­­­ría y cla­­ses de ca­­te­­go­­­ría.

  • Un plu­­gin es un mó­­­du­­lo y un ar­­chi­­vo de me­­ta­­da­­ta. El mó­­­du­­lo de­­fi­­ne una cla­­se que he­­re­­da de una cla­­se de ca­­te­­go­­­ría, y pe­r­­te­­ne­­ce a esa ca­­te­­go­­­ría.

    El ar­­chi­­vo de me­­ta­­da­­ta tie­­ne co­­sas co­­­mo el no­m­­bre del plu­­gi­n, la des­­cri­p­­ció­­n, la UR­­L, ve­r­­sió­­n, etc.

Una de las me­jo­res co­sas de Yap­sy es que no es­pe­ci­fi­ca de­ma­sia­do. Un plu­gin va a ser sim­ple­men­te un ob­je­to Py­tho­n, po­dés po­ner lo que quie­ras ahí, o lo po­dés li­mi­tar de­fi­nien­do la inte­faz en la cla­se de ca­te­go­ría.

De he­cho, lo que ven­go ha­cien­do con las cla­ses de ca­te­go­ría es:

  • Arran­­co con una cla­­se va­­cía

  • Im­­ple­­men­­to dos plu­­gins de esa ca­­te­­go­­­ría

  • Los pe­­da­­zos en co­­­mún los mue­­vo den­­tro de la ca­­te­­go­­­ría.

Pe­ro créan­me, es­to va a ser mu­cho más cla­ro con un ejem­plo :-)

Lo voy a ha­cer con una apli­ca­ción grá­fi­ca en Py­Q­t, pe­ro Yap­sy fun­cio­na igual de bien pa­ra apli­ca­cio­nes "head­le­ss" o pa­ra lí­neas de co­man­do.

Co­men­ce­mos con al­go sim­ple: un edi­tor HT­ML con un wi­dget pre­view.

//ralsina.me/static/yapsy/editor1.jpeg

Un edi­tor sim­ple con pre­view

Es­te es el có­di­go de la apli­ca­ció­n, que es real­men­te sim­ple (no pue­de guar­dar ar­chi­vos ni na­da in­te­re­san­te, es só­lo un ejem­plo­):

Pe­ro es­ta apli­ca­ción tie­ne un ob­vio lí­mi­te: hay que es­cri­bir HT­M­L! Por qué no es­cri­bir py­thon y que lo mues­tre re­sal­ta­do en HT­M­L? O ma­rkup de Wiki! O reS­truc­tu­red tex­t!

Uno po­dría, en prin­ci­pio, im­ple­men­tar to­dos esos mo­do­s, pe­ro es­tás asu­mien­do la res­pon­sa­bi­li­dad de so­por­tar ca­da co­sa-­que-se-­con­vier­te-en-HT­M­L. Tu apli­ca­ción se­ría un mo­n­oli­to. Ahí en­tra Yap­s­y.

Cree­mos en­ton­ces una ca­te­go­ría de plu­gin­s, lla­ma­da "For­ma­tte­r" que to­ma tex­to pla­no y de­vuel­ve HT­M­L. Des­pués agre­gue­mos co­sas en la UI pa­ra que el usua­rio pue­da ele­gir que for­ma­tter usar, e im­ple­men­te­mos un pa­r.

Es­ta es la cla­se de ca­te­go­ría de plu­gin­s:

Por su­pues­to que no sir­ve de na­da sin plu­gin­s! Asi que cree­mos un pa­r.

Pri­me­ro, un plu­gin qye to­ma có­di­go py­thon y de­vuel­ve HT­M­L, usan­do pyg­men­ts.

Co­mo ven, eso va en una car­pe­ta plu­gin­s. Des­pués le de­ci­mos a Yap­sy que bus­que los plu­gins ahi aden­tro.

Pa­ra ser re­co­no­ci­do co­mo un plu­gi­n, ne­ce­si­ta me­ta­da­ta:

Y real­men­te, eso es to­do lo que hay que ha­cer pa­ra ha­cer un plu­gi­n. Acá hay otro pa­ra com­pa­ra­r, que usa do­cu­tils pa­ra for­ma­tear reS­truc­tu­red Tex­t:

Y acá es­tán en ac­ció­n:

//ralsina.me/static/yapsy/editor2.jpeg

reSt mo­de

//ralsina.me/static/yapsy/editor3.jpeg

Py­thon mo­de

Of cour­se using ca­te­go­ries you can do things like a "Tool­s" ca­te­go­r­y, whe­re the plu­gins get added to a Tools me­nu, too.

Es­te es el có­di­go del la­do de la apli­ca­ció­n:

Re­su­mien­do: es fá­ci­l, y te lle­va a me­jo­rar la es­truc­tu­ra in­ter­na de tu apli­ca­ción y ter­mi­nás con me­jor có­di­go.

Có­di­go fuen­te de to­do.

eBooks y PyQt: una linda pareja

Pe­ro en­ton­ces pen­sé... se­rá di­fí­cil leer ePu­b? Bue­no, es re fá­ci­l!

Acá hay una ex­pli­ca­ción en sta­cko­ver­flo­w.­com <http://s­ta­cko­ver­flo­w.­co­m/­ques­tion­s/1388467/­rea­din­g-e­pu­b-­for­mat>`_ pe­ro la ver­sión cor­ta es... es un zip con XML aden­tro.

Uno de esos XML te di­ce adon­de es­tá ca­da co­sa, otro es el ín­di­ce, el res­to es una co­lec­ción de HT­M­L/­CSS/i­má­ge­nes.

En­ton­ce­s: es­tos son los in­gre­dien­tes pa­ra co­ci­nar­te un lec­tor ca­se­ro de ePub en 150 lí­nea­s:

  • Usá el mó­­­du­­lo zi­­pfi­­le pa­­ra no ex­­pan­­dir el zip (e­­so es be­­­rre­­ta)

  • Usá Ele­­ment Tree pa­­ra pa­r­­sear el XM­­L.

  • Usá QtWe­­bkit de Py­­Qt pa­­ra mo­s­­trar esa co­­­le­c­­ción de XM­­L/­­CSS/I­­ma­­ges

  • Usá es­­ta re­­ce­­ta pa­­ra que QtWe­­bkit te avi­­se que quie­­re al­­go del zi­­p.

En­chu­fá una co­sa con otra, sa­cu­dí, y ter­mi­nás con es­to:

Share photos on twitter with Twitpic

Acá es­tá el có­di­go (has­ta aho­ra) <http://­co­de.­google.­co­m/­p/a­ran­duka/­sour­ce/­bro­wse/sr­c/e­pub­viewe­r.­p­y?­r=1­d5­df32­bf717651e5e­d5­d1­d22012666ee06­d63a2>`_ y el ar­chi­vo UI fi­le que ne­ce­si­tás.

Que le fal­ta:

  • No mues­­tra la ta­­pa.

  • Só­­­lo mues­­tra el pri­­mer ni­­vel del ín­­di­­ce.

  • Só­­­lo lo pro­­­bé en dos li­­bros ;-)

  • Ne­­ce­­si­­ta re­­fa­c­­to­­­ri­­zar a mo­­­ri­­r.

Nin­gu­na de esas co­sas es te­rri­ble­men­te di­fí­cil de ha­ce­r!

Presentando Aranduka

Y... es­te no lo es­toy ha­cien­do so­lo, lo que lo ha­ce más di­ver­ti­do.

Es un ad­mi­nis­tra­dor de eBooks (o de li­bros en ge­ne­ra­l?) que te ayu­da a te­ner tus PDF/­Mo­bi/­FB2/­lo­que­sea or­ga­ni­za­do­s, y de­be­ría even­tual­men­te sin­cro­ni­zar­los con el dis­po­si­ti­vo que que­rés usar pa­ra leer­lo­s.

¿Qué fun­cio­na? ¡Mi­rá el vi­deo!

Por si eso no tie­ne sen­ti­do pa­ra vo­s:

  • Po­­­dés ba­­jar li­­bros de Fee­­dBooks. Esos li­­bros se des­­ca­r­­gan, se agre­­gan a la ba­­se de da­­to­­s, se eti­­que­­tan, se ba­­ja la ta­­pa, etc. etc.

  • Po­­­dés im­­po­r­­tar tu ca­r­­pe­­ta ac­­tual de li­­bros en bu­l­­to

    Aran­­duka usa google y otros se­r­­vi­­cios pa­­ra tra­­tar de adi­­vi­­nar (por los no­m­­bres) qué li­­bro es ese y lle­­nar los da­­tos ex­­tra.

  • Po­­­dés "a­­di­­vi­­na­­r" esos da­­tos ex­­tra

    Ma­r­­can­­do co­­­mo co­n­­fia­­bles al­­gu­­nos da­­tos (por eje­m­­plo, el tí­­tu­­lo) Aran­­duka bus­­ca can­­di­­da­­tos que coi­n­­ci­­dan y ele­­gís el co­­­rre­c­­to.

    Por su­­pues­­to que ta­m­­bién se pue­­de edi­­tar los da­­tos ma­­nua­l­­men­­te.

Y eso es to­do por aho­ra. Fea­tu­res pla­nea­do­s:

  • Mu­­chos co­­­mo pa­­ra ha­­cer una lis­­ta.

La me­ta es cla­ra:

  • De­­be ser he­r­­mo­­­so (y no lo es)

  • De­­be ser po­­­ten­­te (y to­­­da­­vía no)

  • De­­be ser me­­jor que la "co­m­­pe­­ten­­cia"

Si no se lo­gran esas tres me­ta­s, es un fra­ca­so. Tal vez sea un fra­ca­so di­ver­ti­do, pe­ro igual es fra­ca­sar.

Diálogo de progreso muy pythónico

Este es un ejemplo que te muestra suficiente para usar progressbar:

progress = ProgressBar()
for i in progress(range(80)):
    time.sleep(0.01)

Sí, eso es to­do, te­nés una lin­da ba­rra de pro­gre­so AS­CII que cru­za la ter­mi­na­l, so­por­ta que la cam­bies de ta­ma­ño y se mue­ve mien­tras ite­rás de 0 a 79.

El módulo progressbar incluso tiene cosas mejores como ETA o velocidades de transferencia, y todo es así de fácil.

¿E­se có­di­go­... no es­tá bue­no? ¿Que­rés una ba­rra de pro­gre­so pa­ra ese lo­op? ¡Lo "en­vol­vé­s" y lis­to! Y por su­pues­to, co­mo yo pro­gra­mo con Py­Q­t, quie­ro que Py­Qt ten­ga al­go igual de bue­no.

Así se ve el re­sul­ta­do:

progress

Es­to lo po­dés ha­cer con cual­quier toolki­t, y pro­ba­ble­men­te de­be­ría­s. Tie­ne un fea­tu­re ex­tra: po­dés in­te­rrum­pir la ite­ra­ció­n, y es­te es el (po­co) có­di­go:

# -*- coding: utf-8 -*-
import sys, time
from PyQt4 import QtCore, QtGui

def progress(data, *args):
    it=iter(data)
    widget = QtGui.QProgressDialog(*args+(0,it.__length_hint__()))
    c=0
    for v in it:
        QtCore.QCoreApplication.instance().processEvents()
        if widget.wasCanceled():
            raise StopIteration
        c+=1
        widget.setValue(c)
        yield(v)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)

    # Do something slow
    for x in progress(xrange(50),"Show Progress", "Stop the madness!"):
        time.sleep(.2)

Di­viér­tan­se!


Contents © 2000-2023 Roberto Alsina