terça-feira, 7 de dezembro de 2010

Uso de Python3 em programação desktop usando PyQt4

O python3 é parcialmente incompatível com o Python2.x, e isso é um grande problema principalmente porque existem milhares de bibliotecas prontas e funcionando bem com o python2 , a realidade é que igualmente ao XP o python2.x vai demorar muito tempo para morrer, principalmente nos frameworks web que possuem uma boa gama de módulos prontinhos e funcionando.
No entanto o Python3 trouxe consigo diversas melhorias com relação à sua versão anterior, e a mais notável com certeza é a de uso de strings unicode, agora é possível criar uma variável com o nome "maçã" por exemplo. Em especial, o PyQt4 também sofreu muitas mudanças, na realidade ele ficou mais simples, uma porcão de objetos que antes existiam no PyQt4 para python2.x não existem mais para o PyQt4 para python3, o que causa problemas ao tentar executar programas em PyQt4 escritos para rodarem no Python2.x, existem algumas "gambiarras" como essa abaixo, no entanto esse método possui algumas falhas graves em relação a uma outra opção que eu coloquei no final do post que é o uso da biblioteca sip do python3, nesse exemplo a QString irá funcionar, no entanto os métodos dela estarão ausente causando dores de cabeça, em seguida eu coloquei um exemplo de uma calculadora simples em PyQt feita por uma amiga que está estudando a linguagem e eu resolvi alterar algumas coisas para colocar como exemplo aqui, é um bom começo para estudo, o código principal pode ser salvo com o nome calculadora.py e o da classe de interface obrigatoriamente tem que ser ui_calculadora.py porque ele é importado para a classe principal.

try:
    from PyQt4.QtCore import QString
except ImportError:
    # we are using Python3 so QString is not defined
    QString = type("") 
 
Eis o Exemplo em Python 2.x 
 
#!/usr/bin/python
# -*- coding: utf-8 -*-
#importação dos módulos das bibliotecas Qt
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore
import ui_calculadora
#Importação dos módulos personalizados
class Calculadora(QMainWindow, ui_calculadora.Ui_Calculadora):
    
    '''
        Classe Principal que cria uma agenda eletrônica Simples :D
    '''
# método init construtor da classe...
    def __init__(self, parent=None):
        #os dois comandos abaixo inicializa a classe com as duas das quais ela herdou métodos e atributos
        #QMainWindow que é uma classe base do Qt framework e ui_calculadora que é a interface criada
        super(Calculadora, self).__init__(parent)
        self.setupUi(self)
        self.edicao = True
        self.memoria = 0
        #conectando os objetos da interface com as funções
        self.connect(self.btnMemoriaNegativa, SIGNAL("clicked()"), self.memoriaNegativa)
        self.connect(self.btnMemoriaPositiva, SIGNAL("clicked()"), self.memoriaPositiva)
        self.connect(self.btnLimparMemoria, SIGNAL("clicked()"), self.limparMemoria)
        self.connect(self.btnNumeros, SIGNAL("buttonClicked(QAbstractButton*)"), self.botaoClickado)
        self.connect(self.btnIgual, SIGNAL("clicked()"), self.resultado)
    
    def limparMemoria(self):
        self.memoria = 0
        self.lblMensagem.setText("0")
        self.edicao = False
    def memoriaNegativa(self):
        self.memoria -= float(str(self.txtCalculo.text()))
        self.lblMensagem.setText(str(self.memoria))
        self.edicao = False
    def memoriaPositiva(self):
        self.memoria += float(str(self.txtCalculo.text()))
        self.lblMensagem.setText(str(self.memoria))
        self.edicao = False
    
    def botaoClickado(self, botao):
        if self.edicao:
            self.txtCalculo.insert(botao.text().toUpper())
        else:
            self.txtCalculo.setText(botao.text().toUpper())
            self.edicao = True
    
    def resultado(self):
        try:
            resultado = eval(str(self.txtCalculo.text() + "."))
            self.txtCalculo.setText(str(resultado))
            self.edicao = False
        except:
            # o caractere u antes da string indica que a mesma é unicode...
            QMessageBox.information(self, u"Expressão incorreta", u"Você digitou uma expressão incorreta",
                                    buttons=QMessageBox.Ok)
            self.txtCalculo.clear()    

#Função que inicializa o aplicativo
if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    formulario = Calculadora()
    formulario.show()
    app.exec_()


Agora a Versão em Python3


#!/usr/bin/python
# -*- coding: utf-8 -*-
#importação dos módulos das bibliotecas Qt
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore
import ui_calculadora
#Importação dos módulos personalizados
class Calculadora(QMainWindow, ui_calculadora.Ui_Calculadora):
    '''
        Classe Principal que cria uma agenda eletrônica Simples :D
    '''
# método init construtor da classe...
    def __init__(self, parent=None):
        #os dois comandos abaixo inicializa a classe com as duas das quais ela herdou métodos e atributos
        #QMainWindow que é uma classe base do Qt framework e ui_calculadora que é a interface criada
        super(Calculadora, self).__init__(parent)
        self.setupUi(self)
        self.edicao = True
        self.memoria = 0
        #conectando os objetos da interface com as funções
        self.connect(self.btnMemoriaNegativa, SIGNAL("clicked()"), self.memoriaNegativa)
        self.connect(self.btnMemoriaPositiva, SIGNAL("clicked()"), self.memoriaPositiva)
        self.connect(self.btnLimparMemoria, SIGNAL("clicked()"), self.limparMemoria)
        self.connect(self.btnNumeros, SIGNAL("buttonClicked(QAbstractButton*)"), self.botaoClickado)
        self.connect(self.btnIgual, SIGNAL("clicked()"), self.resultado)
    
    def limparMemoria(self):
        self.memoria = 0
        self.lblMensagem.setText("0")
        self.edicao = False
    def memoriaNegativa(self):
        self.memoria -= float(str(self.txtCalculo.text()))
        self.lblMensagem.setText(str(self.memoria))
        self.edicao = False
    def memoriaPositiva(self):
        self.memoria += float(str(self.txtCalculo.text()))
        self.lblMensagem.setText(str(self.memoria))
        self.edicao = False
    
    def botaoClickado(self, botao):
        if self.edicao:
            self.txtCalculo.insert(botao.text())
        else:
            self.txtCalculo.setText(botao.text())
            self.edicao = True
    
    def resultado(self):
        try:
            resultado = eval(str(self.txtCalculo.text() + "."))
            self.txtCalculo.setText(str(resultado))
            self.edicao = False
        except:
            # o caractere u antes da string indica que a mesma é unicode...
            QMessageBox.information(self, "Expressão incorreta", "Você digitou uma expressão incorreta",
                                    buttons=QMessageBox.Ok)
            self.txtCalculo.clear()    

#Função que inicializa o aplicativo
if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    formulario = Calculadora()
    formulario.show()
    app.exec_()


Agora o arquivo de interface(ui_calculadora.py) ele funciona normal em python2 ou 3, lembrando que ele foi feito usando o pyuic4 através de um arquivo ui do QtDesigner.


# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'calculadora.ui'
#
# Created: Tue Nov 30 20:07:38 2010
#      by: PyQt4 UI code generator 4.8.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Calculadora(object):
    def setupUi(self, Calculadora):
        Calculadora.setObjectName(_fromUtf8("Calculadora"))
        Calculadora.resize(419, 344)
        Calculadora.setMinimumSize(QtCore.QSize(419, 290))
        self.centralwidget = QtGui.QWidget(Calculadora)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout_3 = QtGui.QGridLayout(self.centralwidget)
        self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
        self.txtCalculo = QtGui.QLineEdit(self.centralwidget)
        self.txtCalculo.setMinimumSize(QtCore.QSize(401, 41))
        self.txtCalculo.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.txtCalculo.setObjectName(_fromUtf8("txtCalculo"))
        self.gridLayout_3.addWidget(self.txtCalculo, 0, 0, 1, 2)
        self.btnLimpar = QtGui.QPushButton(self.centralwidget)
        self.btnLimpar.setMinimumSize(QtCore.QSize(61, 41))
        self.btnLimpar.setMaximumSize(QtCore.QSize(120, 16777215))
        self.btnLimpar.setObjectName(_fromUtf8("btnLimpar"))
        self.gridLayout_3.addWidget(self.btnLimpar, 2, 0, 1, 1)
        self.gridLayout = QtGui.QGridLayout()
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.btn7 = QtGui.QPushButton(self.centralwidget)
        self.btn7.setMinimumSize(QtCore.QSize(61, 41))
        self.btn7.setObjectName(_fromUtf8("btn7"))
        self.btnNumeros = QtGui.QButtonGroup(Calculadora)
        self.btnNumeros.setObjectName(_fromUtf8("btnNumeros"))
        self.btnNumeros.addButton(self.btn7)
        self.gridLayout.addWidget(self.btn7, 0, 0, 1, 1)
        self.btn8 = QtGui.QPushButton(self.centralwidget)
        self.btn8.setMinimumSize(QtCore.QSize(61, 41))
        self.btn8.setObjectName(_fromUtf8("btn8"))
        self.btnNumeros.addButton(self.btn8)
        self.gridLayout.addWidget(self.btn8, 0, 1, 1, 1)
        self.btn9 = QtGui.QPushButton(self.centralwidget)
        self.btn9.setMinimumSize(QtCore.QSize(61, 41))
        self.btn9.setObjectName(_fromUtf8("btn9"))
        self.btnNumeros.addButton(self.btn9)
        self.gridLayout.addWidget(self.btn9, 0, 2, 1, 1)
        self.btn4 = QtGui.QPushButton(self.centralwidget)
        self.btn4.setMinimumSize(QtCore.QSize(61, 41))
        self.btn4.setObjectName(_fromUtf8("btn4"))
        self.btnNumeros.addButton(self.btn4)
        self.gridLayout.addWidget(self.btn4, 1, 0, 1, 1)
        self.btn5 = QtGui.QPushButton(self.centralwidget)
        self.btn5.setMinimumSize(QtCore.QSize(61, 41))
        self.btn5.setObjectName(_fromUtf8("btn5"))
        self.btnNumeros.addButton(self.btn5)
        self.gridLayout.addWidget(self.btn5, 1, 1, 1, 1)
        self.btn6 = QtGui.QPushButton(self.centralwidget)
        self.btn6.setMinimumSize(QtCore.QSize(61, 41))
        self.btn6.setObjectName(_fromUtf8("btn6"))
        self.btnNumeros.addButton(self.btn6)
        self.gridLayout.addWidget(self.btn6, 1, 2, 1, 1)
        self.btn1 = QtGui.QPushButton(self.centralwidget)
        self.btn1.setMinimumSize(QtCore.QSize(61, 41))
        self.btn1.setObjectName(_fromUtf8("btn1"))
        self.btnNumeros.addButton(self.btn1)
        self.gridLayout.addWidget(self.btn1, 2, 0, 1, 1)
        self.btn2 = QtGui.QPushButton(self.centralwidget)
        self.btn2.setMinimumSize(QtCore.QSize(61, 41))
        self.btn2.setObjectName(_fromUtf8("btn2"))
        self.btnNumeros.addButton(self.btn2)
        self.gridLayout.addWidget(self.btn2, 2, 1, 1, 1)
        self.btn3 = QtGui.QPushButton(self.centralwidget)
        self.btn3.setMinimumSize(QtCore.QSize(61, 41))
        self.btn3.setObjectName(_fromUtf8("btn3"))
        self.btnNumeros.addButton(self.btn3)
        self.gridLayout.addWidget(self.btn3, 2, 2, 1, 1)
        self.btnNegativo = QtGui.QPushButton(self.centralwidget)
        self.btnNegativo.setMinimumSize(QtCore.QSize(61, 41))
        self.btnNegativo.setObjectName(_fromUtf8("btnNegativo"))
        self.gridLayout.addWidget(self.btnNegativo, 3, 0, 1, 1)
        self.btn0 = QtGui.QPushButton(self.centralwidget)
        self.btn0.setMinimumSize(QtCore.QSize(61, 41))
        self.btn0.setObjectName(_fromUtf8("btn0"))
        self.btnNumeros.addButton(self.btn0)
        self.gridLayout.addWidget(self.btn0, 3, 1, 1, 1)
        self.btnPonto = QtGui.QPushButton(self.centralwidget)
        self.btnPonto.setMinimumSize(QtCore.QSize(61, 41))
        self.btnPonto.setObjectName(_fromUtf8("btnPonto"))
        self.btnNumeros.addButton(self.btnPonto)
        self.gridLayout.addWidget(self.btnPonto, 3, 2, 1, 1)
        self.gridLayout_3.addLayout(self.gridLayout, 3, 0, 1, 1)
        self.gridLayout_2 = QtGui.QGridLayout()
        self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
        self.btnDiv = QtGui.QPushButton(self.centralwidget)
        self.btnDiv.setMinimumSize(QtCore.QSize(61, 41))
        self.btnDiv.setObjectName(_fromUtf8("btnDiv"))
        self.btnNumeros.addButton(self.btnDiv)
        self.gridLayout_2.addWidget(self.btnDiv, 0, 0, 1, 1)
        self.btnMult = QtGui.QPushButton(self.centralwidget)
        self.btnMult.setMinimumSize(QtCore.QSize(61, 41))
        self.btnMult.setObjectName(_fromUtf8("btnMult"))
        self.btnNumeros.addButton(self.btnMult)
        self.gridLayout_2.addWidget(self.btnMult, 1, 0, 1, 1)
        self.btnMenos = QtGui.QPushButton(self.centralwidget)
        self.btnMenos.setMinimumSize(QtCore.QSize(61, 41))
        self.btnMenos.setObjectName(_fromUtf8("btnMenos"))
        self.btnNumeros.addButton(self.btnMenos)
        self.gridLayout_2.addWidget(self.btnMenos, 2, 0, 1, 1)
        self.btnMais = QtGui.QPushButton(self.centralwidget)
        self.btnMais.setMinimumSize(QtCore.QSize(61, 41))
        self.btnMais.setObjectName(_fromUtf8("btnMais"))
        self.btnNumeros.addButton(self.btnMais)
        self.gridLayout_2.addWidget(self.btnMais, 3, 0, 1, 1)
        self.btnIgual = QtGui.QPushButton(self.centralwidget)
        self.btnIgual.setMinimumSize(QtCore.QSize(61, 41))
        self.btnIgual.setObjectName(_fromUtf8("btnIgual"))
        self.gridLayout_2.addWidget(self.btnIgual, 3, 2, 1, 1)
        self.btnMemoriaNegativa = QtGui.QPushButton(self.centralwidget)
        self.btnMemoriaNegativa.setMinimumSize(QtCore.QSize(61, 41))
        self.btnMemoriaNegativa.setObjectName(_fromUtf8("btnMemoriaNegativa"))
        self.gridLayout_2.addWidget(self.btnMemoriaNegativa, 2, 2, 1, 1)
        self.btnMemoriaPositiva = QtGui.QPushButton(self.centralwidget)
        self.btnMemoriaPositiva.setMinimumSize(QtCore.QSize(61, 41))
        self.btnMemoriaPositiva.setObjectName(_fromUtf8("btnMemoriaPositiva"))
        self.gridLayout_2.addWidget(self.btnMemoriaPositiva, 1, 2, 1, 1)
        self.btnLimparMemoria = QtGui.QPushButton(self.centralwidget)
        self.btnLimparMemoria.setMinimumSize(QtCore.QSize(61, 41))
        self.btnLimparMemoria.setObjectName(_fromUtf8("btnLimparMemoria"))
        self.gridLayout_2.addWidget(self.btnLimparMemoria, 0, 2, 1, 1)
        self.gridLayout_3.addLayout(self.gridLayout_2, 3, 1, 1, 1)
        self.lblMensagem = QtGui.QLabel(self.centralwidget)
        self.lblMensagem.setText(_fromUtf8(""))
        self.lblMensagem.setObjectName(_fromUtf8("lblMensagem"))
        self.gridLayout_3.addWidget(self.lblMensagem, 2, 1, 1, 1)
        Calculadora.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(Calculadora)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 419, 25))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menu_Arquivo = QtGui.QMenu(self.menubar)
        self.menu_Arquivo.setObjectName(_fromUtf8("menu_Arquivo"))
        Calculadora.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(Calculadora)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        Calculadora.setStatusBar(self.statusbar)
        self.actionSair = QtGui.QAction(Calculadora)
        self.actionSair.setObjectName(_fromUtf8("actionSair"))
        self.menu_Arquivo.addAction(self.actionSair)
        self.menubar.addAction(self.menu_Arquivo.menuAction())

        self.retranslateUi(Calculadora)
        QtCore.QObject.connect(self.btnLimpar, QtCore.SIGNAL(_fromUtf8("clicked()")), self.txtCalculo.clear)
        QtCore.QMetaObject.connectSlotsByName(Calculadora)

    def retranslateUi(self, Calculadora):
        Calculadora.setWindowTitle(QtGui.QApplication.translate("Calculadora", "Calculadora Simples", None, QtGui.QApplication.UnicodeUTF8))
        self.btnLimpar.setText(QtGui.QApplication.translate("Calculadora", "&C", None, QtGui.QApplication.UnicodeUTF8))
        self.btn7.setText(QtGui.QApplication.translate("Calculadora", "7", None, QtGui.QApplication.UnicodeUTF8))
        self.btn8.setText(QtGui.QApplication.translate("Calculadora", "8", None, QtGui.QApplication.UnicodeUTF8))
        self.btn9.setText(QtGui.QApplication.translate("Calculadora", "9", None, QtGui.QApplication.UnicodeUTF8))
        self.btn4.setText(QtGui.QApplication.translate("Calculadora", "4", None, QtGui.QApplication.UnicodeUTF8))
        self.btn5.setText(QtGui.QApplication.translate("Calculadora", "5", None, QtGui.QApplication.UnicodeUTF8))
        self.btn6.setText(QtGui.QApplication.translate("Calculadora", "6", None, QtGui.QApplication.UnicodeUTF8))
        self.btn1.setText(QtGui.QApplication.translate("Calculadora", "1", None, QtGui.QApplication.UnicodeUTF8))
        self.btn2.setText(QtGui.QApplication.translate("Calculadora", "2", None, QtGui.QApplication.UnicodeUTF8))
        self.btn3.setText(QtGui.QApplication.translate("Calculadora", "3", None, QtGui.QApplication.UnicodeUTF8))
        self.btnNegativo.setText(QtGui.QApplication.translate("Calculadora", "+/-", None, QtGui.QApplication.UnicodeUTF8))
        self.btn0.setText(QtGui.QApplication.translate("Calculadora", "0", None, QtGui.QApplication.UnicodeUTF8))
        self.btnPonto.setText(QtGui.QApplication.translate("Calculadora", ".", None, QtGui.QApplication.UnicodeUTF8))
        self.btnDiv.setText(QtGui.QApplication.translate("Calculadora", "/", None, QtGui.QApplication.UnicodeUTF8))
        self.btnMult.setText(QtGui.QApplication.translate("Calculadora", "*", None, QtGui.QApplication.UnicodeUTF8))
        self.btnMenos.setText(QtGui.QApplication.translate("Calculadora", "-", None, QtGui.QApplication.UnicodeUTF8))
        self.btnMais.setText(QtGui.QApplication.translate("Calculadora", "+", None, QtGui.QApplication.UnicodeUTF8))
        self.btnIgual.setText(QtGui.QApplication.translate("Calculadora", "=", None, QtGui.QApplication.UnicodeUTF8))
        self.btnMemoriaNegativa.setText(QtGui.QApplication.translate("Calculadora", "M-", None, QtGui.QApplication.UnicodeUTF8))
        self.btnMemoriaPositiva.setText(QtGui.QApplication.translate("Calculadora", "M+", None, QtGui.QApplication.UnicodeUTF8))
        self.btnLimparMemoria.setText(QtGui.QApplication.translate("Calculadora", "MC", None, QtGui.QApplication.UnicodeUTF8))
        self.menu_Arquivo.setTitle(QtGui.QApplication.translate("Calculadora", "&Arquivo", None, QtGui.QApplication.UnicodeUTF8))
        self.actionSair.setText(QtGui.QApplication.translate("Calculadora", "Sair", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Calculadora = QtGui.QMainWindow()
    ui = Ui_Calculadora()
    ui.setupUi(Calculadora)
    Calculadora.show()
    sys.exit(app.exec_())


As diferenças são poucas porque o programa é pequeno, porém em programas maiores onde adicionamos objetos como:
QStringList e QString constantemente temos muitos problemas porque no PyQt para python3 os métodos ficarão diferentes por exemplo, o método QString para Strings maiúsculas é .toUpper() e para strings regulares do python é simplesmente .upper().

Dessa forma usando simplesmente a gambiarra que eu citei acima não irá funcionar porque quando invocarmos os métodos do QString eles não estarão presentes, felizmente existe no Python3 uma biblioteca que resolve isso pra nós, a sip, exemplo:


import sip

sip.setapi('QString', 1)

from PyQt4 import QtCore

Esse método funciona bem, no entanto quando temos funções que retornam QString's ou QStringList's do PyQt em Python2.x agora retornam objetos regulares do python e nem esse método e nem o anterior funcionam adequadamente, portanto é preciso realmente reescrever o código...

terça-feira, 30 de novembro de 2010

A morte do XP..... porque será que ela nunca chega?

Uma matéria muito bem escrita pelo Benito Piropo no fórum pcs fala da "morte do XP" que teima em resistir tempos e mais tempos no mercado, ele fala sobre os recursos do mesmo e muitas coisas, só que pra mim, a resistências das pessoas em sair do XP é muito óbvia e simples.... o sistema opercional pouco importa na vida delas.
A microsoft lançou dois sistemas operacionais excelentes após o XP voltado ao mercado de desktop, o Windows Vista e o Windows 7, o motivo do windows vista não ter ido adiante é simplesmente porque o XP cumpre muito bem o seu papel de sistema operacional e o Vista consumia uma quantidade grande de recursos pra época, o Windows 7 veio depois com o mesmo núcleo do Vista e ferramentas básicas, poderia ser simplesmente uma atualização, mas mercadologicamente não seria uma boa estratégia.
Mesmo assim,  o pessoal está migrando lentamente ao 7 simplesmente porque alguns programas não suportam mais o XP e porque o hardware moderno é mal aproveitado no XP também.
Opa! citei aplicativos lá em cima, agora vocês me entendem não? O Windows XP não é grande coisa em termos de sistema opercional, tem ferramentas nativas pífias e é uma brecha no quesito segurança, no entanto, se você precisa de um programa editor de fotos, ele está lá funcionando de forma maviosa no XP, precisa de um programa de comunicação, ele está lá, precisa gerenciar um bordel? pronto tem o programa que roda no XP...
A verdade é que nesses últimos anos o Windows XP angariou inúmeros aplicativos e as pessoas são bem servidas com ele, pra quê mudar então? porque eu iria migrar para uma interface diferenciada do que eu estou acostumado se tudo o que eu preciso está aqui?
O usuário quer apenas resolver o seu problema e o sistema operacional que ele vai usar pouco importa, o fato das pessoas não gostarem e linux ou qualquer outro sistema operacional diferente não é por causa da "facilidade de uso", pois sou requisitado desde montar uma rede ou formatar um computador até a instalar uma webcam ou antivírus, por mais que o sistema seja "fácil" as pessoas aprendem apenas aquilo que as interessa.
O sucesso inegável do Windows XP não está na sua robustez ou qualidade, está no fato que todos os aplicativos e provavelmente quase todo o hardware do qual você possa precisar irá funcionar e estará disponível pra ele, o sistema operacional para o usuário significa muito pouco ou nada, o que ele quer saber é se nesse computador ele poderá instalar o programa ou dispositivo que irá resolver o problema dele, e o XP em sua maioria atende bem esse propósito ele só vai morrer no dia em que termos programas apenas para o windows 7 ou vista e os computadores começarem a vir com dispositivos incompatíveis com ele.

quinta-feira, 21 de outubro de 2010

Exemplo de Classe em PyQt

Eu coloquei um exemplo anteriormente de código em PyQt e coloquei o link dos arquivos no 4shared, mas o link caiu e agora irei colocar mais um exemplo e vou comentar, e colocarei na tela mesmo.

#!/usr/bin/python
# -*- coding: utf-8 -*-
#importando as classes Qt abaixo
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore
#importando a interface criada no QtDesigner e transformada em classe
#python através do comando pyuic
from interfaces import ui_formCadastroBensImoveis
import datas_Brasileiras
from PyQt4.QtSql import *

'''
nesse sistema, os objetos checkbox alteram o estado dos dicionários com 
chaves com nomes homônimos aos checkbox, dessa forma, a alteração
das chaves do dicionário é transparente e ele fica gravado 
no banco de dados
'''
class FormCadastroBensImoveis(QMainWindow, 
ui_formCadastroBensImoveis.Ui_cadastroBensImoveis, datas_Brasileiras.Datas_cpf):
    '''
    Classe de cadastro de bens imóveis
    tudo que iniciar com txt são caixas de texto 
    da classe principal da interface gráfica do programa, 
    o que for iniciado com cmb são os objetos
    combobox e com radio os radiobox, checkbox são checkbox etc
    '''
    def __init__(self, parent=None, bancodados='', usuario='0000'):
        super(FormCadastroBensImoveis, self).__init__(parent)
        self.setupUi(self)
        self.dic = {}
        self.promptComando = QSqlQuery()
        self.usuario = usuario
        self.populaComboIgreja()
        self.validarCamposNumericos()
        self.fazerConexoes(True)
        
    def fazerConexoes(self, novo=True):
        '''
        Essa função faz as conexões dos objetos
        com os sinais e eventos, função de salvar não está aqui
        porque quando eu usar esse mesmo módulo como alteração
        eu irei usar o botão com a função alterar.
        a biblioteca partial permite criar funções 
        sob demanda desse modo eu economizo muitas linhas
        de código, as funções que são parecidas
        são criadas automaticamente
        '''
        from functools import partial
        from cadastros import sair
        self.connect(self.txtDataConstrucao, SIGNAL('editingFinished()')
        , self.validarData)
        #A função findChildren retorna uma lista com 
        #todos os objetos que responderem 
        #a um tipo ou função específica.
        lista = self.findChildren(QCheckBox)
        for objeto in lista:
            self.connect(objeto, SIGNAL('stateChanged(int)'),
            self.alt_diversos)
            self.dic[unicode(objeto.objectName(), 'utf-8')] = u"não"
        self.connect(self.txtDataConstrucao, SIGNAL("editingFinished ()"),
        self.validarData)
        if novo:
            self.connect(self.btnSalvar, SIGNAL('clicked()'),
            self.salvarDados)
        
    def validarCamposNumericos(self):
        '''Essa função valida os campos numéricos usando o objeto 
        QDoubleValidator, ele é muito bom e eficiente,
        tem muitas vantagens sobre a máscara, novamente,
        eu uso um laço for aqui para deixar a função
        mais compacta e pythoniana :)
        '''
        validarReal = QDoubleValidator(0, 99999, 0, self)
        validarReal.setDecimals(2)
        listaObj = [self.txtAreaAverbadaCasaOracao,
        self.txtAreaAverbadaTerreno,
        self.txtAreaRealCasaOracao, self.txtareaRealTerreno]
        for objeto in listaObj:
            objeto.setValidator(validarReal)
    
    def populaComboIgreja(self, tudo=False):
        '''
        Essa função popula o combo igreja
        '''
        comando = QString("SELECT cod_relatorio, nome_localidade FROM \
        bens_imoveis WHERE e_administracao LIKE 'sim'")
        if tudo:
            comando = QString("SELECT cod_localidade, nome_localidade \
            FROM bens_imoveis")
        self.cmbAdministracao.clear()
        self.promptComando.exec_(comando)
        listaAdministracao = QStringList('') 
        while self.promptComando.next() :
            listaAdministracao << self.promptComando.value(0).toString()\
             + " - " + self.promptComando.value(1).toString()
        self.cmbAdministracao.addItems(listaAdministracao)
        
    def alt_diversos(self):
        '''Essa função altera os valores das chaves do dicionário
        quando os objetos checkbox são clicados, a função sender()
        retorna o objeto que enviou o sinal, como as chaves
        do dicionário tem os nomes dos objetos então fica fácil
        usar essa função pois as chaves correspondentes
        a cada objeto são alteradas de acordo 
        com o nome do objeto que enviou o sinal.
        '''
        if self.sender().isChecked() == True:
            enviador = unicode(self.sender().objectName(),
            'utf-8')
            self.dic[enviador] = QString("sim")
        else:
            enviador = unicode(self.sender().objectName(),
            'utf-8')
            self.dic[enviador] = u"não"                                                       
    
    def salvarDados(self):
        ''' Essa é a função que salva os dados do formulário
        '''
        comando = QString("INSERT INTO bens_imoveis(cod_relatorio,\
        nome_localidade,administracao,registro_imovel,e_administracao,\
        alvara_construcao,alvara_funcionamento,CEI,CND,contrato,escritura,\
        habite_se,projeto_arquitetonico,projeto_eletrico,projeto_estrutural,\
        projeto_hidraulico,projeto_incendio,registro,data_construcao,\
        situacao,area_real_terreno,area_averbada_terreno,areaReal_casaOracao,\
        areaAverbada_casaOracao,justificativaDificuldade,usuario) \
        VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
        administracao = QString()
        if self.cmbAdministracao.currentText() != "":
            administracao = self.cmbAdministracao.currentText().split(" - ")[1]
        self.promptComando.prepare(comando)
        self.promptComando.bindValue(0, self.txtcodRelatorio.text())
        self.promptComando.bindValue(1, self.txtNomeLocalidade.text().replace(" - ", "-"))
        self.promptComando.bindValue(2, administracao)
        self.promptComando.bindValue(3, self.txtRegistroImovel.text())
        self.promptComando.bindValue(4, self.dic["checkAdministracao"])
        self.promptComando.bindValue(5, self.dic["checkAlvaraConstrucao"])
        self.promptComando.bindValue(6, self.dic["checkAlvaraFuncionamento"])
        self.promptComando.bindValue(7, self.dic["checkCEI"])
        self.promptComando.bindValue(8, self.dic["checkCND"])
        self.promptComando.bindValue(9, self.dic["checkContrato"])
        self.promptComando.bindValue(10, self.dic["checkEscritura"])
        self.promptComando.bindValue(11, self.dic["checkHabitese"])
        self.promptComando.bindValue(12, self.dic["checkProjArquitetonico"])
        self.promptComando.bindValue(13, self.dic["checkProjEletrico"])
        self.promptComando.bindValue(14, self.dic["checkProjEstrutural"])
        self.promptComando.bindValue(15, self.dic["checkProjHidraulico"])
        self.promptComando.bindValue(16, self.dic["checkProjIncendio"])
        self.promptComando.bindValue(17, self.dic["checkRegistro"])
        self.promptComando.bindValue(18, self.conversor_data(self.txtDataConstrucao.text()))
        self.promptComando.bindValue(19, self.cmbSituacao.currentText())
        self.promptComando.bindValue(20, self.txtareaRealTerreno.text().replace(",", "."))
        self.promptComando.bindValue(21, self.txtAreaAverbadaTerreno.text().replace(",", "."))
        self.promptComando.bindValue(22, self.txtAreaRealCasaOracao.text().replace(",", "."))
        self.promptComando.bindValue(23, self.txtAreaAverbadaCasaOracao.text().replace(",", "."))
        self.promptComando.bindValue(24, self.textoJustificativa.toPlainText())
        self.promptComando.bindValue(25, self.usuario)
        if self.promptComando.exec_():
            id = str(self.promptComando.lastInsertId().toInt()[0])
            QMessageBox.warning(self, unicode("O número do registro gravado foi: ",
            "utf-8"), unicode("Número de Registro: " + id, "utf-8"))
            self.limpar_dados()
        else:
            textoErro = self.promptComando.lastError().text()
            QMessageBox.warning(self, unicode("Falha ao Gravar o Registro",
            "utf-8"), unicode("O código do erro foi: " + textoErro, "utf-8"))
        
    
    def limpar_dados(self, tudo=True):
        '''
        Essa função limpa os campos do formulário, o interessante
        é que eu resolvi usar laços for associados com listas,
        achei dessa forma uma maneira mais "pythoniana" :)
        '''
        # Esse laço coloca todas as chaves do dicionário como "não"
        for chaves in self.dic.keys(): 
            self.dic[chaves] = u"não"
        lista = self.findChildren(QLineEdit)
        #Esse laço pega a lista anterior de objetos texto e coloca 
        #em todos o texto vazio
        for objeto in lista: 
            objeto.setText('')
        # Essa lista pega os objetos "checkbox" e o laço seguinte 
        #desmarca todos eles.
        lista = self.findChildren(QCheckBox)
        for objeto in lista: 
            objeto.setChecked(False)
        if tudo:
            self.cmbAdministracao.setCurrentIndex(0)
            self.cmbAdministracao.setFocus()
            self.populaComboIgreja()
        self.textoJustificativa.setPlainText("")
        self.cmbSituacao.setCurrentIndex(0)


Eu usei um programinha bacana chamado colored para criar o código html para colar aqui no blog, isso vai ajudar demais agora pois colocarei todos os códigos aqui.

sexta-feira, 8 de outubro de 2010

Nokia 5230 Como modem no linux entre outros

A cada dia que passa me acostumo mais e mais com o linux e suas facilidades, comprei essa semana um nokia 5230, preferi esse modelo por esses principais motivos:
  • Preço: Realmente convidativo, em diversos sites na internet o valor dele é de R$468,00 aqui na cidade estava esse valor também, porém essa semana subiu, só encontrei um modelo de vitrine na TIMAX por R$528,00 depois de chorar muito consegui baixar para R$495,00, estou super satisfeito com o mesmo, como não preciso de câmera, Wifi o 3G e o GPS foram o diferencial.
  • Symbian: O symbian apesar de defasado ainda é uma boa pedida e tem muita coisa pra ele.
  • 3G: Como tenho uma boa câmera e um note para acesso wifi, ambos eram dispensáveis no aparelho.
  • GPS: O que eu posso dizer? é ótimo e muito bacana :D
A minha preocupação era o acesso 3G usando o mesmo como modem no linux, para o windows é simples, você instala o nokia pc suite e configura depois de instalar os drivers do aparelho, nem precisa dizer que o PC suite não tem versão para linux né?
Mesmo assim decidi arriscar, o custo benefício era excelente e mesmo porque navegar pelo aparelho é razoável, porém depois que eu coloquei o bicho no ubuntu não é que o network manager reconheceu tudo na hora e está funcionando redondo? Não precisei instalar nada e a configuração do network manager é transparente e só next > next > finish.
Se alguém pretende adquirir o mesmo e está receoso quanto ao uso no linux, pode comprar sem medo que é uma ótima pedida! Funciona tudo tranquilamente.
O único porém é que como ele não carrega via usb o carregador tem que ficar pendurado junto com o cabo usb, a velocidade que ele atinge é maior que o do W580i, aqui em montes claros o W580i chegava a 56Kbps no GPRS e o 5230 chega aos 147Kbps em média no EDGE.
Show de Bola! (principalmente a R$0,50 ao dia hehe)

sexta-feira, 17 de setembro de 2010

Infinity Web da TIM

Esse foi o plano mais incrível lançado por uma operadora que eu já vi, a TIM deu uma bola dentro e tanto dessa vez, porém apesar de tudo, o foco da TIM além da classe C é com certeza as lojas on line de aplicativos como a Android Store e Ovi Store da nokia.
Agora a pessoa poderá acessar do seu celular as lojas de aplicativos online e realizar a compra dos aplicativos sem se preocupar com a tarifação da internet.
A concorrência com certeza é a melhor coisa que existe para os consumidores, agora você pode usar os diversos serviços online que existem para os aparelhos celulares sem ver todo o seu crédito ir embora.

quinta-feira, 15 de julho de 2010

X11 Forwarding no Ubuntu 10.04

Estava a quebrar a cabeça com o X11 Forwarding no Ubuntu Server 10.04, porém vendo a buglist do ubuntu descobri a solução postada pelo usuário asaijo basta adicionar -4 na linha do /etc/default/ssh

no arquivo mude a linha de:

SSHD_OPTS=

para:

SSHD_OPTS=-4
isso faz com que o ssh-server use o IPv4.
depois reinicie o ssh-server:
# /etc/init.d/ssh restart