Ayuda con librerias QT, cargando paginas con webView

Hola! estoy haciendo una pequeña aplicación que básicamente lo que hace es visitar unas URL's que tengo almacenadas, todo bastante simple. El problema surge cuando voy a cargar las paginas web:
def leerMenSinLeer(self):
      print "Mensajes sin leer: " + str(len(self.menSinLeer))
      for link in self.menSinLeer:
         print "Mensaje -> " + str(link)
         self.verMensaje(link)

def verMensaje(self, url):
      """ Metodo para visitar un mensaje """
      visitar = self.dominio + str(url)
      self.logToConsole("Visitando mensaje: " + str(url))
      self.visitarURL(visitar)

def visitarURL(self, url):
      """ Metodo generico para visitar una URL cualquiera sin usar POST o GET """       
      manager = QNetworkAccessManager()
      request = QNetworkRequest(QUrl(url))
      
      self.ui.webView.load(QUrl(url))
      self.logToConsole("Visitando: " + str(url))
      print "visitando " + str(url)


El problema es que yo quiero que cargue una web, espere a que termine de cargar, una vez que termina de cargar esa web vaya a por la siguiente, así hasta cargar todos los elementos de la lista.
Según tengo he entendido después de haberme leído la documentación para lograr este funcionamiento debería reescribir el método de la señal loadFinished(bool) lo cual se hace de la siguiente forma:
QtCore.QObject.connect(self.ui.webView,QtCore.SIGNAL("loadFinished (bool)"), self.ejecutaSiguiente)


Ahora, he intentado hacerlo y no consigo que funcione correctamente, siempre carga solo el ultimo link de la lista o simplemente no carga nada. Alguien que haya utilizado estos clases puede echarme una mano?

Muchísimas gracias!

PD: Estoy utilizando Python + PyQT
Envydia escribió:Según tengo he entendido después de haberme leído la documentación para lograr este funcionamiento debería reescribir el método de la señal loadFinished(bool) lo cual se hace de la siguiente forma:
QtCore.QObject.connect(self.ui.webView,QtCore.SIGNAL("loadFinished (bool)"), self.ejecutaSiguiente)


No se muy bien como sera en PyQt, pero por similitudes con Qt "real" (c++), lo que estas haciendo es conectar una señal a un slot, no reimplementar nada.
Es decir, le estas diciendo que cuando el widget que has llamado webView emita la señal "loadFinished()", se ejecute la funcion ejecutaSiguiente, que por cierto, entiendo que deberia ser un SLOT()

Me temo que faltan demasiadas partes del codigo para acabar de entender... que se supone que hace la funcion ejecutaSiguiente?
Envydia escribió:
def leerMenSinLeer(self):
      print "Mensajes sin leer: " + str(len(self.menSinLeer))
      for link in self.menSinLeer:
         print "Mensaje -> " + str(link)
         self.verMensaje(link)


Con ese for estás leyendo todos los mensajes sin leer uno tras otro sin esperar a que terminen de cargar y por eso en webView se te quedará la última url que tengas por leer.

Viendo un poco la documentación de PyQt veo que no es necesario definir un slot como comenta Jan, sino que puedes asignarle una función definida directamente, así que lo que tendrías que hacer es sólamente leer el primer mensaje sin leer, cuando este se haya cargado ejecutaSiguiente hace un pop de la lista de urls y carga la siguiente... ya nos contarás qué tal te va.
Perdonad por no haber contestado antes que con navidades... ya sabéis :S

JanKusanagi escribió:
Envydia escribió:Según tengo he entendido después de haberme leído la documentación para lograr este funcionamiento debería reescribir el método de la señal loadFinished(bool) lo cual se hace de la siguiente forma:
QtCore.QObject.connect(self.ui.webView,QtCore.SIGNAL("loadFinished (bool)"), self.ejecutaSiguiente)


No se muy bien como sera en PyQt, pero por similitudes con Qt "real" (c++), lo que estas haciendo es conectar una señal a un slot, no reimplementar nada.
Es decir, le estas diciendo que cuando el widget que has llamado webView emita la señal "loadFinished()", se ejecute la funcion ejecutaSiguiente, que por cierto, entiendo que deberia ser un SLOT()

Me temo que faltan demasiadas partes del codigo para acabar de entender... que se supone que hace la funcion ejecutaSiguiente?


ejecutaSiguiente era un ejemplo :) me refería al trozo de código que debía ejecutarse después de cargar la web^^


Gooler escribió:
Envydia escribió:
def leerMenSinLeer(self):
      print "Mensajes sin leer: " + str(len(self.menSinLeer))
      for link in self.menSinLeer:
         print "Mensaje -> " + str(link)
         self.verMensaje(link)


Con ese for estás leyendo todos los mensajes sin leer uno tras otro sin esperar a que terminen de cargar y por eso en webView se te quedará la última url que tengas por leer.

Viendo un poco la documentación de PyQt veo que no es necesario definir un slot como comenta Jan, sino que puedes asignarle una función definida directamente, así que lo que tendrías que hacer es sólamente leer el primer mensaje sin leer, cuando este se haya cargado ejecutaSiguiente hace un pop de la lista de urls y carga la siguiente... ya nos contarás qué tal te va.


Al final opte por la solución del pop que me pareció mas sencilla.

def verMensajesSinLeer(self):
      if len(self.menSinLeer) > 0:
         QtCore.QObject.connect(self.ui.webView.page(),QtCore.SIGNAL("loadFinished (bool)"), self.verMensajesSinLeer)
         mensaje = self.menSinLeer.pop()
         self.ui.webView.load( QUrl( self.dominio + mensaje ) )
         print "visitando: " + self.dominio + mensaje
      else:
         QtCore.QObject.connect(self.ui.webView.page(),QtCore.SIGNAL("loadFinished (bool)"), self.loadFinished)
         print "No hay mensajes para leer."
         self.cerrarSesion()


El problema que tengo ahora es que al finalizar todo, es decir cuando termina de ver los mensajes y cierra la sesión, si quiere volver a ejecutar todo el proceso otra vez(que se hace con un botón), no funciona de la misma forma y ademas no tiene el funcionamiento adecuado. He revisado el código durante horas y no encuentro el fallo, es mas he creado un método que resetea toooodas las variables de la aplicación por si quedaba algún resto, reinicia incluso las señales y sigue sin ir.
Lo que se me ocurrió, aunque puede que sea un poco bruto..., es destruir el widget del webView y luego volver a crearlo. Lo intente con .destroy() y no hacia nada como si no lo hubiese destruido, he probado meter el webView en un layout pero al hacer removeWidget() tampoco hace nada..

Sabéis que puede ser?

Muchísimas gracias a ambos! ^^
def verMensajesSinLeer(self):
      if len(self.menSinLeer) > 0:
         QtCore.QObject.connect(self.ui.webView.page(),QtCore.SIGNAL("loadFinished (bool)"), self.verMensajesSinLeer)
         mensaje = self.menSinLeer.pop()
         self.ui.webView.load( QUrl( self.dominio + mensaje ) )
         print "visitando: " + self.dominio + mensaje
      else:
         QtCore.QObject.connect(self.ui.webView.page(),QtCore.SIGNAL("loadFinished (bool)"), self.loadFinished)
         print "No hay mensajes para leer."
         self.cerrarSesion()


En esta última porción de código veo raro que estés cambiando la conexión de loadFinished en uno de los métodos a los que se conecta.
Que yo sepa, las conexiones se hacen cuando se construyen los objetos y no se van cambiando durante la ejecución del código, pero no sé si es una buena práctica o si directamente no se puede hacer. El caso es que si estás teniendo problemas igual es por esto.

Así que yo sacaría esas conexiones de ahí y metería sólo la primera en el constructor.
Luego, una vez en verMensajesSinLeer(), dejas el if/else que tienes y si tienes que llamar a loadFinished() llámalo directamente igual que llamas a cerrarSesion().
O también puedes emitir una señal que hayas definido a mano y que esté conectada con esos dos métodos...

Espero que te sea de ayuda.
4 respuestas