def actualizar_imagen(self, MyPlayerEvent): if self.started: for i in self.deads: i.is_dead = True pl = MyPlayerEvent.player d = pl.daño an = pl.pseudo_angulo tipo = pl.tipo ftipo = pl.first_tipo label = pl.image if pl.contador%20 == 0: self.sound_walk() if not pl.is_dead: c = pl.contador_game % 40 // 10 + 1 pixmap = QPixmap(all_sprites_shits[tipo][d][c]) l_pixmap = QPixmap(all_sprites_shits[ftipo][d][c]) else: c = pl.contador_game % 60 // 10 pixmap = QPixmap(entidad_muerta[tipo][c]) l_pixmap = QPixmap(entidad_muerta[ftipo][c]) pixmap = pixmap.scaled(self.w / 70 * pl.tamaño**0.8, self.w / 70 * pl.tamaño**0.8) transform = QTransform().rotate(pl.angulo - 180 - an) pixmap = pixmap.transformed(transform, Qt.SmoothTransformation) label.move(pl.position[0], pl.position[1]) label.setPixmap(pixmap) label.raise_() l_pixmap = l_pixmap.scaled(self.w/10, self.w/10) l_pixmap = l_pixmap.transformed(transform, Qt.SmoothTransformation) self.label_game.setPixmap(l_pixmap) self.label_game.setAlignment(Qt.AlignCenter)
def create_d_pad(self): self.label_up = QLabel(self) self.label_left = QLabel(self) self.label_down = QLabel(self) self.label_right = QLabel(self) self.label_stop = QLabel(self) self.label_publisher = QLabel(self) img = QPixmap(self.script_path + '../images/d-pad-pressed.png') img = img.scaled(SCREEN_SIZE, SCREEN_SIZE, Qt.KeepAspectRatio) t = QTransform() self.label_up.setPixmap(img) t.rotate(90) self.label_right.setPixmap(img.transformed(t)) t.rotate(90) self.label_down.setPixmap(img.transformed(t)) t.rotate(90) self.label_left.setPixmap(img.transformed(t)) # e-stop img = QPixmap(self.script_path + '../images/d-e-stop.png') img = img.scaled(SCREEN_SIZE, SCREEN_SIZE, Qt.KeepAspectRatio) self.label_stop.setPixmap(img) # publisher icon img = QPixmap(self.script_path + '../images/d-publisher.png') img = img.scaled(SCREEN_SIZE, SCREEN_SIZE, Qt.KeepAspectRatio) self.label_publisher.setPixmap(img) # --- self.change_state()
def mostrar_cartas_oponentes(self): self.movedor_1 = 70 for i in range(0, 4): carta = QLabel(self) pixmap = QPixmap(self.parametros["PATH_REVERSO"]).scaled(50, 70) transform = QTransform().rotate(90) pixmap = pixmap.transformed(transform, Qt.SmoothTransformation) carta.setPixmap(pixmap) carta.move(0, self.movedor_1) self.movedor_1 += 50 self.cartas_1.append(carta) self.movedor_2 = 70 for i in range(0, 4): carta = QLabel(self) pixmap = QPixmap(self.parametros["PATH_REVERSO"]).scaled(50, 70) transform = QTransform().rotate(180) pixmap = pixmap.transformed(transform, Qt.SmoothTransformation) carta.setPixmap(pixmap) carta.move(self.movedor_2, 0) self.movedor_2 += 50 self.cartas_2.append(carta) self.movedor_3 = 70 for i in range(0, 4): carta = QLabel(self) pixmap = QPixmap(self.parametros["PATH_REVERSO"]).scaled(50, 70) transform = QTransform().rotate(270) pixmap = pixmap.transformed(transform, Qt.SmoothTransformation) carta.setPixmap(pixmap) carta.move(570, self.movedor_3) self.movedor_3 += 50 self.cartas_3.append(carta)
def rotateImage90(self, direction): """Rotate image 90º clockwise or counterclockwise.""" if self.image.isNull() == False: if direction == "cw": transform90 = QTransform().rotate(90) elif direction == "ccw": transform90 = QTransform().rotate(-90) pixmap = QPixmap(self.image) #TODO: Try flipping the height/width when flipping the image rotated = pixmap.transformed(transform90, mode=Qt.SmoothTransformation) self.resize(self.image.height(), self.image.width()) #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height) #self.image_label.setPixmap(rotated.scaled(self.image_label.size(), # Qt.KeepAspectRatio, Qt.SmoothTransformation)) self.image = QImage(rotated) #self.setPixmap(rotated) self.setPixmap( rotated.scaled(self.size(), Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation)) self.repaint() # repaint the child widget else: # No image to rotate pass
def cerrarPinzas(self): self.img = QImage() self.img.load(self.rutaImg + "/cerrar.png") pixmap = QPixmap(self.img) transform = QTransform().rotate(self.rotation) pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation) self.setPixmap(pixmap)
def on_new_token_messages(self, data): # print('Tokens:', data) for token in data: if token['component_id'] == 40: print('Found Token 40') self.last_time_token_seen = time.time() #if not self.image_visible: self.label.show() self.image_visible = True token_angle = token['angle'] if self.image_rotation not in range(token_angle - 1, token_angle + 1): # Based on https://stackoverflow.com/questions/31892557/rotating-a-pixmap-in-pyqt4-gives-undesired-translation pixmap = QPixmap(os.path.abspath(os.path.join(os.path.dirname(__file__), 'image.jpg'))) transform = QTransform().rotate(token_angle) self.image_rotation = token_angle pixmap = pixmap.transformed(transform, Qt.SmoothTransformation) self.label.setPixmap(pixmap) #global_pos = QPoint(int(token['x_pos'] / 1280 * 2560), int(token['y_pos'] / 720 * 1440)) local_pos = self.mapFromGlobal(QPoint(token['x_pos'],token['y_pos'])) try: self.label.move(local_pos.x() - self.label.width()/2, local_pos.y() - self.label.height()/2 + 500) except Exception as e: print(e)
def CaptureVideo(self): if not self.videoBusy and self.camOpen: self.videoBusy = True self.img = self.cam.GetQImage() pix = QPixmap(self.camView.width(), self.camView.height()) pix.fill(Qt.black) img = self.img.scaled(self.camView.size(), Qt.KeepAspectRatio) painter = QPainter(pix) painter.setRenderHints( QPainter.Antialiasing | QPainter.SmoothPixmapTransform, True) pointx = int( np.round(np.fabs(self.camView.width() - img.width()) / 2)) pointy = int( np.round(np.fabs(self.camView.height() - img.height()) / 2)) painter.drawImage(pointx, pointy, img) painter.end() fh = 1 fv = 1 if self.fliphCheck.isChecked(): fh = -1 if self.flipvCheck.isChecked(): fv = -1 if (fv != 1 or fh != 1): pix = pix.transformed(QTransform().scale(fh, fv)) self.camView.setPixmap(pix) self.videoBusy = False
def setIcon(self, widget, ico, rotate=0, force_color_change: str = None): if isinstance(ico, str): icon = QIcon() if not ico == '': if app_defs.APP_IMAGE_DIR: path = app_defs.APP_IMAGE_DIR else: path = 'img' path = os.path.join(path, ico) if not os.path.isfile(path): logging.warning( f'File {path} does not exist or is not a file') pixmap = QPixmap(path) if rotate: transf = QTransform().rotate(rotate) pixmap = QPixmap(pixmap.transformed(transf)) if force_color_change: tmp = pixmap.toImage() color = QColor(force_color_change) for y in range(0, tmp.height()): for x in range(0, tmp.width()): color.setAlpha(tmp.pixelColor(x, y).alpha()) tmp.setPixelColor(x, y, color) pixmap = QPixmap.fromImage(tmp) icon.addPixmap(pixmap) else: icon = self.style().standardIcon(ico) widget.setIcon(icon)
def attack_graphic(self, pos, angle, nro_img, carpeta, iden): path = 'IMGS/{}/attack_graphic{}.png'.format(carpeta, nro_img) if path not in self.imagenes: img = QPixmap(path) self.imagenes[path] = img else: img = self.imagenes[path] if not hasattr(self, 'attack_anim{}_{}'.format(nro_img, iden)): setattr(self, 'attack_anim{}_{}'.format(nro_img, iden), MyQLabel(self)) qlabel = getattr(self, 'attack_anim{}_{}'.format(nro_img, iden)) diag = (img.width()**2 + img.height()**2)**0.5 qlabel.setMinimumSize(diag, diag) qlabel.setAlignment(Qt.AlignCenter) else: qlabel = getattr(self, 'attack_anim{}_{}'.format(nro_img, iden)) angle = round(360 - angle) key = path + str(angle) if key not in self.imagenes: img = img.transformed(QTransform().rotate(angle), Qt.SmoothTransformation) self.imagenes[key] = img else: img = self.imagenes[key] qlabel.setPixmap(img) qlabel.move(*pos) qlabel.show()
def render(self, qp: QPainter, x: float, y: float) -> None: """ Fait le rendu de l'entité sur l'écran à l'aide du painter de ce dernier. Args: qp (QPainter): painter de la surface sur laquelle dessiner x (float): position X du milieu de l'entité par rapport au joueur y (float): position Y du milieu de l'entité par rapport au joueur """ # Si on a définit une image on la dessine if self.image is not None: img = QPixmap(self.image) if self.image_direction.equal(Vecteur(0.0, 1.0)): # direction sud rotation = 180 elif self.image_direction.equal(Vecteur(1.0, 0.0)): # direction est rotation = 90 elif self.image_direction.equal(Vecteur(-1.0, 0.0)): # direction ouest rotation = 270 else: # direction nord rotation = 0 img_rotated = img.transformed(QTransform().rotate(rotation)) # xoffset = (img_rotated.width() - img.width()) / 2 # yoffset = (img_rotated.height() - img.height()) / 2 # img_rotated = img_rotated.copy(xoffset, yoffset, img.width(), img.height()) img_rot_scal = img_rotated.scaled(*self.size) qp.drawPixmap(QPoint(x - self.size[0] // 2, y - self.size[1] // 2), img_rot_scal) self.draw_life_bar(qp, x, y)
def rotate_img(self): rotate_val = self.rotate_slider.value() transform = QTransform().rotate(rotate_val/10) pixmap = QPixmap(self.will_change_img) rotated = pixmap.transformed(transform, mode=Qt.SmoothTransformation) self.will_change_img = QImage(rotated) self.image_label2.setPixmap(QPixmap.fromImage(self.will_change_img))
class Bullet(QLabel): kreni = pyqtSignal() #x i y su koordinate rakete, rotation je broj slike (1 - 72) def __init__(self, x, y, rotation, scene: QGraphicsScene): super().__init__() self.image = QPixmap("Images/bullet.png") t = QTransform().rotate(rotation) self.image = self.image.transformed(t) self.setPixmap(self.image) self.init_x = x self.init_y = y self.scene = scene self.xMovement = float(cos(radians(rotation))) self.yMovement = float(sin(radians(rotation))) self.scene.addWidget(self) self.kreni.connect(self.moveSelf) self.initBullet() def initBullet(self): self.move(self.init_x, self.init_y) def moveSelf(self): y = self.geometry().y() x = self.geometry().x() self.init_x = float(self.init_x).__add__(self.xMovement) self.init_y = float(self.init_y).__sub__(self.yMovement) #if y > -35 and y < 490 and x > 0 and x < 600: self.move(self.init_x, self.init_y)
class MovingEntityVisualisation(QWidget): def __init__(self, father, wrapping_object: MovingEntity, texture: str): super().__init__() self.setParent(father) self.x = wrapping_object.x * father.cell_size self.y = wrapping_object.y * father.cell_size self.tick_mod = Cells.CellSize // wrapping_object.speed self.ticks = 0 self.father = father self.angle = 0 self.q_trans = None self.screen_x = wrapping_object.x * father.cell_size self.screen_y = wrapping_object.y * father.cell_size self.moves = False self.moving_will = MovingWills.Nowhere self.wrapping_object = wrapping_object self.setGeometry(self.screen_x, self.screen_y, father.cell_size, father.cell_size) self.label = QLabel() self.img = None self.set_texture(texture) self.adjust_direction() def set_texture(self, texture): self.img = QPixmap(texture).scaled(self.father.cell_size, self.father.cell_size) self.label.setPixmap(self.img) self.label.setParent(self) self.label.show() def adjust_direction(self): if self.wrapping_object.direction == Direction.Up: self.angle = 0 elif self.wrapping_object.direction == Direction.Down: self.angle = 180 elif self.wrapping_object.direction == Direction.Right: self.angle = 90 else: self.angle = 270 self.q_trans = QTransform().rotate(self.angle) self.label.setPixmap(self.img.transformed(self.q_trans)) def update_position(self): col = None if self.ticks == 0 and self.moves: col = self.wrapping_object.move(self.father.game, self.moving_will) if (abs(self.wrapping_object.x - self.screen_x / self.father.cell_size) > 1e-8 or abs(self.wrapping_object.y - self.screen_y / self.father.cell_size) > 1e-8): self.screen_x += (self.moving_will * self.wrapping_object.speed * self.wrapping_object.direction[0]) self.screen_y += (self.moving_will * self.wrapping_object.speed * self.wrapping_object.direction[1]) self.move(self.screen_x, self.screen_y) self.ticks = (self.ticks + 1) % self.tick_mod else: self.ticks = 0 self.moving_will = MovingWills.Nowhere self.adjust_direction() return col
def get_icon_pixmap(ico_file_name: str, rotate=0, force_color_change: str = None) -> QPixmap: if app_defs.APP_IMAGE_DIR: path = app_defs.APP_IMAGE_DIR else: path = 'img' path = os.path.join(path, ico_file_name) if not os.path.isfile(path): logging.warning(f'File {path} does not exist or is not a file') pixmap = QPixmap(path) if rotate: transf = QTransform().rotate(rotate) pixmap = QPixmap(pixmap.transformed(transf)) if force_color_change: tmp = pixmap.toImage() color = QColor(force_color_change) for y in range(0, tmp.height()): for x in range(0, tmp.width()): color.setAlpha(tmp.pixelColor(x, y).alpha()) tmp.setPixelColor(x, y, color) pixmap = QPixmap.fromImage(tmp) return pixmap
def _image(file, sub_folder, rotate=None): pixmap = QPixmap(os_path_join(_BASE_PATH, sub_folder, file)) if rotate is None: return pixmap transform = QTransform() transform.rotate(rotate) return pixmap.transformed(transform)
def __closePincers(self): self.image = QImage() self.image.load(self.routeImage + "/closePincer.png") pixmap = QPixmap(self.image) transform = QTransform().rotate(self.rotation) pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation) self.setPixmap(pixmap)
def OnWindowResize(self, event): Timer(0.1, self.FixOverlays).start() Timer(0.2, self.DrawFixedScale).start() if self.camOpen and not self.capTimer.isActive(): pix = QPixmap(self.camView.width(), self.camView.height()) pix.fill(Qt.black) img = self.img.scaled(self.camView.size(), Qt.KeepAspectRatio) painter = QPainter(pix) painter.setRenderHints( QPainter.Antialiasing | QPainter.SmoothPixmapTransform, True) pointx = int( np.round(np.fabs(self.camView.width() - img.width()) / 2)) pointy = int( np.round(np.fabs(self.camView.height() - img.height()) / 2)) painter.drawImage(pointx, pointy, img) painter.end() fh = 1 fv = 1 if self.fliphCheck.isChecked(): fh = -1 if self.flipvCheck.isChecked(): fv = -1 if (fv != 1 or fh != 1): pix = pix.transformed(QTransform().scale(fh, fv)) self.camView.setPixmap(pix)
def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) ##Captors self.captors = [333,0, 666,0, 1025,500, 666,1020, 333,1020, 0,500] self.rotation = [0, 0, 90, 180, 180, 270] captors=[] for i in range(0,6): captor = QLabel(self) img = QPixmap('ir-detector-small.png') transform = QTransform().rotate(self.rotation[i]) img = img.transformed(transform, Qt.SmoothTransformation) captor.setPixmap(img) captor.move(self.captors[i*2]-5, self.captors[i*2+1]-5) captors.append(captor) self.circles = [200,640,200, 410,340,360, 750,480,280] self.circlesInitPos = self.circles.copy() #Labels self.recordingLabel = QLabel(self) self.recordingLabel.setText("Amplitude des mouvements faciaux") self.recordingLabel.move(0,0) self.recordingLabel.resize(300, 20) ##Timers self.backToPosTimer=QTimer() self.backToPosTimer.timeout.connect(self.comeBackToPosition) self.backToPosTimer.start(int(1000/self.FPS)) self.updateTimer=QTimer() self.updateTimer.timeout.connect(self.paintUpdate) self.updateTimer.start(int(1000/self.FPS)) self.show()
def set_steering(self, sval): self.steering.setProperty("value", sval) transform = QTransform() transform.rotate(sval * 2 - 100) steering_wheel = QPixmap('steering-wheel.svg') self.steering_wheel = steering_wheel.transformed(transform) self.wheel_label.setPixmap(self.steering_wheel)
class Human(Entity): path = _PATH + os.sep + "assets" + os.sep + "humans" + os.sep LUDOPATA = "ludopata" KIBITZER = "kibitzer" DIECIOCHERO = "dieciochero" GANADOR = "ganador" MILLONARIO = "millonario" def __init__(self, personality, x=0, y=0, parent=None): super().__init__(self.path + f"human_{personality}.png", parent=parent) self.personality = personality self.x = x self.y = y self.setFixedSize(73 * _SCALE, 73 * _SCALE) def change_personality(self, new_perso): self.personality = new_perso self._base_image = f"{self.path}human_{self.personality}.png" self.updatePixmap() def updatePixmap(self): path = self._base_image self.__pixmap = QPixmap(path) self.__pixmap = self.__pixmap.scaled(self.__pixmap.width() * _SCALE, self.__pixmap.height() * _SCALE) self.__pixmap = self.__pixmap.transformed(QTransform().rotate( self.angle)) self._base_label.setPixmap(self.__pixmap)
def cambiarMapeta(self): """ El canvas ha girado. Hay que recargar la imagen del mapeta apropiada.\n La imagen sin giro se gira lo que manda la rotación del canvas y se recarga en el mapeta Se invoca en la carga y cuando se detecta una rotacion """ #print("cambiarMapeta",QTime.currentTime().toString(Qt.DefaultLocaleLongDate)) angulo_rotacion = self.canvas.rotation() # Roto la imagen pixmap = QPixmap(self.PngMapeta) # self.setGeometry(20,20,self.xTamany,self.yTamany) rot_pixmap = pixmap.transformed(QTransform().rotate(angulo_rotacion), Qt.SmoothTransformation) # Recorto la imagen al tamaño establecido en el PGW hp = rot_pixmap.height() pc = (hp - self.xTamany) / 2 rect = QRect(pc, pc, self.xTamany, self.yTamany) self.cropped_pixmap = rot_pixmap.copy(rect) #TODO:paso FEO (salvar a disco) para recargar la imagen. Seguramente causa retardos self.tempdir = configuracioQvista.tempdir fic_tmp = os.path.join(self.tempdir, "trash.png") self.cropped_pixmap.save(fic_tmp, "PNG", 100) parametro = "{opacity: 50; background-image: url(" + fic_tmp + ");} " parametro = parametro.replace('\\', '/') self.setStyleSheet('QFrame' + parametro)
def rotateNeg(self): pixmap = QPixmap(self.img) self.rotation -= 3 transform = QTransform().rotate(self.rotation) pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation) self.setPixmap(pixmap) self.angulo = math.fabs(self.rotation % 360) self.modificarEcuacion()
def __rotateNeg(self): pixmap = QPixmap(self.image) self.rotation -= 5.1 transform = QTransform().rotate(self.rotation) pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation) self.setPixmap(pixmap) self.angle = math.fabs(self.rotation % 360) self.__updateEquationOfTheLine()
def draw(self): transform = QTransform() transform.rotate(self.ROTATE_ANGLES[self.direction]) pixmap = QPixmap(self.SPRITES[self.type]) pixmap = pixmap.scaled(self.CELL_SIZE, self.CELL_SIZE) pixmap = pixmap.transformed(transform) self.cell_label.setPixmap(pixmap)
def __loadGraphicItemImagePart( image: 'ImageInfo', condition_variables: 'Optional[Dict[str, Any]]', condition_graphic_items: 'List[ConditionGraphicsPixmapItem]') \ -> 'QGraphicsItem': pixmap = QPixmap(str( FileInfo().getPath(FileInfo.FileDataType.IMAGE, image.name))) image_x_is_expr = isinstance(image.x, str) image_y_is_expr = isinstance(image.y, str) image_angle_is_expr = isinstance(image.angle, str) width_scale, height_scale = __getSizeScale( pixmap.width(), pixmap.height(), image.width, image.height) if not image_angle_is_expr: pixmap = pixmap.transformed(QTransform().rotate(image.angle)) setup_script = image.setup_script if setup_script is not None: result = __runExpression(setup_script, condition_variables) if result is not None: condition_variables = result if image_angle_is_expr or image_x_is_expr or image_y_is_expr or \ image.condition: gitem_part = ConditionGraphicsPixmapItem( image.condition, pixmap, names=condition_variables) condition_graphic_items.append(gitem_part) else: gitem_part = QGraphicsPixmapItem(pixmap) gitem_part.setTransform(QTransform().scale(width_scale, height_scale)) if image_angle_is_expr: gitem_part.setAngleOffsetExpression(image.angle) x_offset = 0 if image_x_is_expr: gitem_part.setXOffsetExpression(image.x, multiplier=1/width_scale) else: x_offset = image.x/width_scale y_offset = 0 if image_y_is_expr: gitem_part.setYOffsetExpression(image.y, multiplier=1/height_scale) else: y_offset = image.y/height_scale gitem_part.setOffset(x_offset - pixmap.width()/2, y_offset - pixmap.height()/2) gitem_part.setZValue(image.z_value) return gitem_part
def rota(self): string = '/uis/Sprites/' + str(self.nombre) + '/' + str( self.estado_caminar) pixmap = QPixmap(os.getcwd() + string) pixmap = pixmap.scaled(40, 40) pixmap = pixmap.transformed(QtGui.QTransform().rotate(self.angulo)) self.jugador_label.setPixmap(pixmap) self.mover.emit( Move(self.jugador_label, self.jugador_label.x(), self.jugador_label.y()))
def FlightPicture(self, bird, wUp, left): if (wUp): picture = QPixmap("13g.gif") else: picture = QPixmap("18g.gif") if (left): picture = picture.transformed(QTransform().scale(-1, 1)) picture = picture.scaled(50, 50) bird.setPixmap(picture)
class Ctriunfo(): def __init__(self): self.mi_triunfo = None self.mi_imagen_triunfo = None def ftriunfo(self, carpeta, formato, triunfo): self.mi_triunfo = carpeta + str(triunfo) + formato self.mi_imagen_triunfo = QPixmap(self.mi_triunfo) self.mi_imagen_triunfo = self.mi_imagen_triunfo.transformed( QTransform().rotate(90)) return (self.mi_imagen_triunfo)
def caminar(self): string = '/uis/Sprites/' + str(self.nombre) + '/' + str( self.estado_caminar) pixmap = QPixmap(os.getcwd() + string) pixmap = pixmap.scaled(40, 40) pixmap = pixmap.transformed(QtGui.QTransform().rotate(self.angulo)) self.jugador_label.setPixmap(pixmap) self.estado_caminar += 1 if self.estado_caminar == 4: self.estado_caminar = 1 self.pbar.move(self.jugador_label.x(), self.jugador_label.y() - 7)
class ImageView(QLabel): def __init__(self, img_w): QLabel.__init__(self, img_w) self.img = None def upload_img(self, path_img): """ upload the image to show""" self.img = QPixmap(path_img) self.setMax = False self.resize_img() def resize_img(self): """ resize the image to show """ if self.img.width() > self.img.height(): img_resized = self.img.scaledToWidth(512) else: img_resized = self.img.scaledToHeight(512) self.setMaximumSize(img_resized.width(), img_resized.height()) self.setPixmap(img_resized) self.adjustSize() self.setMax = True def resizeEvent(self, event): """ resize the image as the window size changes (override QWidget method)""" if self.img != None and self.setMax == True: self.setPixmap( self.img.scaled( QSize(self.size().width(), self.size().height()), Qt.KeepAspectRatio)) super().resizeEvent(event) def rotateRight(self): """ rotate the image 90 degrees to the right """ self.img = self.img.transformed(QTransform().rotate(90)) self.resize_img() def rotateLeft(self): """ rotate the image 90 degrees to the left """ self.img = self.img.transformed(QTransform().rotate(-90)) self.resize_img()
def componentToImage(self, component): if component.type == ComponentType.Wire: image = QPixmap("assets/icon.png").scaled(self.blockSideLength, self.blockSideLength) if component.numberOfConnections() == 1: image = QPixmap("assets/wire-top.png").scaled(self.blockSideLength, self.blockSideLength) if component.connections[Direction.Right] is not None: image = image.transformed(QtGui.QTransform().rotate(90)) elif component.connections[Direction.Bottom] is not None: image = image.transformed(QtGui.QTransform().rotate(180)) elif component.connections[Direction.Left] is not None: image = image.transformed(QtGui.QTransform().rotate(270)) elif component.numberOfConnections() == 2: if component.connections[Direction.Left] is not None and component.connections[Direction.Right] is not None: image = QPixmap("assets/wire-left-right.png").scaled(self.blockSideLength, self.blockSideLength) elif component.connections[Direction.Top] is not None and component.connections[Direction.Bottom] is not None: image = QPixmap("assets/wire-left-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(90)) elif component.connections[Direction.Top] is not None and component.connections[Direction.Right] is not None: image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength) elif component.connections[Direction.Top] is not None and component.connections[Direction.Left] is not None: image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(270)) elif component.connections[Direction.Bottom] is not None and component.connections[Direction.Right] is not None: image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(90)) elif component.connections[Direction.Bottom] is not None and component.connections[Direction.Left] is not None: image = QPixmap("assets/wire-top-right.png").scaled(self.blockSideLength, self.blockSideLength).transformed(QtGui.QTransform().rotate(180)) elif component.numberOfConnections() == 3: image = QPixmap("assets/wire-left-top-right.png").scaled(self.blockSideLength, self.blockSideLength) if component.connections[Direction.Left] is None: image = image.transformed(QtGui.QTransform().rotate(90)) elif component.connections[Direction.Top] is None: image = image.transformed(QtGui.QTransform().rotate(180)) elif component.connections[Direction.Right] is None: image = image.transformed(QtGui.QTransform().rotate(270)) return image else: imageName = "assets/wire-right.png" if component.type == ComponentType.Bulb: if component.isOn(): imageName = "assets/bulb-on.png" else: imageName = "assets/bulb-off.png" elif component.type == ComponentType.Switch: if component.closed: imageName = "assets/switch-on.png" else: imageName = "assets/switch-off.png" elif component.type == ComponentType.Button: if component.closed: imageName = "assets/button-on.png" else: imageName = "assets/button-off.png" else: imageName = self.componentTypeToImageName(component.type) return QPixmap(imageName).scaled(self.blockSideLength, self.blockSideLength)
class MainWindow(QMainWindow): """Main window class.""" def __init__(self): """Init class.""" super(MainWindow, self).__init__() self.pixmap_syncthingui = QPixmap(":/images/syncthingui.svg") tf = QTransform() self.pixmap_syncthingui0 = QPixmap(":/images/syncthingui.svg") tf.rotate(90.0) self.pixmap_syncthingui1 = self.pixmap_syncthingui0.transformed(tf) tf.rotate(180.0) self.pixmap_syncthingui2 = self.pixmap_syncthingui0.transformed(tf) tf.rotate(270.0) self.pixmap_syncthingui3 = self.pixmap_syncthingui0.transformed(tf) self.init_gui() self.init_menu() self.init_systray() self.run() def init_gui(self): """init gui setup""" self.setWindowIcon(QIcon(self.pixmap_syncthingui)) self.progressbar = QProgressBar() self.statusBar().showMessage(getoutput(SYNCTHING + ' --version')) self.statusBar().addPermanentWidget(self.progressbar) self.setWindowTitle(__doc__.strip().capitalize()) self.setMinimumSize(900, 600) self.setMaximumSize(1280, 1024) self.resize(self.minimumSize()) self.center() # QWebView # self.view = QWebView(self) self.view = QWebEngineView(self) self.view.loadStarted.connect(self.start_loading) self.view.loadFinished.connect(self.finish_loading) self.view.loadProgress.connect(self.loading) self.view.titleChanged.connect(self.set_title) self.view.page().linkHovered.connect( lambda link_txt: self.statusBar().showMessage(link_txt[:99], 3000)) QShortcut("Ctrl++", self, activated=lambda: self.view.setZoomFactor(self.view.zoomFactor() + 0.2)) QShortcut("Ctrl+-", self, activated=lambda: self.view.setZoomFactor(self.view.zoomFactor() - 0.2)) QShortcut("Ctrl+0", self, activated=lambda: self.view.setZoomFactor(1)) QShortcut("Ctrl+q", self, activated=lambda: self.close()) # syncthing console self.consolewidget = QWidget(self) # TODO: start at specify (w,h) self.consolewidget.setMinimumSize(QSize(200, 100)) # TODO: setStyleSheet # self.consolewidget.setStyleSheet("margin:0px; padding: 0px; \ # border:1px solid rgb(0, 0, 0);") # border-radius: 40px;") # TODO read syncthing console visible from setting # self.consolewidget.setVisible(False) # self.consolewidget.showEvent # self.consoletextedit = QPlainTextEdit(parent=self.consolewidget) self.consoletoolbar = QWidget(self) hlayout = QHBoxLayout() hlayout self.consoletoolbar.setLayout(hlayout) self.consoletextedit = QTextEdit(parent=self.consolewidget) self.consoletextedit.setWordWrapMode(QTextOption.NoWrap) # self.consoletextedit.setStyleSheet(" border:1px solid rgb(0, 0, 0);") # self.consoletextedit.setStyleSheet("margin:0px; padding: 0px;") layout = QVBoxLayout() layout.addWidget(self.consoletoolbar) layout.addWidget(self.consoletextedit) self.consolewidget.setLayout(layout) self.splitter = QSplitter(Qt.Vertical) self.splitter.addWidget(self.view) self.splitter.addWidget(self.consolewidget) # process self.process = QProcess() self.process.error.connect(self._process_failed) # QProcess emits `readyRead` when there is data to be read self.process.readyRead.connect(self._process_dataReady) self.process.stateChanged.connect(self._process_stateChanged) # Just to prevent accidentally running multiple times # Disable the button when process starts, and enable it when it finishes # self.process.started.connect(lambda: self.runButton.setEnabled(False)) # self.process.finished.connect(lambda: self.runButton.setEnabled(True)) # backend options self.chrt = QCheckBox("Smooth CPU ", checked=True) self.ionice = QCheckBox("Smooth HDD ", checked=True) self.chrt.setToolTip("Use Smooth CPUs priority (recommended)") self.ionice.setToolTip("Use Smooth HDDs priority (recommended)") self.chrt.setStatusTip(self.chrt.toolTip()) self.ionice.setStatusTip(self.ionice.toolTip()) # main toolbar self.toolbar = self.addToolBar("SyncthinGUI Toolbar") # self.toolbar.addAction(QIcon.fromTheme("media-playback-stop"), self.toolbar.addAction(QIcon(":/images/stop.svg"), "Stop Sync", lambda: self.syncthing_stop()) # self.toolbar.addAction(QIcon.fromTheme("media-playback-start"), self.toolbar.addAction(QIcon(":/images/start.svg"), "Restart Sync", lambda: self.run()) self.toolbar.addSeparator() self.toolbar.addWidget(self.chrt) self.toolbar.addWidget(self.ionice) self.toolbar.addSeparator() # TODO: test event API self.toolbar.addAction(QIcon(":/images/start.svg"), "test ", lambda: self.test()) # final gui setup self.setCentralWidget(self.splitter) def test(self): """ test some function """ print("test") def init_menu(self): """init menu setup""" # file menu file_menu = self.menuBar().addMenu("File") # TODO: setting menu item file_menu.addAction("Exit", lambda: self.close()) # Syncthing menu sync_menu = self.menuBar().addMenu("Syncthing") sync_menu.addAction("Start Syncronization", lambda: self.run()) sync_menu.addAction("Stop Syncronization", lambda: self.syncthing_stop()) # TODO: restart # TODO: reflash F5 sync_menu.addAction("Open in external browser", lambda: open_new_tab(URL)) # view menu view_menu = self.menuBar().addMenu("View") # TODO: syncthing console menu view_menu.addAction("syncthing console", lambda: self.show_console) # zoom_menu = view_menu.addMenu("Zoom browser") zoom_menu.addAction( "Zoom In", lambda: self.view.setZoomFactor(self.view.zoomFactor() + .2)) zoom_menu.addAction( "Zoom Out", lambda: self.view.setZoomFactor(self.view.zoomFactor() - .2)) zoom_menu.addAction( "Zoom To...", lambda: self.view.setZoomFactor(QInputDialog.getInt( self, __doc__, "<b>Zoom factor ?:", 1, 1, 9)[0])) zoom_menu.addAction("Zoom Reset", lambda: self.view.setZoomFactor(1)) view_menu.addSeparator() act = view_menu.addAction("View Page Source", lambda: self.view_syncthing_source) act.setDisabled(True) # window menu window_menu = self.menuBar().addMenu("&Window") window_menu.addAction("Minimize", lambda: self.showMinimized()) window_menu.addAction("Maximize", lambda: self.showMaximized()) window_menu.addAction("Restore", lambda: self.showNormal()) window_menu.addAction("Center", lambda: self.center()) window_menu.addAction("Top-Left", lambda: self.move(0, 0)) window_menu.addAction("To Mouse", lambda: self.move_to_mouse_position()) window_menu.addAction("Fullscreen", lambda: self.showFullScreen()) window_menu.addSeparator() window_menu.addAction("Increase size", lambda: self.resize( self.size().width() * 1.2, self.size().height() * 1.2)) window_menu.addAction("Decrease size", lambda: self.resize( self.size().width() // 1.2, self.size().height() // 1.2)) window_menu.addAction("Minimum size", lambda: self.resize(self.minimumSize())) window_menu.addAction("Maximum size", lambda: self.resize(self.maximumSize())) window_menu.addAction("Horizontal Wide", lambda: self.resize( self.maximumSize().width(), self.minimumSize().height())) window_menu.addAction("Vertical Tall", lambda: self.resize( self.minimumSize().width(), self.maximumSize().height())) window_menu.addSeparator() window_menu.addAction("Disable Resize", lambda: self.setFixedSize(self.size())) # help menu help_menu = self.menuBar().addMenu("&Help") help_menu.addAction("Support Forum", lambda: open_new_tab(HELP_URL_0)) help_menu.addAction("Lastest Release", lambda: open_new_tab(HELP_URL_1)) help_menu.addAction("Documentation", lambda: open_new_tab(HELP_URL_2)) help_menu.addAction("Bugs", lambda: open_new_tab(HELP_URL_3)) help_menu.addAction("Source Code", lambda: open_new_tab(HELP_URL_4)) help_menu.addSeparator() help_menu.addAction("About Qt 5", lambda: QMessageBox.aboutQt(self)) help_menu.addAction("About Python 3", lambda: open_new_tab('https://www.python.org')) help_menu.addAction("About " + __doc__, lambda: QMessageBox.about(self, __doc__, HELPMSG)) help_menu.addSeparator() help_menu.addAction("Keyboard Shortcuts", lambda: QMessageBox.information(self, __doc__, SHORTCUTS)) help_menu.addAction("View GitHub Repo", lambda: open_new_tab(__url__)) if not sys.platform.startswith("win"): help_menu.addAction("Show Source Code", lambda: self.view_source()) help_menu.addSeparator() help_menu.addAction("Check Updates", lambda: self.check_for_updates()) def init_systray(self): """init system tray icon""" # self.tray = QSystemTrayIcon(QIcon(self.pixmap_syncthingui), self) self.tray = AnimatedSysTrayIcon(QIcon(self.pixmap_syncthingui), self) self.tray.add_ani_icon(QIcon(self.pixmap_syncthingui0)) self.tray.add_ani_icon(QIcon(self.pixmap_syncthingui1)) self.tray.add_ani_icon(QIcon(self.pixmap_syncthingui2)) self.tray.add_ani_icon(QIcon(self.pixmap_syncthingui3)) self.tray.setToolTip(__doc__.strip().capitalize()) traymenu = QMenu(self) traymenu.addAction(__doc__).setDisabled(True) traymenu.addSeparator() # to test animate # traymenu.addAction("start", lambda: self.tray.animate_start()) # traymenu.addAction("stop", lambda: self.tray.animate_stop()) # traymenu.addSeparator() traymenu.addAction("Stop Sync", lambda: self.syncthing_stop()) traymenu.addAction("Restart Sync", lambda: self.run()) traymenu.addSeparator() traymenu.addAction("Show", lambda: self.show_gui()) traymenu.addAction("Hide", lambda: self.hide()) traymenu.addSeparator() # traymenu.addAction("Open Web", lambda: open_new_tab(URL)) # traymenu.addAction("Quit All", lambda: self.close()) traymenu.addAction("Quit All", lambda: self.app_exit()) self.tray.setContextMenu(traymenu) self.tray.show() def show_gui(self): """ Helper method to show UI, this should not be needed, but I discovered. """ self.showNormal() # webview require 70Mb to show webpage self.view.load(QUrl(URL)) def syncthing_start(self): """syncthing start""" self.run() def syncthing_stop(self): """syncthing stop""" print("try to stop syncthing") self.process.kill() # check there is no other syncthing is running! for proc in psutil.process_iter(): # check whether the process name matches # print("procress: %s " % proc.name()) if proc.name() == SYNCTHING: proc.kill() def run(self): """Run bitch run!.""" # Stop first! self.syncthing_stop() command_to_run_syncthing = " ".join(( "ionice --ignore --class 3" if self.ionice.isChecked() else "", "chrt --verbose --idle 0" if self.chrt.isChecked() else "", SYNCTHING, "-no-browser")) print(command_to_run_syncthing) self.process.start(command_to_run_syncthing) if not self.process.waitForStarted(): self._process_failed() @pyqtSlot() def _process_failed(self): """Read and return errors.""" self.statusBar().showMessage("ERROR:Fail:Syncthing blow up in pieces!") print("ERROR:Fail:Syncthing blow up in pieces! Wheres your God now?") return str(self.process.readAllStandardError()).strip().lower() @pyqtSlot() def _process_dataReady(self): """get process stdout/strerr when data ready""" # TODO: format the msg to remove extra b and \n msg = str(self.process.readAll()) lines = msg.split("'") tmp = lines[1] tmp = tmp.splitlines(0) lines = tmp[0].split("\\n") for line in lines: if line != "": # print("1: %s" % line) self.consoletextedit.append(line) self.consoletextedit.ensureCursorVisible() # autoscroll to last line's first character self.consoletextedit.moveCursor(QTextCursor.End) self.consoletextedit.moveCursor(QTextCursor.StartOfLine) @pyqtSlot(QProcess.ProcessState) def _process_stateChanged(self, state): """ procress_stateChanged """ # TODO handle procress_stateChanged print("procress_stateChanged: %s" % state) def center(self): """Center Window on the Current Screen,with Multi-Monitor support.""" window_geometry = self.frameGeometry() mousepointer_position = QApplication.desktop().cursor().pos() screen = QApplication.desktop().screenNumber(mousepointer_position) centerpoint = QApplication.desktop().screenGeometry(screen).center() window_geometry.moveCenter(centerpoint) self.move(window_geometry.topLeft()) def move_to_mouse_position(self): """Center the Window on the Current Mouse position.""" window_geometry = self.frameGeometry() window_geometry.moveCenter(QApplication.desktop().cursor().pos()) self.move(window_geometry.topLeft()) def show_console(self): """Show syncthing console""" visible = not self.consolewidget.isVisible print("bVisible: %s" % visible) self.consolewidget.setVisible(True) self.consolewidget.resize(QSize(200, 100)) def view_source(self): """ TODO: Call methods to load and display source code.""" # call(('xdg-open ' if sys.platform.startswith("linux") else 'open ') # + __file__, shell=True) pass def view_syncthing_source(self): """Call methods to load and display web page source code.""" print("view_syncthing_source start") # access_manager = self.view.page().networkAccessManager() # reply = access_manager.get(QNetworkRequest(self.view.url())) # reply.finished.connect(self.slot_source_downloaded) def slot_source_downloaded(self): """Show actual page source code.""" reply = self.sender() # TODO: highlight html source editor/viewer self.textedit = QPlainTextEdit() self.textedit.setAttribute(Qt.WA_DeleteOnClose) self.textedit.setReadOnly(True) self.textedit.setPlainText(QTextStream(reply).readAll()) self.textedit.show() reply.deleteLater() @pyqtSlot() def start_loading(self): """show progressbar when downloading data""" self.progressbar.show() @pyqtSlot(bool) def finish_loading(self, finished): """Finished loading content.""" if not finished: # TODO: When loading fail, what should we do? print("load fail") if self.process.state() == QProcess.NotRunning: self.run() self.view.reload() # if self.process.state != QProcess.Running: # print("syncthing is not running: %s" % self.process.state()) # pass print("finish_loading: %s" % finished) # TODO: WebEngineView does not have following function? # self.view.settings().clearMemoryCaches() # self.view.settings().clearIconDatabase() # print("finish_loading %s" % datetime.strftime(datetime.now(), # '%Y-%m-%d %H:%M:%S')) # TODO: following line need 6 sec to finish!! # TODO: (" INFO: Loading Web UI increases >250Mb RAM!.") # self.view.page().mainFrame().evaluateJavaScript(BASE_JS) # print("finish_loading %s" % datetime.strftime(datetime.now(), # '%Y-%m-%d %H:%M:%S')) self.progressbar.hide() @pyqtSlot(int) def loading(self, idx): """loading content""" #print("loading %s" % idx) self.progressbar.setValue(idx) @pyqtSlot(str) def set_title(self, title): """set title when webview's title change""" # print("title: %s" % title) if len(title.strip()) > 0: self.setWindowTitle(self.view.title()[:99]) def check_for_updates(self): """Method to check for updates from Git repo versus this version.""" # print("TODO: https://github.com/coolshou/syncthingui/releases/latest") print("__version__: %s" % __version__) ''' this_version = str(open(__file__).read()) print("this_version: %s" % this_version) last_version = str(request.urlopen(__source__).read().decode("utf8")) print("last_version: %s" % last_version) TODO: previous use file compare, when diff then there is new file!! if this_version != last_version: m = "Theres new Version available!<br>Download update from the web" else: m = "No new updates!<br>You have the lastest version of" + __doc__ return QMessageBox.information(self, __doc__.title(), "<b>" + m) ''' def closeEvent(self, event): """Ask to Quit.""" if self.tray.isVisible(): if self.tray.supportsMessages(): self.tray.showMessage("Info", "The program will keep running in the " "system tray. To terminate the program," " choose <b>Quit</b> in the context " "menu of the system tray entry.") else: print(" System tray not supports balloon messages ") self.hide() event.ignore() def app_exit(self): """exit app""" # TODO: do we need to show UI when doing close? # self.show_gui() # TODO: show QMessageBox on all virtual desktop the_conditional_is_true = QMessageBox.question( self, __doc__.title(), 'Quit %s?' % __doc__, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes if the_conditional_is_true: self.syncthing_stop() self.ani_stop = True QApplication.instance().quit quit()
class OverviewCity(QDialog): closed_status_dialogue = pyqtSignal([bool]) units_dico = {'metric': '°C', 'imperial': '°F', ' ': '°K'} def __init__(self, weatherdata, icon, forecast, dayforecast, unit, icon_url, uv_coord, parent=None): super(OverviewCity, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.days_dico = {'0': self.tr('Mon'), '1': self.tr('Tue'), '2': self.tr('Wed'), '3': self.tr('Thu'), '4': self.tr('Fri'), '5': self.tr('Sat'), '6': self.tr('Sun')} cond = conditions.WeatherConditions() self.conditions = cond.trans self.precipitation = cond.rain self.wind_direction = cond.wind_codes self.wind_name_dic = cond.wind self.clouds_name_dic = cond.clouds self.uv_risk = cond.uv_risk self.uv_recommend = cond.uv_recommend self.settings = QSettings() self.tree = forecast self.tree_day = dayforecast self.icon_url = icon_url self.uv_coord = uv_coord self.forecast_weather_list = [] self.dayforecast_weather_list = [] self.weatherdata = weatherdata self.icon_list = [] self.dayforecast_icon_list = [] self.unit_temp = self.units_dico[unit] self.total_layout = QVBoxLayout() # ----First part overview day ----- self.over_layout = QVBoxLayout() self.dayforecast_layout = QHBoxLayout() self.dayforecast_temp_layout = QHBoxLayout() # --------------------------------- self.city_label = QLabel( '<font size="4"><b>' + self.weatherdata['City'] + ', ' + self.weatherdata['Country']+'<\b><\font>') self.over_layout.addWidget(self.city_label) self.icontemp_layout = QHBoxLayout() self.icon_label = QLabel() self.icon_label.setPixmap(icon) self.icontemp_layout.addWidget(self.icon_label) self.temp_label = QLabel( '<font size="5"><b>' + '{0:.1f}'.format( float(self.weatherdata['Temp'][:-1])) + ' ' + self.unit_temp + '<\b><\font>') self.icontemp_layout.addWidget(self.temp_label) self.over_layout.addLayout(self.icontemp_layout) self.weather = QLabel('<font size="4"><b>' + self.weatherdata['Meteo'] + '<\b><\font>') self.icontemp_layout.addWidget(self.weather) self.icontemp_layout.addStretch() self.over_layout.addLayout(self.dayforecast_layout) self.over_layout.addLayout(self.dayforecast_temp_layout) # ------Second part overview day--------- self.over_grid = QGridLayout() # Wind self.wind_label = QLabel('<font size="3" color=grey><b>' + self.tr('Wind') + '<\font><\b>') self.wind_label.setAlignment(Qt.AlignTop) wind_unit = self.settings.value('Unit') or 'metric' self.speed_unit = ' m/s ' if wind_unit == 'imperial': self.speed_unit = ' mph ' self.wind = QLabel('None') try: self.wind = QLabel('<font color=grey>' + self.weatherdata['Wind'][4] + ' ' + self.weatherdata['Wind'][2] + '° ' + '<br/>' + '{0:.1f}'.format(float(self.weatherdata['Wind'][0])) + self.speed_unit + self.weatherdata['Wind'][1] + '<\font>') except: logging.error('Cannot find wind informations:\n' + str(self.weatherdata['Wind'])) self.wind_icon_label = QLabel() self.wind_icon_label.setAlignment(Qt.AlignLeft) self.wind_icon = QPixmap(':/arrow') self.wind_icon_direction() # ---------------- self.clouds_label = QLabel('<font size="3" color=grey><b>' + self.tr('Cloudiness') + '<\b><\font>') self.clouds_name = QLabel('<font color=grey>' + self.weatherdata['Clouds'] + '<\font>') self.pressure_label = QLabel('<font size="3" color=grey><b>' + self.tr('Pressure') + '<\b><\font>') self.pressure_value = QLabel('<font color=grey>' + str(round(float(self.weatherdata['Pressure'][0]))) + ' ' + self.weatherdata['Pressure'][1] + '<\font>') self.humidity_label = QLabel('<font size="3" color=grey><b>' + self.tr('Humidity') + '<\b><\font>') self.humidity_value = QLabel('<font color=grey>' + self.weatherdata['Humidity'][0] + ' ' + self.weatherdata['Humidity'][1] + '<\font>') self.precipitation_label = QLabel('<font size="3" color=grey><b>' + QCoreApplication.translate('Precipitation type (no/rain/snow)', 'Precipitation', 'Weather overview dialogue') + '<\b><\font>') rain_mode = self.precipitation[self.weatherdata['Precipitation'][0]] rain_value = self.weatherdata['Precipitation'][1] rain_unit = ' mm ' if rain_value == '': rain_unit = '' else: if wind_unit == 'imperial': rain_unit = 'inch' rain_value = str(float(rain_value) / 25.4) rain_value = "{0:.4f}".format(float(rain_value)) else: rain_value = "{0:.2f}".format(float(rain_value)) self.precipitation_value = QLabel('<font color=grey>' + rain_mode + ' ' + rain_value + ' ' + rain_unit + '</font>') self.sunrise_label = QLabel('<font color=grey><b>' + self.tr('Sunrise') + '</b></font>') self.sunset_label = QLabel('<font color=grey><b>' + self.tr('Sunset') + '</b></font>') rise_str = self.utc('Sunrise', 'weatherdata') set_str = self.utc('Sunset', 'weatherdata') self.sunrise_value = QLabel('<font color=grey>' + rise_str[:-3] + '</font>') self.sunset_value = QLabel('<font color=grey>' + set_str[:-3] + '</font>') # --UV--- self.uv_label = QLabel( '<font size="3" color=grey><b>' + QCoreApplication.translate( 'Ultraviolet index', 'UV', 'Label in weather info dialogue' + '<\b><\font>')) self.uv_label.setAlignment(Qt.AlignTop) fetching_text = ('<font color=grey>' + QCoreApplication.translate( 'Ultraviolet index', 'Fetching...', '' + '<\font>')) self.uv_value_label = QLabel() self.uv_value_label.setText(fetching_text) # Ozone self.ozone_label = QLabel( '<font size="3" color=grey><b>' + QCoreApplication.translate( 'Ozone data title', 'Ozone', 'Label in weather info dialogue' + '<\b><\font>')) self.ozone_value_label = QLabel() self.ozone_value_label.setText(fetching_text) self.over_grid.addWidget(self.wind_label, 0, 0) self.over_grid.addWidget(self.wind, 0, 1) self.over_grid.addWidget(self.wind_icon_label, 0, 2) self.over_grid.addWidget(self.clouds_label, 1, 0) self.over_grid.addWidget(self.clouds_name, 1, 1) self.over_grid.addWidget(self.pressure_label, 2, 0) self.over_grid.addWidget(self.pressure_value, 2, 1) self.over_grid.addWidget(self.humidity_label, 3, 0) self.over_grid.addWidget(self.humidity_value, 3, 1, 1, 3) # align left self.over_grid.addWidget(self.precipitation_label, 4, 0) self.over_grid.addWidget(self.precipitation_value, 4, 1) self.over_grid.addWidget(self.sunrise_label, 5, 0) self.over_grid.addWidget(self.sunrise_value, 5, 1) self.over_grid.addWidget(self.sunset_label, 6, 0) self.over_grid.addWidget(self.sunset_value, 6, 1) self.over_grid.addWidget(self.uv_label, 7, 0) self.over_grid.addWidget(self.uv_value_label, 7, 1) self.over_grid.addWidget(self.ozone_label, 8, 0) self.over_grid.addWidget(self.ozone_value_label, 8, 1) # -------------Forecast------------- self.forecast_days_layout = QHBoxLayout() self.forecast_icons_layout = QHBoxLayout() self.forecast_minmax_layout = QHBoxLayout() # ---------------------------------- self.total_layout.addLayout(self.over_layout) self.total_layout.addLayout(self.over_grid) self.total_layout.addLayout(self.forecast_icons_layout) self.total_layout.addLayout(self.forecast_days_layout) self.total_layout.addLayout(self.forecast_minmax_layout) self.forecastdata() logging.debug('Fetched forecast data') self.iconfetch() logging.debug('Fetched 6 days forecast icons') self.dayforecastdata() logging.debug('Fetched day forecast data') self.dayiconfetch() logging.debug('Fetched day forcast icons') self.uv_fetch() logging.debug('Fetched uv index') self.ozone_fetch() logging.debug('Fetched ozone data') self.setLayout(self.total_layout) self.setWindowTitle(self.tr('Weather status')) self.restoreGeometry(self.settings.value("OverviewCity/Geometry", QByteArray())) def wind_icon_direction(self): transf = QTransform() angle = self.weatherdata['Wind'][2] logging.debug('Wind degrees direction: ' + angle) transf.rotate(int(float(angle))) rotated = self.wind_icon.transformed(transf, mode=Qt.SmoothTransformation) self.wind_icon_label.setPixmap(rotated) def ozone_du(self, du): if du <= 125: return '#060106' # black if du <= 150: return '#340634' # magenta if du <= 175: return '#590b59' # fuccia if du <= 200: return '#421e85' # violet if du <= 225: return '#121e99' # blue if du <= 250: return '#125696' # blue sea if du <= 275: return '#198586' # raf if du <= 300: return '#21b1b1' # cyan if du <= 325: return '#64b341' # light green if du <= 350: return '#1cac1c' # green if du <= 375: return '#93a92c' # green oil if du <= 400: return '#baba2b' # yellow if du <= 425: return '#af771f' # orange if du <= 450: return '#842910' # brown if du <= 475: return '#501516' # brown dark if du > 475: return '#210909' # darker brown def uv_color(self, uv): try: uv = float(uv) except: return ('grey', 'None') if uv <= 2.9: return ('green', 'Low') if uv <= 5.9: return ('yellow', 'Moderate') if uv <= 7.9: return ('orange', 'High') if uv <= 10.9: return ('red', 'Very high') if uv >= 11: return ('purple', 'Extreme') def utc(self, rise_set, what): ''' Convert sun rise/set from UTC to local time 'rise_set' is 'Sunrise' or 'Sunset when it is for weatherdata or the index of hour in day forecast when dayforecast''' listtotime = '' # Create a list ['h', 'm', 's'] and pass it to QTime if what == 'weatherdata': listtotime = self.weatherdata[rise_set].split('T')[1].split(':') elif what == 'dayforecast': listtotime = self.tree_day[4][rise_set].get('from').split( 'T')[1].split(':') suntime = QTime(int(listtotime[0]), int(listtotime[1]), int( listtotime[2])) # add the diff UTC-local in seconds utc_time = suntime.addSecs(time.localtime().tm_gmtoff) utc_time_str = utc_time.toString() return utc_time_str def forecastdata(self): '''Forecast for the next 6 days''' # Some times server sends less data doc = QTextDocument() periods = 7 fetched_file_periods = (len(self.tree.xpath('//time'))) if fetched_file_periods < periods: periods = fetched_file_periods logging.warn('Reduce forecast for the next 6 days to {0}'.format( periods-1)) for d in range(1, periods): date_list = self.tree[4][d].get('day').split('-') day_of_week = str(datetime.date( int(date_list[0]), int(date_list[1]), int(date_list[2])).weekday()) label = QLabel('' + self.days_dico[day_of_week] + '') label.setToolTip(self.tree[4][d].get('day')) label.setAlignment(Qt.AlignHCenter) self.forecast_days_layout.addWidget(label) mlabel = QLabel( '<font color=grey>' + '{0:.0f}'.format(float( self.tree[4][d][4].get('min'))) + '°<br/>' + '{0:.0f}'.format(float(self.tree[4][d][4].get('max'))) + '°</font>') mlabel.setAlignment(Qt.AlignHCenter) mlabel.setToolTip(self.tr('Min Max Temperature of the day')) self.forecast_minmax_layout.addWidget(mlabel) self.icon_list.append(self.tree[4][d][0].get('var')) # icon weather_cond = self.tree[4][d][0].get('name') try: weather_cond = self.conditions[self.tree[4][d][0].get( 'number')] except: logging.warn('Cannot find localisation string for :' + weather_cond) pass try: doc.setHtml(self.precipitation_label.text()) precipitation_label = doc.toPlainText() + ': ' precipitation_type = self.tree[4][d][1].get('type') precipitation_type = self.precipitation[precipitation_type] + ' ' precipitation_value = self.tree[4][d][1].get('value') rain_unit = ' mm' if self.speed_unit == ' mph ': rain_unit = ' inch' precipitation_value = str(float(precipitation_value) / 25.4) + ' ' precipitation_value = "{0:.2f}".format(float(precipitation_value)) else: precipitation_value = "{0:.1f}".format(float(precipitation_value)) weather_cond += ('\n' + precipitation_label + precipitation_type + precipitation_value + rain_unit) except: pass doc.setHtml(self.wind_label.text()) wind = doc.toPlainText() + ': ' try: wind_direction = self.wind_direction[self.tree[4][d][2].get('code')] except: wind_direction = '' wind_speed = '{0:.1f}'.format(float(self.tree[4][d][3].get('mps'))) weather_cond += '\n' + wind + wind_speed + self.speed_unit + wind_direction doc.setHtml(self.pressure_label.text()) pressure_label = doc.toPlainText() + ': ' pressure = '{0:.1f}'.format(float(self.tree[4][d][5].get('value'))) weather_cond += '\n' + pressure_label + pressure + ' hPa' humidity = self.tree[4][d][6].get('value') doc.setHtml(self.humidity_label.text()) humidity_label = doc.toPlainText() + ': ' weather_cond += '\n' + humidity_label + humidity + ' %' clouds = self.tree[4][d][7].get('all') doc.setHtml(self.clouds_label.text()) clouds_label = doc.toPlainText() + ': ' weather_cond += '\n' + clouds_label + clouds + ' %' self.forecast_weather_list.append(weather_cond) def iconfetch(self): logging.debug('Download 6 days forecast icons...') self.download_thread = IconDownload(self.icon_url, self.icon_list) self.download_thread.wimage['PyQt_PyObject'].connect(self.iconwidget) self.download_thread.url_error_signal['QString'].connect(self.error) self.download_thread.start() def iconwidget(self, icon): '''6 days forecast icons''' image = QImage() image.loadFromData(icon) iconlabel = QLabel() iconlabel.setAlignment(Qt.AlignHCenter) iconpixmap = QPixmap(image) iconlabel.setPixmap(iconpixmap) iconlabel.setToolTip(self.forecast_weather_list.pop(0)) self.forecast_icons_layout.addWidget(iconlabel) def dayforecastdata(self): '''Fetch forecast for the day''' # Some times server sends less data periods = 7 fetched_file_periods = (len(self.tree_day.xpath('//time'))) if fetched_file_periods < periods: periods = fetched_file_periods logging.warn('Reduce forecast of the day to {0}'.format(periods-1)) for d in range(1, periods): timeofday = self.utc(d, 'dayforecast') weather_cond = self.conditions[self.tree_day[4][d][0].get('number')] self.dayforecast_weather_list.append(weather_cond) # icon self.dayforecast_icon_list.append(self.tree_day[4][d][0].get('var')) daytime = QLabel( '<font color=grey>' + timeofday[:-3] + '<br/>' + '{0:.0f}'.format(float(self.tree_day[4][d][4].get('value'))) + '°' + '</font>') daytime.setAlignment(Qt.AlignHCenter) unit = self.settings.value('Unit') or 'metric' precipitation = str(self.tree_day[4][d][1].get('value')) if unit == 'metric': mu = 'mm' elif unit == 'imperial': mu = 'inch' if precipitation.count('None') == 0: precipitation = str(float(precipitation) / 25.0) ttip = (precipitation + ' ' + mu + ' ' + str(self.tree_day[4][d][1].get('type')) + '<br/>') if ttip.count('None') >= 1: ttip = '' else: ttip = ttip.replace('snow', self.tr('snow')) ttip = ttip.replace('rain', self.tr('rain')) # Winddirection/speed windspeed = self.tree_day[4][d][3].get('mps') ttip = ttip + (windspeed + ' ' + self.speed_unit) winddircode = self.tree_day[4][d][2].get('code') wind = '' if winddircode != '': wind = self.wind_direction[winddircode] + ' ' else: logging.warn('Wind direction code is missing: ' + str(winddircode)) wind_name = self.tree_day[4][d][3].get('name') try: wind_name_translated = ( self.conditions[self.wind_name_dic[wind_name.lower()]] + '<br/>') wind += wind_name_translated except KeyError: logging.warn('Cannot find wind name :' + str(wind_name)) logging.info('Set wind name to None') wind = '' finally: if wind == '': wind += '<br/>' # Clouds clouds_translated = '' clouds = self.tree_day[4][d][7].get('value') cloudspercent = self.tree_day[4][d][7].get('all') if clouds != '': clouds_translated = self.conditions[self.clouds_name_dic[clouds.lower()]] else: logging.warn('Clouding name is missing: ' + str(clouds)) clouds_cond = clouds_translated + ' ' + cloudspercent + '%' ttip = ttip + wind + clouds_cond daytime.setToolTip(ttip) self.dayforecast_temp_layout.addWidget(daytime) def ozone_fetch(self): logging.debug('Download ozone info...') self.ozone_thread = Ozone(self.uv_coord) self.ozone_thread.o3_signal['PyQt_PyObject'].connect(self.ozone_index) self.ozone_thread.start() def ozone_index(self, index): try: du = int(index) o3_color = self.ozone_du(du) factor = str(du)[:1] + '.' + str(du)[1:2] gauge = '◼' * round(float(factor)) logging.debug('Ozone gauge: ' + gauge) except: du = '-' o3_color = None du_unit = QCoreApplication.translate('Dobson Units', 'DU', 'Ozone value label') if o3_color is not None: self.ozone_value_label.setText('<font color=grey>' + str(du) + ' ' + du_unit + '</font>' + '<font color=' + o3_color + '> ' + gauge + '</font>') self.ozone_value_label.setToolTip(QCoreApplication.translate( 'Ozone value tooltip', '''The average amount of ozone in the <br/> atmosphere is roughly 300 Dobson Units. What scientists call the Antarctic Ozone “Hole” is an area where the ozone concentration drops to an average of about 100 Dobson Units.''', 'http://ozonewatch.gsfc.nasa.gov/facts/dobson_SH.html')) else: self.ozone_value_label.setText('<font color=grey>' + str(du) + '</font>') def uv_fetch(self): logging.debug('Download uv info...') self.uv_thread = Uv(self.uv_coord) self.uv_thread.uv_signal['PyQt_PyObject'].connect(self.uv_index) self.uv_thread.start() def uv_index(self, index): uv_gauge = '-' uv_color = self.uv_color(index) if uv_color[1] != 'None': uv_gauge = '◼' * int(round(float(index))) if uv_gauge == '': uv_gauge = '◼' self.uv_value_label.setText('<font color=grey>' + '{0:.1f}'.format(float(index)) + ' ' + self.uv_risk[uv_color[1]] + '</font>' + '<br/>' + '< font color=' + uv_color[0] + '><b>' + uv_gauge + '</b></font>') else: self.uv_value_label.setText(uv_gauge) logging.debug('UV gauge ◼: ' + uv_gauge) self.uv_value_label.setToolTip(self.uv_recommend[uv_color[1]]) def dayiconfetch(self): '''Icons for the forecast of the day''' logging.debug('Download forecast icons for the day...') self.day_download_thread = IconDownload(self.icon_url, self.dayforecast_icon_list) self.day_download_thread.wimage['PyQt_PyObject'].connect(self.dayiconwidget) self.day_download_thread.url_error_signal['QString'].connect(self.error) self.day_download_thread.start() def dayiconwidget(self, icon): '''Forecast icons of the day''' image = QImage() image.loadFromData(icon) iconlabel = QLabel() iconlabel.setAlignment(Qt.AlignHCenter) iconpixmap = QPixmap(image) iconlabel.setPixmap(iconpixmap) iconlabel.setToolTip(self.dayforecast_weather_list.pop(0)) self.dayforecast_layout.addWidget(iconlabel) def error(self, error): logging.error('error in download of forecast icon:\n' + error) def moveEvent(self, event): self.settings.setValue("OverviewCity/Geometry", self.saveGeometry()) def resizeEvent(self, event): self.settings.setValue("OverviewCity/Geometry", self.saveGeometry()) def hideEvent(self, event): self.settings.setValue("OverviewCity/Geometry", self.saveGeometry()) def closeEvent(self, event): self.settings.setValue("OverviewCity/Geometry", self.saveGeometry()) exit = True self.closed_status_dialogue.emit(exit)