giovedì 4 aprile 2013

InstallJammer per Progetti Qt

Come indicato in questo post e' abbastanza semplice portare un programma Qt su una macchina diversa da quella di sviluppo in Windows

Si puo' migliorare creando un installer vero e proprio utilizzando il software InstallJammer, programma multipiattaforma per creare installer Qt

Attenzione: il progetto risulta dormiente o morto per cui non previsti sviluppi
Per Linux si puo' installare la versione 1.2.15 mentre per Windows e' necessario utilizzare la versione installjammer-1.2-snapshot.zip

Il programma e' piuttosto semplice



L'unica accortezza e' quella di includere nell'installer tutti i file indicati nel precedente post

martedì 2 aprile 2013

Settare il TabOrder in Qt

Per settare il tab order dei vari widget si deve aprire il menu Edit e selezionare Edit Tab Order
Il form cambiera' l'aspetto come in figura


Cliccando sui vari componenti si determinera' l'ordine con questi vengono attivati nel Tab Order.
C'e' da osservare che a differenza di Windows, in Qt il comportamento standard relativo al tasto Tab non e' quello di passare da un widget all'altro. Per ottenere questo comportamento si deve inserire la proprieta' tabChangesFocus su ogni componente



Configurare la TimeZone in Debian

UPDATE

Il metodo corretto e' digitare
dpkg-reconfigure tzdata

--------------------------------------------------

Per modificare la timezone della propria Linux Box si procede lanciando

tzselect


Per rendere la modifica permanente si deve modificare il proprio file .profile

Benchmark con Hardinfo

Di solito uso un paio di macchine, un Samsung N150 Plus ed un IBM X40, entrambi con una Debian Testing

E' da un po' di tempo che mi senbrava che il Centrino dell'X40 fosse piu' prestante del processore Atom N450 dell'N150 e per togliermi il dubbio ho provato ad usare hardinfo che si scarica semplicemente con

apt-get install hardinfo

il software, oltre a riconoscere l'hardware, permette di fare dei semplici benchmark del processore e di sotto riporto i risultati con il test BlowFish

 IBM X40

Samsung N150 Plus

E' abbastanza evidente che l'IBM, nonostante sia di circa 6 anni piu' vecchio, sia decisamente piu' veloce del Samsung. C'e' da dire che quando usci' l'X40 era un modello estremamente costoso e per professionisti mentre il Samsung e' da intendersi come un portatile per i poveri (infatti il primo lo ho comprato abbondantemente usato) e si puo' giustificare in parte la differenza ma gli anni a quanto pare sono passati invano

lunedì 1 aprile 2013

Errore su Grub Installer in MacPup 529

Cercando di riportare in vita una macchina obsoleta (e non volendo perdere troppo tempo con Debian) ho provato ad installare MacPup 529 con un Celeron 700 con circa 384 Mb di Ram

La distribuzione, fatta partire come LiveCd, mi ha ben impressionato riconoscendo tutto l'hardware compreso il SIS 630....i problemi sono nati quando ho deciso di passare all'installazione su disco fisso


Senza istruzioni e' quasi impossibile in quanto non e' prevista una procedura completa e decisamente non e' pensata per i principianti. Si devono effettuare tre passi distinti:
1) Partizionamento con GParted
2) Copia dei file con Puppy Universal Installer (nessun indice di progressione :<<<<)
3) Installazione Grub

Superati i due primi passi ci si accorge che, a causa di un bug, non e' possibile configurare Grub e si deve installare Grub4Dos come unica (e non documentata) soluzione

La distribuzione viene inoltre dichiarata compatibile con Ubuntu ma non vi e' traccia di apt-get quindi il supporto con Ubuntu e' quantomeno limitato

Anche la configurazione della scheda wireless (per quanto subito riconosciuta) non e' per niente intuitiva

In sostanza ho rimontato subito una Debian Squeeze che, pur facendo urlare per la prima ora di configurazione, funziona decisamente bene su una macchina obsoleta

Errore su Qt connectSlotsByName: No matching signal for ..

UPDATE
Ho risolto il problema e la soluzione come al solito e' sotto agli occhi.
In Windows avevo usato l'SDK completo (circa 770 Mb) scaricato dal sito di Qt con preinstallate le Qt 4.8.4 e con QtCreator 2.7
In Debian Wheezy avevo invece installato tutto mediante apt-get non vedendo che QtCreator era alla versione 2.5.Una volta aggiornato QtCreator anche su Linux tutto ha funzionato in modo corretto

---------------------------------------------------------

Spostando lo sviluppo di un progetto Qt da una macchina Windows ad una macchina Linux mi sono imbattuto in una cosa piuttosto curriosa



Il progetto si compila e funziona correttamente ma quando ho cercato di aggiungere una nuova entrata in QMenu al momento di compilare la menubar non risulta modificata ed viene segnalato l'errore

QMetaObject::connectSlotsByName: No matching signal for on_actionClassifica_triggered()

al momento non ho soluzioni per il problema

Zbar QRcode Scanner

Sulla base dell'esperienza di questo post sull'utilizzo della libreria zxing ha voluto provare la libreria ZBar piu' che altro per la necessita' di avere una maggiore velocita' di acquisizione

La principale differenza tra i due metodi e' che in Zxing si usa l'Intent ovvero si lancia una applicazione esterna e si attende il risultato mentre con ZBar si usa una libreria nativa inclusa nella propria applicazione


Il risultato e' una velocita' di elaborazione decisamente piu' veloce (ho dovuto creare una procedura apposita per impedire le acquisizione multiple su un stesso QrCode perche' il programma e' piu' veloce nel riconoscimento dello spostamento della mano)

Molto utile e' l'esempio compreso nella libreria che rende il tutto operativo in pochi minuti

Segue il codice di un programma che sto sviluppando per il riconoscimento dei pettorali delle corse podistiche
-----------------------------------------------------------------------

/*
 * Basic no frills app which integrates the ZBar barcode scanner with
 * the camera.
 * 
 * Created by lisah0 on 2012-02-24
 */
package net.sourceforge.zbar.android.CameraTest;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

import net.sourceforge.zbar.android.CameraTest.CameraPreview;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;

import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Button;
import android.widget.Toast;

import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Size;

import android.widget.TextView;

/* Import ZBar Class files */
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import net.sourceforge.zbar.Config;

public class CameraTestActivity extends Activity
{
    private Camera mCamera;
    private CameraPreview mPreview;
    private Handler autoFocusHandler;

    TextView scanText;
    Button scanButton;

    ImageScanner scanner;

    private boolean previewing = true;
private long partenza;
private String old_pettorale;
private String pettorale;
private TextView pett;
private EditText man;
private int contatore;


    static {
        System.loadLibrary("iconv");
    } 

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        contatore = 0;
        pettorale = "";
        
        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();

        /* Instance barcode scanner */
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        preview.addView(mPreview);
        scanText = (TextView)findViewById(R.id.scanText);
        pett = (TextView)findViewById(R.id.pettorale);
        man = (EditText)findViewById(R.id.editText1);

        //gestisce l'introduzione manuale del pettorale
        man.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
                    //Log.d("test","Premuto il tasto Done");
                pettorale = man.getText().toString();
                    long attuale = System.currentTimeMillis();
                    long x = (attuale-partenza) / 1000;
          long seconds = x % 60;
          x /= 60;
          long minutes = x % 60;
          x /= 60;
          long hours = x % 24;
          x /= 24;
          long days = x;
          contatore = contatore + 1;
          String ora_passaggio = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
          String race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
          String str3 = Integer.toString(contatore)+";"+pettorale + ";" + race_time +"\n";
          pett.setText(str3);
         
     
          
          playAlarm();
          scrivi(ora_passaggio+";"+str3);
          send_udp(str3);
                    man.setText("");
                    old_pettorale=pettorale;
                    
                    }

// TODO Auto-generated method stub
return false;
}
});
        
    }

    public void onPause() {
        super.onPause();
        releaseCamera();
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e){
        }
        return c;
    }

    private void releaseCamera() {
        if (mCamera != null) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    private Runnable doAutoFocus = new Runnable() {
            public void run() {
                if (previewing)
                    mCamera.autoFocus(autoFocusCB);
            }
        };

    PreviewCallback previewCb = new PreviewCallback() {
            private long attuale;
private String race_time;
private String ora_passaggio;
private String str3;
private String chk;

public void onPreviewFrame(byte[] data, Camera camera) {
                Camera.Parameters parameters = camera.getParameters();
                Size size = parameters.getPreviewSize();

                Image barcode = new Image(size.width, size.height, "Y800");
                barcode.setData(data);

                int result = scanner.scanImage(barcode);
                
                if ((result != 0) && (!start)) 
            {
            pett.setText("Partenza non effettuata");
            }
                
                if ((result != 0) && (start)) {
                    SymbolSet syms = scanner.getResults();
                    for (Symbol sym : syms) {
                        pettorale = sym.getData();        
                    }
                        attuale = System.currentTimeMillis();
                        if (!pettorale.equals(old_pettorale)) //evita le immissioni multiple di un pettorale
                       {
              long x = (attuale-partenza) / 1000;
          long seconds = x % 60;
          x /= 60;
          long minutes = x % 60;
          x /= 60;
          long hours = x % 24;
          x /= 24;
          long days = x;
          contatore = contatore + 1;
          chk ="Arrivo";
          race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
          ora_passaggio = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
          str3 =  Integer.toString(contatore)+";"+pettorale + ";" + race_time +"\n";
          pett.setText(str3);
          
          playAlarm();
          old_pettorale = pettorale;
          //pettorale = "";
          scrivi(ora_passaggio+";"+str3);
          send_udp(str3);
                   }
                        else
                        {// se il pettorale e' gia' stato battuto fai un suono differente
               //scanText.setText("Gia' acquisito");
                                               
                        }
                        
                        
        } //if result
            } // preview Frame
        }; //termina il callback
        
        
 private void playAlarm() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
 }     
        

 private void scrivi(String testo)
{
File sdcard = Environment.getExternalStorageDirectory();
    if (sdcard.canWrite()) 
     {
     File localFile2 = new File(sdcard, "passaggi.txt");
         FileWriter localFileWriter1 = null;
 try {
localFileWriter1 = new FileWriter(localFile2, true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 BufferedWriter localBufferedWriter = new BufferedWriter(localFileWriter1);
 try {
localBufferedWriter.write(testo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 try {
localBufferedWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 }// chiude la scrittura su file
 }


 private void send_udp(String testo)
 {
DatagramSocket socket = null;
//testo = "luca";
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    InetAddress serverIP = null;
try {
serverIP = InetAddress.getByName("192.168.0.100");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
     byte[] outData = testo.getBytes();
     DatagramPacket out = new DatagramPacket(outData,outData.length, serverIP,55000);
     try {
socket.send(out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
     socket.close();
 }

    public void onBackPressed() {
   new AlertDialog.Builder(this)
          .setMessage("Vuoi uscire?")
          .setCancelable(false)
          .setPositiveButton("Si", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
                   finish();
              }
          })
          .setNegativeButton("No", null)
          .show();
}

    // Mimic continuous auto-focusing
    AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
            public void onAutoFocus(boolean success, Camera camera) {
                autoFocusHandler.postDelayed(doAutoFocus, 1000);
            }
        };
private boolean start;
        
    @Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(1,1,0,"Partenza");
menu.add(1,2,1,"Annulla passaggio");
return true;
}
    
    public boolean onOptionsItemSelected(MenuItem item)
    {
    
switch(item.getItemId())
{
case 1:
if (!start) 
{
  start = true;
      partenza = System.currentTimeMillis();
      long x2 = (partenza) / 1000;
  long seconds2 = x2 % 60;
  x2 /= 60;
  long minutes2 = x2 % 60;
  x2 /= 60;
  long hours2 = x2 % 24;
  x2 /= 24;
  //long days = x;
      send_udp("Partenza   "+String.format("%02d:%02d:%02d", hours2,minutes2,seconds2));
          pett.setText("Partenza effettuata");
          scrivi("Partenza   "+String.format("%02d:%02d:%02d", hours2,minutes2,seconds2)+"\n");
          playAlarm();
}

else
{
Toast.makeText(this, "Partenza gia' effettuata",Toast.LENGTH_SHORT).show();
return false;
}


   Timer ti = new Timer();
   ti.scheduleAtFixedRate(new TimerTask() {
           public void run() {
            runOnUiThread(new Runnable() {
          private long attuale;
private String race_time;

@Override
          public void run() {
           //String tempo = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
           if (partenza > 0)
           {
            attuale = System.currentTimeMillis();
    long x = (attuale-partenza) / 1000;
    long seconds = x % 60;
    x /= 60;
    long minutes = x % 60;
    x /= 60;
    long hours = x % 24;
    x /= 24;
    //long days = x;
    race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
    scanText.setText(race_time);
           }
    }});}}, 0, 1000);
 //fa partire il cronometro della corsa
 partenza = System.currentTimeMillis();
   return true;
   
case 2:
send_udp("Annullato pettorale " + pettorale);
      pett.setText("Annullato pettorale " + pettorale);
      scrivi("Annullato pettorale " + pettorale+"\n");
      contatore = contatore - 1;
return true;

}

return false;
}
   
}

Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...