sábado, 20 de enero de 2018

Conclusiones sobre unik-qml-blogger

He estado en estas ultimas horas programando un modulo para unik. El modulo se llama unik-qml-blogger. Consiste en un conjunto de 4 archivos QML, el main.qml es el mas grande pero los demas son muy sencillos. Dichos archivos, una vez cargados por unik, permiten utilizar Blogger.com de una manera mas placentera al menos para mi asi lo es. Ahora mismo estoy escribiendo desde el.

Lo que quiero contar no es sobre el modulo que he mencionado. Lo que voy a decir aqui, en este texto, es cual es mi impresion o a cual conclusion he llegado con respecto al hecho de haber desarrollado ese modulo. Cada desafio que uno asume y se propone encarar, es una experiencia aparte y hay veces en que merece cierta mencion o por lo menos dejar constancia escrita sobre ello. Talves a alguien le resulte util.

Hace apenas unos pocos dias, creo que 2 semanas, venia haciendo muchas pruebas de unik. Cuando digo pruebas digo muchas, algo asi como 8 horas, 5 dias a la semana, haciendo 200 pruebas por dia, algo normal en este rubro. Decia que fue hace poco que unik lo notaba funcionando muy bien, en vez de encontrar errores o algun bug que frenara el proyecto, surgian nuevas ideas y nuevas caracteristicas para implementar y todo venia aplicandose a un buen ritmo.  De buenas a primeras me dije, pues tengo que utilizarlo! Si no lo utilizo, no sabre a ciencia cierta si unik va bien, si cumple con su finalidad o en que etapa de desarrollo esta el proyecto. Me decidi a crear un modulo para cargar en unik que sea algo mas ambicioso.

Ya habia creado algunos modulos pequeños que solo funcionaban a los fines de ser simples ejemplos para que unik comience a salir a escena. Luego de decidirme a utilizar unik de un modo mas intensivo, cual si fuese yo un usuario final, se me ocurrio terminar un modulo que ya venia programando en mis pequeños minutos libres. El modulo al que me refiero se denomina unik-qml-writer. Esta publicado en https://github.com/nextsigner/unik-qml-writer.

Retome la programacion de ese modulo con la intencion de dedicarle un mayor tiempo y con mayor calidad. A cada parte del codigo que tenia que modificar, corregir o crear, en cada momento, me senti comodo y cada vez mas entusiasmado. El año 2016 y 2017, yo venia ejerciendo la actividad con un alto grado de intensidad por momentos extrema. Siempre que me exijo, lo hago de manera consciente y por una buena razon, no me quejo pero el cuerpo o la cabeza aunque uno no lo quiera aceptar, si o si se recienten. Ese ciclo me habia desgastado un poco, ya estaba programando sin sentirme comodo. Corrigiendo unik-qml-writer comence a sentir de nuevo el placer de programar. Me percate de ello y decidi seguir a paso constante.

El modulo unik-qml-writer consiste basicamente en cargar en un WebEngineView de QML, un editor de texto online que yo utilizo mucho. No se en que momento, se me ocurrio que seria bueno que unik acceda al contenido de esos archivos, que vaya uno a saber en que rincon de la red estarian disponibles. El editor de texto online que yo estaba utilizando se llama Writer. Lo pueden utilizar en https://writer.bighugelabs.com/. Al parecer esta mas orientado a publicar los textos en PDF, compartirlos en Google Drive, Dropbox etc, pero no he tenido suerte o tiempo de verlos online como hace Blogger.com. Lo que si logre, fue algo que me parecio una genialidad! Pedirle al Writer de https://writer.bighugelabs.com/ que me descargue el texto con formato de codigo QML que estaba editando y mi modulo QML se encargaria de ejecutarlo en una nueva instancia de unik. Que enriedo! No?

Aclarando. En unik yo podia cargar el modulo unik-qml-writer, el mismo me permitia ejecutar en una nueva instancia de unik el codigo QML que se descargaba de la web visualizada en el WebEngineView. Cuando termine de programar el unik-qml-writer se me ocurrio comenzar a cargar todo tipo de paginas cuyas caracteristicas sean similares a Writer online o mejores. He probado como 15 paginas. Choque contra una pared al intentarlo con Google Drive Documents (mejor dicho lo hice, pero con ciertas limitaciones). Hasta que llegue a Blogger.com. Me parecio todo muy aceptable y comodo. Un buen candidato como para comenzar un nuevo modulo con un editor diferente.

Cuando comence a montar Blogger.com todo iba bien. Le asigne el nombre unik-qml-blogger y comenzaron a surgir las buenas sorpresas y una lluvia de ideas. Implemente un boton para hacer correr el codigo QML directamente desde el editor de texto de Blogger.com. Todo funciono con solo 10 lineas de codigo. Luego se me ocurrio que ejecutara el codigo QML desde el menu contextual del mouse en el WebEngineView, todo se pudo hacer programando tambien unas pocas lineas. Y asi, cada objetivo propuesto se podia ir resolviendo y aplicando sin mayores complicaciones.

En fin, unik-qml-blogger resulto ser un proyecto que me ha comformado mucho. Esta publicado en https://github.com/nextsigner/unik-qml-blogger. En estos momentos tiene muchas caracteristicas valorables e importantes a tener en cuenta. El tiempo dira si sera utilizado mucho o no. Lo que se ha logrado con pocas horas de desarrollo es algo que no existia, unik-qml-blogger funciona como un sencillo pero util IDE para Editar, Crear, Publicar y Probar codigo QML online.

Lo que mas me ha gustado de todo este desafio superado, es comprobar que unik esta resultando, sirve para un determinado fin y lo hace bien. A mi me ha servido, le he exigido y cualquier sistema operativo me ha respondido de manera correcta. Sin unik lo hubiese podido hacer igual, pero con un IDE de 2.3Gigas, unik me permitio lograrlo con su tamaño de 100Mb y la posibilidad de desarrollar y ejecutar modulos que tienen un tamaño de apenas 2Kb. Los motivos como para estar contento y comforme son muchos. El tiempo lo dira. Yo tengo mucha confianza y alegria, prueba de ello es que a pesar de lo cansado que estoy, tengo ganas de que comience otra jornada y ver cual de las 1000 ideas que unik me ha provocado, cual de ellas comienzo a desarrollar.

unik-qml-blogger run qml code with mouse contextual menu

You can run this examples into unik-qml-blogger!

Select any code segment and Press right mouse button

Run this example in mode 1

This mode make and run a main.qml file in a temp location. You can see this path in the Debug panel fron the unik-qml-blogger.

/*Start code*/
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow{
     id:app
     visible: true
     width:500
     height:300
     color: 'red'
     Text{
          text: 'This code is run from web!\nIts run in mode 1'
          anchors.centerIn: parent
     }
     Component.onCompleted: {         
          unik.log('App from Blogger!\nMode 1')
     }
}
/*End code*/

Run this example in mode 2

This mode make and run a main.qml in the first comment location. This path is appended with the path seted into the currentFolder button of unik-qml-blogger. This example run at currentFolder+'/'+exampleMode2/main.qml. . You can see this path in the Debug panel fron the unik-qml-blogger.

Note: The file name in this mode is always seted by first line comment. Will can be other file name. For example: //myFolder/Button.qml

/*Start code*/
//exampleMode2/main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow{
     id:app
     visible: true
     width:500
     height:300
     color: 'red'
     Text{
          text: 'This code is run from web!\nIts run in mode 2'
          anchors.centerIn: parent
     }
     Component.onCompleted: {       
          unik.log('App from Blogger!\nMode 2')
     }
}
/*End code*/

Run this example in mode 3

This mode make and run a main.qml file in a temp location. This mode not require the ApplicationWindow component. This mode will to add a full code for run the selected code. You can see this path and full code in the Debug panel fron the unik-qml-blogger.

/*Start code*/
          Text{
               text: 'This code is run from web!\nIts run in mode 3'
               anchors.centerIn: parent
               font.pixelSize: 40
               wrapMode: Text.WordWrap
          }
          Component.onCompleted: {      
               unik.log('App from Blogger!\nMode 3')
          }
     /*End code*/

unik-qml-blogger-manual

ToolBar

1) Play Button
     This button is used for run the QML/JavaScript code existent into the Blogger Text Editor. This button run call a function named compilar(). This action too you can execute with the keyboard combination Ctrl+R.

2) Home Button
     This button load the Blogger.com, this load the Post Edition Page. If you are not logged with you Google Account, the Blogger.com require authentication. This unik-qml-blogger have a WebEngineView, it is a modern WebView, a component of de Qt and QtQuick. This componente is very secure, its functionality is of type Engine Web Render V8 of Chromium and Google Chrome. All user data used is encrypted into your cache of the operative system. All this modules is running as a web browser conventional.

3) Go to Blog Button
     This button load the current blog in edition. Press this button for view the blog pages published.

4) E Color Button
     This button is used for change the background color of the Blogger text editor. This color are not change for the page published.

5) T Color Button
     This button is used for change the text color of the Blogger text editor. This color are not change for the page published.

6) Debug Viewer Button
     This button is used for see o not see the Debug panel.

Debug Panel

      This panel write the unik-qml-blogger std output and the news unik instances called for running a QML code example. All advice or errors notification can see into this debug panel.

Quick Codes Panel

     This panel is used for storing you QML codes or any text. Into the web page you can press rigth mouse button for run a contextual menu. Select the save code option for save the text selected into the Quick Code Panel.

     This panel have a seach textinput. When you clicked in a element of the Quick Code Panel, the text of this element is pasted into the web page editor.

viernes, 19 de enero de 2018

about unik-qml-blogger

Whas is?

unik-qml-blogger is a small qml project created by nextsigner for load into unik qml engine.

This project contain only 4 qml files published in https://github.com/nextsigner/unik-qml-blogger

All qmls files are load in unik qml engine created by nextsigner. When run unik with this qmls, unik run a WebEngineView for use el Google Blogger.com.

For what used?

With unik-qml-blogger you can run QML codes examples published in Blogger or other sites. The unik-qml-blogger have a GUI for to use as a Lite IDE for QML Exercices or for publish any functional QML codes in share mode.

More info: nextsigner@gmai.com
GitHub Project: https://github.com/nexsigner/unik-qml-blogger

about qt opensource

Qt OpenSource
unik is a application created with Qt Creator

Qt Creator provides a cross-platform, complete integrated development environment (IDE) for application developers to create applications for multiple desktop, embedded, and mobile device platforms, such as Android and iOS. It is available for Linux, macOS and Windows operating systems. For more information, see Supported Platforms.

This manual also describes features that are only available if you have the appropriate Qt license. For more information, see Qt Creator Commercial Features.

Copyright 2008-2017 The Qt Company Ltd. All rights reserved.

More info in Qt Web Site: https://qt.io/

unik-qml-blogger-help

miércoles, 17 de enero de 2018

Programar en QML - ¿Cuáles son sus ventajas?


Los que nos dedicamos a la Programaciòn, durante años hemos visto la evoluciòn de los diferentes lenguajes de programaciòn. Hemos tenido en su momento la plena seguridad de que los lenguajes de programaciòn iban a ir mejorando, cambiando, surgirìan nuevos. Llegarìa el momento en que ya no se prodrìan lograr lenguajes màs simples que conserven el potencial de desarrollo. La simplificación sería llevada a un extremo límite.

Ese tiempo es hoy. Antes no existìan ni QML, ni Go, ni Swift. Ahora estamos frente a un escenario nuevo. Hay màs opciones que antes. Algunas con caracterìsticas a tener en cuenta. Es cierto que no siempre los lenguajes son antagònicos o contrarios entre sì y en ocaciones hasta pueden incluirse en un mismo proyecto varios lenguajes o tecnologìas.

Estamos aquì para opinar sobre QML y cuàles son las ventajas y razones por las cuales muchos optamos por este lenguaje. En mi caso particular yo utilizo desde hace 5 años Qt, el IDE Qt Creator, con C++, desde hace 3 años  C++ con QML/JavaScript. Si bien lo que describirè a continuaciòn parece un texto copiado de otro sitio web, les garantizo que es mi opiniòn escrita letra por letra. Sè de lo que hablo y me refiero a ello con conocimiento de causa.

1) Permite crear aplicaciones múltiplataformas potentes, modernas y de ùltima generaciòn de manera ràpida y sencilla.

2) Al ser un lenguaje Declarativo nos permite maquetar interfaz gràficas con buena apariencia, fluida, animada y que aproveche al màximo el espacio de pantalla, todo esto solo maquetando como lo solíamos hacer en HTML.

3) Al ser un lenguaje Declarativo basado en JavaScript, podemos programar la lògica de la aplicaciòn con JavaScript con todas las ventajas que ello conlleva.

4) Una de las caracterìsticas màs importantes, QML, al pertenecer al Framework llamado QtQuick, siendo parte del Framework Qt, esto nos posibilita conectar nuestro còdigo QML/JavaScript con las librerìas C++ de Qt.

5) Con un solo proyecto, con solo programar còdigo en un solo proyecto, ya podemos distribuir la aplicaciòn para casi todos los sistemas operativos. Por ejemplo GNU/Linux, Android, Windows, Macos, iOS, QNX y otros.

6) Podemos cargar còdigo QML pràcticamente desde cualquier origen. Tal como lo hace la aplicaciòn, Unik QML Engine creada por nextsigner@gmail.com, podemos cargar còdigo QML/JavaScript en tiempo de ejecuciòn desde dentro del binario de la aplicaciòn, desde una carpeta local, desde una carpeta remota o desde otros orígenes tal es el caso de Unik QML Engine que carga còdigo QML desde unos paquetes con un formato llamado .UPK (Unik Package) en donde se encuentra el còdigo fuente QML encriptado.

7) Con QML/JavaScript podemos crear elementos dinàmicamente en tiempo de ejecuciòn. Podemos crear variables JavaScript de tipo objeto o elemento QML con las caracterìsticas necesarias para cada caso.

8) Su sintàxis está simplificada al màximo y es muy simple de comprender y utilizar. Es muy similar o màs fàcil aùn que JSON. Una vez que nos amigamos con la manera en la que se declaran los elementos, còmo se le asigna un valor a cada propiedad de cada elemento, en breve ya podemos avanzar con la realizaciòn y desarrollo de aplicaciònes muy contundentes.

9) Gran facilidad para modelar izar los proyectos. Tanto al momento de importar archivos con funciones JavaScript o reutilizar otros mòdulos o ítems utilizados en otras aplicaciones, todo se hace de manera sencilla y sin la menor complicaciòn.

10) Contamos con la posibilidad de distribuir aplicaciones bajo las licencias del OpenSource LGPL2, LGPL3 o Enterprise. Qt es propiedad de Digia.com y ofrece una gran variedad y tipos de licencias como para que tu elijas cuàl es la que mejor se ajusta a tus necesidades.

11) La Tecnologìa Qt, QtQuick, con los lenguajes C++, QML/JavaScript estàn siendo utilizadas por las compañías y empresas màs avanzadas en el àrea de la Electrònica, Inginierìa Informàtica e industria de la Tecnologìa Elèctromecànica. Por ejemplo Pannasonic, Mercedes Benz y otras.

Para màs informaciòn: https://qt.io
Si necesita asesoramiento puede solicitarlo a nextsigner@gmail.com
Podemos llegar a un acuerdo para colaborar mutuamente, si usted realiza una colaboraciòn puedo prestarle colaboraciòn.


Estoy utilizando Qt 5.9.1 OpenSource

Desde hace muchos años utilizo Qt. Estoy 100% conforme con todo lo que en él he podido desarrollar, aprender y proyectar. Sin duda alguna, es una de las mejores decisiones que he tomado en este rubro. Haber optado por Qt ha sido un paso adelante trás otro constantemente.

He tenido la oportunidad durante los últimos 2 años de utilizar una versión Qt Enterprise. En otra oportunidad contaré cuáles fueron para mí las ventajas y diferencias entre utilizar Qt Enterprise o Qt OpenSource.

Para utilizar Qt OpenSource hay que entender cómo se aplica y bajo qué términos la Licencia LGPL2 y la LGPL3. Básicamente, para que se entienda en que consisten dichas licencias y qué nos exigen dichas licencias para que podamos utilizar Qt OpenSource, debes considerar y cumplir los siguientes requisitos.

  1. Registrarte en www.qt.io
  2. Descargar Qt OpenSource.
  3. Hacer público, publicar como codigo libre el código fuente de tus aplicaciones desarrolladas en Qt OpenSource.
  4.  Hacer mención a Qt OpenSource en el menú "Acerca de" de tu aplicación.
  5. No utilizar librerías Qt compiladas de manera estática dentro de tu ejecutable. 

Siguiendo estas pautas puedes utilizar Qt OpenSource sin problemas.

Desde aquí te recomendamos ambas modalidades. Es muy positivo y representa un avance muy importante para uno mismo y para toda la comunidad de Desarrolladores de Software que utilicemos Qt OpenSource y publiquemos código para difundir la tecnología y entre todos aportemos más y más información y documentación a la red. También, dependiendo el caso, en determinada ocasión es conveniente obtener una licencia de Qt Enterprise que puedes pagar mensualmente por unos pocos dólares o anualmente.

En el extremo caso de tu proyecto o desarrollo implique que determinada marca o empresa no supere las ganancias de 100 mil dólares anuales, también se podría comprar una licencia perpetua por unos 4500 dólares. No sé cuál sería el costo si las ganancias superan dichos montos. No recomiendo en ninguno de los casos comprar una licencia perpetua ya que solo son para la versión del momento y se podría llegar a justificar en un marco de muchísima productividad e ingresos que justifiquen tamaña inversión.

Por todos estos motivos, yo recomiendo Qt OpenSource. Aquí tienes el enlace de descarga en donde puedes elegir que instalador de Qt OpenSource 5.9.1 necesitas para tu sistema operativo.

Descargar Qt OpenSource 5.9.1: https://download.qt.io/official_releases/qt/5.9/5.9.1/

Yo lo utilizo en GNU/Linux y Android para compilar aplicaciones en GCC,  en Windows con MinGW y Visual Studio 2015 y en Macos con CLANG_64.

martes, 16 de enero de 2018

unik-qml-blogger-v1

/*
Jaunary 2018
This file is created by nextsigner
This code is used for the unik qml engine system too created by nextsigner.
Please read the Readme.md from https://github.com/nextsigner/unik-qml-writer.git
Contact
    email: nextsigner@gmail.com
    whatsapps: +541138024370
*/
import QtQuick 2.7
import QtQuick.Controls 2.0
import Qt.labs.settings 1.0
import QtWebEngine 1.4
import uk 1.0
ApplicationWindow {
    id:app
    visible: true
    width: 1400
    height: 600
    visibility:"Maximized"
    title: 'unik-qml-writer'
    property string tool: ""
    property string urlEditor: 'https://www.blogger.com/'
    property var wvResult
    onToolChanged: {
        if(app.tool === "quickcode"){
            xQuickCode.state = "show"
        }else{
            xQuickCode.state = "hide"
        }
    }
    Settings{
        id: appSettings
        category: 'Configuration'
        property string bgColorEditor: 'black'
        property string txtColorEditor: 'white'
    }
    FontLoader {name: "FontAwesome";source: "qrc:/fontawesome-webfont.ttf";}
    UK{
        id:uk
    }
    Connections {
        target: unik
        onUkStdChanged: {
            console.log('Writer dice: '+unik.ukStd)
       }
    }
    WebEngineView{
        id: wv
        width: app.width-xTools.width
        height: app.height
        anchors.left: xTools.right
        url: app.urlEditor
        profile: defaultProfile
        focus: true
        property QtObject defaultProfile: WebEngineProfile {
            storageName: "Default"
            onDownloadRequested: {
                download.path=uk.getPath(2)+'/main.qml'
                download.accept();
                console.log(download.path)
            }
            onDownloadFinished: {
                var d=''+uk.getFile(uk.getPath(2)+'/main.qml', true)
                console.log('--------->'+d)
                var m0=d.split('\n')
                var l1 = ''+m0[0]
                var fileName = l1.substring(2,l1.length)
                console.log('Saving: '+fileName)
                var m1 = fileName.split('/')

                var folder = fileName.replace('/'+m1[m1.length-1], '')
                var l2 = ''+m0[1]
                //var cl = l2.substring(2,l2.length)
                uk.mkdir(folder)
                uk.setFile(fileName,d,true)
                var cl = '-folder '+folder

                var appPath
                if(Qt.platform.os==='windows'){
                    appPath = '"'+uk.getPath(1)+'/'+uk.getPath(0)+'"'
                    uk.setFile('H:/cl.txt',cl,true)
                }
                if(Qt.platform.os==='linux'){
                    //appPath = '"'+uk.getPath(1)+'/'+uk.getPath(0)+'"'
                    //appPath = '"'+uk.getPath(1)+'/'+uk.getPath(0)+'"'
                    appPath = '"'+appExec+'"'
                }
                //uk.setFile('H:/cl.txt', appPath+' '+cl,true)
                //uk.setFile('/home/nextsigner/Escritorio/fn.txt', fileName,true)
                //uk.setFile('/home/nextsigner/Escritorio/cl.txt', appPath+' '+cl,true)
                console.log('Running: '+appPath+' '+cl)
                uk.run(appPath+' '+cl, true)
            }
        }
        settings.javascriptCanOpenWindows: true
        settings.allowRunningInsecureContent: false
        //settings.hyperlinkAuditingEnabled:  true
        settings.javascriptCanAccessClipboard: true
        settings.localStorageEnabled: true
        settings.javascriptEnabled: true
        onNewViewRequested: {
            request.openIn(wv)
            request.accepted = true;
        }

        onContextMenuRequested: function(request) {
            request.accepted = true;
            contextMenu.x = request.x;
            contextMenu.y = request.y;
            contextMenu.visible = true
        }
        onUrlChanged: {
            console.log("Url: "+url)
        }        

        Shortcut {
            sequence: "Ctrl+Tab"
            onActivated: {                
                clipboard.setText("     ")                
                wv.focus = true
                wv.triggerWebAction(WebEngineView.Paste)                
            }
        }
        Shortcut {
            sequence: "Ctrl+R"
            onActivated: {
                compilar()
            }
        }
    }
    Menu {
        id: contextMenu
        MenuItem { id: ccs; text: "Compilar Còdigo Seleccionado"
            onTriggered:{
                //wv.triggerWebAction(WebEngineView.Copy)
                var js='\'\'+window.getSelection()'
                wv.runJavaScript(js, function(result) {
                    console.log('[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'+result);
                    compilarCS(result)
                });

            }
        }        
        MenuItem { text: "Guardar Còdigo"
            onTriggered:{
                wv.triggerWebAction(WebEngineView.Copy)
                guardarCodigo.visible = true
            }
        }
        MenuItem { text: "Atras"
            onTriggered:{
                wv.goBack()
            }
        }
        MenuItem { text: "Adelante"
            onTriggered:{
                wv.goForward()
            }
        }
        MenuItem { text: "Cortar"
            onTriggered:{
                wv.triggerWebAction(WebEngineView.Cut)
            }
        }
        MenuItem { text: "Copiar"
            onTriggered:{
                wv.triggerWebAction(WebEngineView.Copy)
                var js='\'\'+window.getSelection()'
                wv.runJavaScript(js, function(result) {
                    console.log(result);
                });

                //console.log(wv.ViewSource.toString())
            }
        }
        MenuItem {
            id: menuPegar
            text: "Pegar"
            onTriggered:{
                wv.triggerWebAction(WebEngineView.Paste)
            }
        }
    }

    Rectangle{
        id: xTools
        width: app.width*0.02
        height: app.height
        color: "#000"
        border.width: 1
        border.color: "white"
        Column{
            width: parent.width
            spacing:  width*0.5
            anchors.verticalCenter: parent.verticalCenter


            Boton{
                id: btnRun
                w:parent.width
                h: w
                t: "\uf04b"
                enabled: (''+wv.url).indexOf('blogger.com') !== -1
                opacity: enabled ? 1.0 : 0.5
                onClicking: {
                    if(app.urlEditor==='https://www.blogger.com/'){
                        compilar()
                    }else{
                        wv.runJavaScript('chooseExport(\'txt\', \'Download text file\'); exportDoc();', function(result) {
                            console.log(result);

                        })
                    }
                }
                Timer{
                    running: true
                    repeat: true
                    interval: 500
                    onTriggered: {
                        //btnRun.opacity = (''+wv.url).indexOf('blogger.com') !== -1 ? 1.0 : 0.5
                    }

                }


            }
            Boton{
                id:btnhome
                w:parent.width
                h: w
                t: '\uf015'
                onClicking: {
                    wv.url = 'https://blogger.com'
                }
            }
            Boton{
                id:btnBgColorEditor
                objectName: 'btnBGCTE'
                w:parent.width
                h: w
                t: 'E'
                b: appSettings.bgColorEditor
                c: appSettings.txtColorEditor
                onClicking: {
                    colorPicker.obj = btnBgColorEditor
                    //colorPicker.colorSeted = appSettings.bgColorEditor
                    colorPicker.visible = true
                }
            }
            Boton{
                id:btnTextColorEditor
                objectName: 'btnTXTCTE'
                w:parent.width
                h: w
                t: 'T'
                b: appSettings.bgColorEditor
                c: appSettings.txtColorEditor
                onClicking: {
                    colorPicker.obj = btnTextColorEditor
                    //colorPicker.colorSeted = appSettings.txtColorEditor
                    colorPicker.visible = true
                }
            }
            Boton{
                w:parent.width
                h: w
                t: "\uf121"
                onClicking: {
                    app.tool = app.tool === "quickcode" ? "" : "quickcode"
                }
            }
            Boton{
                w:parent.width
                h: w
                t: "\uf011"
                onClicking: {
                    Qt.quit()
                }
            }
        }
    }

    Rectangle{
        id: xQuickCode
        width: app.width*0.2
        height: app.height
        color: "#333"
        border.width: 1
        border.color: "white"
        state: app.tool === "quickcode" ? "show" : "hide"
        states:  [
            State {
                name: "hide"
                PropertyChanges {
                    target: xQuickCode
                    x: 0-xQuickCode.width
                }
            },
            State {
                name: "show"
                PropertyChanges {
                    target: xQuickCode
                    x: 0
                }
            }

        ]
        transitions: [
            Transition {
                from: "hide"
                to: "show"
                NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad; duration: 500 }
            },
            Transition {
                from: "show"
                to: "hide"
                NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad; duration: 250 }
            }
        ]
        Column{
            anchors.fill: parent
            Text {
                id: txtTitQC
                text: "QuickCode"
                font.pixelSize: app.width*0.01
                anchors.horizontalCenter: parent.horizontalCenter
                color: "white"
            }
            Rectangle{
                id: xSearch
                width: parent.width
                height: txtTitQC.contentHeight*1.4
                color: "#ccc"
                TextInput{
                    id: tiSearch
                    width: parent.width*0.98-btnSearch.w
                    height: parent.height*0.98
                    anchors.centerIn: parent
                    font.pixelSize: parent.height*0.9
                    text: "search"
                    anchors.left: parent.left
                    anchors.leftMargin: parent.height*0.02
                    onFocusChanged: {
                        selectAll()
                    }
                    onTextChanged: {
                        loadQC(text)
                    }
                }
                Boton{
                    id: btnSearch
                    w:parent.height*0.9
                    h: w
                    t: "\uf002"
                    anchors.right: parent.right
                    anchors.verticalCenter: parent.verticalCenter
                    onClicking: {
                        loadQC(tiSearch.text)
                    }
                }
            }
            Rectangle{
                width: parent.width
                height: parent.height-txtTitQC.contentHeight-xSearch.height
                color: "#ccc"
                border.width: 1
                border.color: "white"

                ListView{
                    id:listQC
                    width: parent.width*0.98
                    height: parent.height
                    anchors.centerIn: parent
                    clip: true
                    model: lmQC
                    delegate: delQC
                    spacing: 10
                    ListModel{
                        id: lmQC
                        function add(i, n, c, rc){
                            return {
                                cid: i,
                                nom: n,
                                code: c,
                                rcode: rc
                            }
                        }
                    }
                    Component{
                        id: delQC
                        Rectangle{
                            width: parent.width
                            height: labelNomQC.height+labelCodeQC.height
                            property string realCode: rcode
                            Text{
                                id: labelNomQC
                                text: nom+'\n'
                                font.pixelSize: parent.width*0.05
                                wrapMode: Text.WordWrap
                            }
                            Text{
                                id: labelCodeQC
                                text: code
                                font.pixelSize: parent.width*0.025
                                width: parent.width*0.98
                                anchors.horizontalCenter: parent.horizontalCenter
                                //textFormat: Text.RichText
                                wrapMode: Text.WordWrap
                                anchors.top: labelNomQC.bottom
                            }
                            MouseArea{
                                anchors.fill: parent
                                onClicked: {
                                    clipboard.setText(rcode)
                                    wv.triggerWebAction(WebEngineView.Paste)
                                }
                            }
                            Boton{
                                w:parent.width*0.04
                                h: w
                                t: "X"
                                anchors.right: parent.right
                                onClicking: {
                                    var sql = 'DELETE FROM quickcodes WHERE id='+cid
                                    unik.sqlQuery(sql, true)
                                    loadQC("")
                                }
                            }
                        }

                    }

                }

            }
        }
        Boton{
            w: txtTitQC.height
            h: w
            t:"X"
            anchors.right: parent.right
            onClicking: app.tool = ""
        }
    }

    ColorPicker{
        id:colorPicker;
        visible: false;
        property var obj
        onCurrentColorChanged: {
            if(obj.objectName==='btnBGCTE'){appSettings.bgColorEditor=currentColor}
            if(obj.objectName==='btnTXTCTE'){appSettings.txtColorEditor=currentColor}
        }
        onRejected: {
            if(obj.objectName==='btnBGCTE'){appSettings.bgColorEditor=prevcolor}
            if(obj.objectName==='btnTXTCTE'){appSettings.txtColorEditor=prevcolor}
        }
        onAccepted: {
            if(obj.objectName==='btnBGCTE'){appSettings.bgColorEditor=color}
            if(obj.objectName==='btnTXTCTE'){appSettings.txtColorEditor=color}
        }
    }

    GuardarCodigo{
        id: guardarCodigo
        visible:false
        onGuardandoComo: {
            var txt = ''+clipboard.getText();
            var  sql = 'INSERT INTO quickcodes(id, nom, qc)VALUES(NULL, \''+n+'\', \''+txt+'\')'
            uk.sqlQuery(sql, true)
            loadQC("")
            console.log(txt)
        }
    }
    Component.onCompleted:  {
        //bgcEditor = appSettings.bgColorEditor

        var sf = ((''+appsDir).replace('file:///', ''))+'/'+app.title+'.sqlite'
        var initSqlite = uk.sqliteInit(sf, true)
        var sql

        //Tabla quickcodes
        sql = 'CREATE TABLE IF NOT EXISTS quickcodes(
                       id INTEGER PRIMARY KEY AUTOINCREMENT,
                       nom TEXT,
                       qc NUMERIC
                        )'
        uk.sqlQuery(sql, true)
        //sql = 'DELETE FROM quickcodes'
        //uk.sqlQuery(sql, true)
        cleanBDQC()
        loadQC("")
    }
    Timer{
        id: ts
        running: true
        repeat: true
        interval: 250
        onTriggered: {
            setColorTextEditor()
            setColorDivs()
            setColorSpans()
            setStyle()
        }

    }    
    function setColorTextEditor(){
        wv.runJavaScript('document.getElementById("postingComposeBox").contentDocument.getElementsByTagName(\'p\').length', function(result) {
            //console.log("Cantindad de lineas: "+result)
            var js=''
            for(var i=0;i<result;i++){                
                js += 'document.getElementById("postingComposeBox").contentDocument.getElementsByTagName(\'p\')['+i+'].style.color="'+txtcEditor+'";'
            }
            wv.runJavaScript(js, function(result2) {
                //console.log("Result Styles Paragraph: "+result2)

            })

        })
    }
    function setColorDivs(){
        wv.runJavaScript('document.getElementsByTagName(\'div\').length', function(result) {
            //console.log("Cantindad de lineas: "+result)
            var js='function setColorDiv(d){if(d.className!==\'goog-palette-colorswatch\'){d.style.backgroundColor="#333333";d.style.color="#fff";}};'
            for(var i=0;i<result;i++){
                js += 'setColorDiv(document.getElementsByTagName(\'div\')['+i+']);'
            }
            wv.runJavaScript(js, function(result2) {
                //console.log("Result Styles Divs: "+result2)
            })

        })
    }
    function setColorSpans(){
        wv.runJavaScript('document.getElementsByTagName(\'span\').length', function(result) {
            //console.log("Cantindad de lineas: "+result)
            var js='function setColorDiv(d){if(d.className!==\'goog-palette-colorswatch\'){d.style.backgroundColor="#333333";d.style.color="#fff";}};'
            for(var i=0;i<result;i++){
                js += 'setColorDiv(document.getElementsByTagName(\'span\')['+i+']);'
            }
            wv.runJavaScript(js, function(result2) {
                //console.log("Result Styles Divs: "+result2)
            })

        })
    }
    function setStyle(){
        var bgColorTextAreaEditor = appSettings.bgColorEditor
        var txtColorTextAreaEditor = appSettings.txtColorEditor
        var bgColor = '#000000'
        var fsColor = '#ffffff'
        var js = 'document.getElementsByTagName(\'html\')[0].style.backgroundColor="'+bgColor+'";'
        js = 'document.getElementsByTagName(\'html\')[0].style.color="'+fsColor+'";'
        js += 'document.getElementsByTagName(\'body\')[0].style.backgroundColor="'+bgColor+'";'
        js += 'document.getElementById("postingComposeBox").contentDocument.getElementsByTagName(\'body\')[0].style.backgroundColor="'+bgColorTextAreaEditor+'";'
        js += 'document.getElementById("postingComposeBox").contentDocument.getElementsByTagName(\'body\')[0].style.color="'+txtColorTextAreaEditor+'";'
        wv.runJavaScript(js, function(result) {
            //console.log("Result Style: "+result)

        })

    }

    function compilarCS(res){
        console.log('Compilando código seleccionado...')
        var js = ''
        var d=''+res;
        console.log('--------->'+d)
        uk.setFile('H:/cdd.txt', d,true)        
        var r = new Date(Date.now())
        var fileName = ''+unik.getPath(2)+'/'+r.getTime()+'/main.qml'
        console.log('Saving: '+fileName)
        var m1 = fileName.split('/')
        var folder = fileName.replace('/'+m1[m1.length-1], '')        
        uk.mkdir(folder)
        uk.setFile(fileName,d,true)
        var cl = '-folder '+folder

        var appPath
        if(Qt.platform.os==='windows'){
            appPath = '"'+uk.getPath(1)+'/'+uk.getPath(0)+'"'
            uk.setFile('H:/cl.txt',cl,true)
        }
        if(Qt.platform.os==='linux'){            
            appPath = '"'+appExec+'"'
        }
        uk.setFile('H:/cl.txt', appPath+' '+cl,true)        
        console.log('Running: '+appPath+' '+cl)
        if(uk.fileExist(fileName)){
            uk.run(appPath+' '+cl, true)
        }else{

        }
    }
    function compilar(){
        console.log('Compilando...')
        var js = ''        
        js += 'document.getElementById("postingComposeBox").contentDocument.getElementsByTagName(\'body\')[0].innerHTML;'        
        wv.runJavaScript(js, function(result) {            
            var tagPre1 = '<'+'/pre>\n'
            var c1 = ''+result+'<br />'
            console.log('QML Trim: '+c1.replace(/<(?:.|\n)*?>/gm, ''))
            var c2 = c1.replace(/<[\/p]>/g, '')//encuentra inicio parrafo
            var c3 = c2.replace(/<\/[p]>/g, '\n')//encuentra fin parrafo
            var c4 = c3.replace(/<\/(pre)>/g, tagPre1)
            var c5 = c4.replace(/<[\/b][\/r] \/>/g, '\n')//encuentra < br / >
            var c6 = c5.replace(/<[\/b][\/r]>/g, '\n')//encuentra < br >
            var c7 = c6.replace(/(&nbsp);/g, ' ')//encuentra espacio html
            var c8 = c7.replace(/<(?:.|\n)*?>/gm, '')
            var c9 = c8.replace("p, li { white-space: pre-wrap; }", '')
            app.wvResult = c9
            console.log('QML: '+app.wvResult)
            var m0=c9.split('\n')
            var l1 = ''
            for(var i=0;i<m0.length;i++){
                var l = ''+m0[i]
                if(l.substring(0,2)==='//'){
                    l1 = ''+m0[i]
                    break;
                }
            }

            var fileName = l1.substring(2,l1.length)
            console.log('Saving: '+fileName)
            var m1 = fileName.split('/')

            var folder = fileName.replace('/'+m1[m1.length-1], '')
            var l2 = ''+m0[1]
            //var cl = l2.substring(2,l2.length)
            uk.mkdir(folder)
            uk.setFile(fileName,app.wvResult,true)
            var cl = '-folder '+folder

            var appPath
            if(Qt.platform.os==='windows'){
                appPath = '"'+uk.getPath(1)+'/'+uk.getPath(0)+'"'
                uk.setFile('H:/cl.txt',cl,true)
            }
            if(Qt.platform.os==='linux'){                
                appPath = '"'+appExec+'"'
            }           
            console.log('Running: '+appPath+' '+cl)
            if(unik.fileExist(fileName)){
                uk.run(appPath+' '+cl, true)
            }else{

            }
        })
    }   
    function getVG(nom, valxdef){
        var sql = 'select val from varglob where nom=\''+nom+'\''
        var res = uk.getJsonSql('varglob', sql, 'sqlite', true)
        var json = JSON.parse(res)
        if(json['row0']!==undefined){
            return json['row0'].col0
        }else{
            sql = 'INSERT INTO varglob(id, nom, val)VALUES(NULL, \''+nom+'\', \''+valxdef+'\')'
            uk.sqlQuery(sql, true)
        }
        return ''
    }
    function cleanBDQC(){
        var sql = 'select id from quickcodes;'
        var c = ''+uk.getJsonSql('quickcodes', sql, 'sqlite', true)
        var j = JSON.parse(c)
        for(var i=0;i<Object.keys(j).length;i++){
            sql = 'select * from quickcodes where id=\''+j['row'+i].col0+'\';'
            var res = ''+uk.getJsonSql('quickcodes', sql, 'sqlite', true)
            var res2 = res.replace(/\r\n/g, '<br>')
            var res3 = res2.replace(/\t/g, '&#09;')
            var res4 = res3.replace(/\n/g, '<br>')
            var a
            try {
              a = JSON.parse(res4);
              console.log('QC id: '+j['row'+i].col0+' pass...')
            } catch (e) {
                sql = 'delete from quickcodes where id='+j['row'+i].c0+';'
                unik.sqlQuery(sql, true)
                console.log('QC id: '+j['row'+i].col0+' deleted...')
            }

        }
    }
    function loadQC(s){
        lmQC.clear()
        var sql = 'select * from quickcodes where nom like \'%'+s+'%\' or qc like \'%'+s+'%\''
        var res = ''+uk.getJsonSql('quickcodes', sql, 'sqlite', true)
        var res2 = res.replace(/\r\n/g, '<br>')
        var res3 = res2.replace(/\t/g, '&#09;')
        var res4 = res3.replace(/\n/g, '<br>')

        var json = JSON.parse(res4)
        for(var i=0; i < Object.keys(json).length; i++){
            var item = Object.keys(json)[i]
            var code = ''+json['row'+i].col2
            var rcode = ''+json['row'+i].col2
            var rcode1 = rcode.replace(/<br>/g, '\n')
            var rcode2 = rcode1.replace(/&#09;/g, '\t')
            var code1 = code.replace(/<br \/>/g, '<br>')
            var code2 = code1.replace(/&#09;/g, '--')
            lmQC.append(lmQC.add(json['row'+i].col0, json['row'+i].col1, code2, rcode2))
        }
    }
}

Entrada destacada

Para Desarrollo de Apps Android recomendamos Framework Qt

Como todos sabemos, este universo de la informàtica va en constante expansiòn, a veces a una velocidad que nos supera. Por momentos es difìc...