Package pilas :: Module asistente
[hide private]
[frames] | no frames]

Source Code for Module pilas.asistente

  1  # -*- encoding: utf-8 -*- 
  2  # pilas engine - a video game framework. 
  3  # 
  4  # copyright 2010 - hugo ruscitti 
  5  # license: lgplv3 (see http://www.gnu.org/licenses/lgpl.html) 
  6  # 
  7  # website - http://www.pilas-engine.com.ar 
  8   
  9  import sys 
 10  import os 
 11  from PyQt4 import QtCore, QtGui, QtWebKit, QtNetwork 
 12  import json 
 13   
 14  from asistente_base import Ui_AsistenteWindow 
 15  import pilas 
 16  import utils 
 17   
18 -class VentanaAsistente(Ui_AsistenteWindow):
19
20 - def setupUi(self, main):
21 self.main = main 22 Ui_AsistenteWindow.setupUi(self, main) 23 24 self.webView.setAcceptDrops(False) 25 self.webView.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateExternalLinks) 26 self.webView.connect(self.webView, QtCore.SIGNAL("linkClicked(const QUrl&)"), self.cuando_pulsa_link) 27 self._cargar_pagina_principal() 28 self._deshabilitar_barras_de_scroll() 29 pilas.utils.centrar_ventana(main) 30 self.statusbar.showMessage(u"Versión " + pilas.version()) 31 self._habilitar_inspector_web() 32 self.salir_action.connect(self.salir_action, QtCore.SIGNAL("triggered()"), self.salir) 33 self._consultar_ultima_version_del_servidor()
34
36 direccion = QtCore.QUrl("http://www.pilas-engine.com.ar/version.json") 37 self.manager = QtNetwork.QNetworkAccessManager(self.main) 38 self.manager.get(QtNetwork.QNetworkRequest(direccion)) 39 40 self.manager.connect(self.manager, QtCore.SIGNAL("finished(QNetworkReply*)"), 41 self._cuando_termina_de_consultar_version)
42
43 - def _cuando_termina_de_consultar_version(self, respuesta):
44 respuesta_como_texto = respuesta.readAll().data() 45 try: 46 respuesta_como_json = json.loads(str(respuesta_como_texto)) 47 48 version_en_el_servidor = float(respuesta_como_json['version']) 49 version_instalada = float(pilas.pilasversion.VERSION) 50 51 if version_en_el_servidor == version_instalada: 52 mensaje = "- actualizada" 53 elif version_en_el_servidor < version_instalada: 54 mensaje = u"- desarrollo (versión estable en la web: %.2f)" %(version_en_el_servidor) 55 else: 56 mensaje = u"- desactualizada: la version %.2f ya está disponible en la web!)" %(version_en_el_servidor) 57 except ValueError: 58 mensaje = u"(sin conexión a internet)" 59 60 self.statusbar.showMessage(u"Versión " + pilas.version() + " " + mensaje)
61 62
63 - def _habilitar_inspector_web(self):
64 QtWebKit.QWebSettings.globalSettings() 65 settings = QtWebKit.QWebSettings.globalSettings() 66 settings.setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) 67 settings.setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessFileUrls, True)
68
70 self.webView.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) 71 self.webView.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAsNeeded)
72
73 - def _cargar_pagina_principal(self):
74 file_path = utils.obtener_ruta_al_recurso('asistente/index.html') 75 # TODO: convierto la ruta en absoluta para que mac desde py2app 76 # pueda interpretar correctamente las imagenes. 77 file_path = os.path.abspath(file_path) 78 79 contenido = self._obtener_html(file_path) 80 base_dir = QtCore.QUrl.fromLocalFile(file_path) 81 self.webView.setHtml(contenido, base_dir)
82
83 - def _obtener_html(self, file_path):
84 archivo = open(file_path, "rt") 85 contenido = archivo.read() 86 contenido = contenido.replace("{{VERSION_FRAME}}", """<iframe src='http://www.pilas-engine.com.ar/estadistica'></iframe>""") 87 archivo.close() 88 return contenido.decode('utf8')
89 116
117 - def _ejecutar_ejemplo(self, categoria, nombre):
118 """Intenta ejecutar un programa de ejemplo en base a la categoria y nombre. 119 120 Internamente, esta funcion intenta buscar un archivo dentro de la 121 ruta "../ejemplos/ejemplos/{categoria}/{nombre}.py". 122 """ 123 try: 124 ruta = self._obtener_ruta_al_ejemplo(categoria, nombre) 125 126 self.process = QtCore.QProcess(self.main) 127 self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels) 128 self.process.finished.connect(self._cuando_termina_la_ejecucion_del_ejemplo) 129 self.process.start(sys.executable, [ruta]) 130 except Exception, name: 131 QtGui.QMessageBox.critical(self.main, "Error", str(name))
132
133 - def _mostrar_codigo(self, categoria, nombre):
134 try: 135 ruta = self._obtener_ruta_al_ejemplo(categoria, nombre) 136 file_path = utils.obtener_ruta_al_recurso('asistente/codigo.html') 137 # TODO: convierto la ruta en absoluta para que mac desde py2app 138 # pueda interpretar correctamente las imagenes. 139 file_path = os.path.abspath(file_path) 140 141 contenido = self._obtener_html(file_path) 142 143 import codecs 144 archivo_codigo = codecs.open(ruta, "r", "utf-8") 145 contenido_codigo = archivo_codigo.read() 146 archivo_codigo.close() 147 contenido = contenido.replace("{codigo}", contenido_codigo) 148 base_dir = QtCore.QUrl.fromLocalFile(file_path) 149 self.webView.setHtml(contenido, base_dir) 150 except Exception, name: 151 QtGui.QMessageBox.critical(self.main, "Error", str(name))
152
153 - def _obtener_ruta_al_ejemplo(self, categoria, nombre):
154 recurso = "../ejemplos/ejemplos/" + categoria + "/" + nombre + ".py" 155 return pilas.utils.obtener_ruta_al_recurso(recurso)
156 157
158 - def _cuando_termina_la_ejecucion_del_ejemplo(self, codigo, estado):
159 "Vuelve a permitir que se usen todos los botone de la interfaz." 160 salida = str(self.process.readAll()) 161 162 if codigo: 163 QtGui.QMessageBox.critical(self.main, "Error al iniciar ejemplo", "Error: \n" + salida)
164
166 comando = " ".join([sys.executable, sys.argv[0], '-i']) 167 self._ejecutar_comando(comando)
168
169 - def ejecutar_script(self, nombre_archivo_script):
170 comando = " ".join([sys.executable, sys.argv[0], '-i', str(nombre_archivo_script)]) 171 self._ejecutar_comando(comando)
172
173 - def _ejecutar_comando(self, comando):
174 "Ejecuta un comando en segundo plano." 175 self.proceso = QtCore.QProcess() 176 self.proceso.startDetached(comando)
177
179 base_dir = '/usr/share/pilas' 180 ruta_al_manual = os.path.join(base_dir, 'pilas-%s.pdf' %(pilas.version())) 181 182 try: 183 # BUSCA el archivo: /usr/share/pilas/pilas-VERSION.pdf 184 ruta = pilas.utils.obtener_ruta_al_recurso(ruta_al_manual) 185 pilas.utils.abrir_archivo_con_aplicacion_predeterminada(ruta) 186 except IOError: 187 try: 188 # BUSCA el archivo: /home/mi_usuario/.pilas/pilas-VERSION.pdf 189 base_dir = str(QtCore.QDir.homePath()) 190 ruta_al_manual = os.path.join(base_dir, '.pilas', 'pilas-%s.pdf' %(pilas.version())) 191 ruta = pilas.utils.obtener_ruta_al_recurso(ruta_al_manual) 192 pilas.utils.abrir_archivo_con_aplicacion_predeterminada(ruta) 193 except IOError: 194 titulo = "Error, no se encuentra el manual" 195 mensaje = u"Lo siento, no se encuentra el manual en tu equipo. ¿Quieres descargarlo?" 196 respuesta = self._consultar(self.main, titulo, mensaje) 197 198 if respuesta == QtGui.QMessageBox.Yes: 199 url = "http://media.readthedocs.org/pdf/pilas/latest/pilas.pdf" 200 pilas.utils.descargar_archivo_desde_internet(self.main, url, ruta_al_manual)
201
202 - def _consultar(self, parent, titulo, mensaje):
203 "Realizar una consulta usando un cuadro de dialogo." 204 return QtGui.QMessageBox.question(parent, titulo, mensaje, 205 QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
206
207 - def salir(self, *_):
208 self.main.close()
209 210
211 -class MainWindow(QtGui.QMainWindow):
212
213 - def __init__(self):
214 QtGui.QMainWindow.__init__(self) 215 self.setAcceptDrops(True)
216
217 - def definir_receptor_de_comandos(self, ui):
218 self.ui = ui
219
220 - def dragEnterEvent(self, event):
221 if event.mimeData().hasUrls(): 222 event.acceptProposedAction()
223
224 - def dragMoveEvent(self, event):
225 super(MainWindow, self).dragMoveEvent(event)
226
227 - def dropEvent(self, event):
228 if event.mimeData().hasUrls(): 229 for url in event.mimeData().urls(): 230 self.ui.ejecutar_script(url.path()) 231 event.acceptProposedAction() 232 else: 233 super(MainWindow,self).dropEvent(event)
234
235 -def ejecutar():
236 app = QtGui.QApplication(sys.argv) 237 app.setApplicationName("pilas-engine") 238 239 main = MainWindow() 240 ui = VentanaAsistente() 241 main.definir_receptor_de_comandos(ui) 242 ui.setupUi(main) 243 244 main.show() 245 main.raise_() 246 app.exec_()
247