Spendi Meno Quanto Basta Parte 1

Posso usare Qt per controllare le mie spese personali?

Da dove iniziamo?

Da inizio anno il saldo delle mie entrate / uscite è negativo. Non che debba chiedere aiuto allo stato, ma alcune spese straordinarie hanno fatto saltare i conti e nel lungo periodo il trend non è sostenibile, pertanto devo fare qualcosa.

Leggendo vari siti di finanza personale e sviluppo personale, il primo suggerimento che ho trovato è di scrivere tutte le spese (tante) e le entrate (poche) e poi identificare quali sono le spese comprimibili. Già la pigrizia di dover registrare la spesa aiuta ad evitare spese superflue; ovviamente sto parlando del caffè al bar, o l’ultimo gadget su Amazon, non dei libri per la scuola dei figli.

Naturalmente preferirei trascrivere il tutto in una applicazione, non su tavolette di argilla, pertanto per prima cosa ho cercato una app.

Seguendo i suggerimenti vari ho fatto delle prove, ma nessuna app mi ha veramente soddisfatto. Non ho provato quelle a pagamento, perché capite bene che se devo spendere di più per risparmiare il progetto parte male.

E se lo facessi con Qt?

Ecco che a questo punto mi sono detto: ma perché non fare una mia applicazione usando Qt, in modo da farmela Divertente e Comoda Quanto Basta?

Analisi del progetto.

Servono 2 flussi, Ingressi e Uscite. Non sono in grado di capire le registrazioni fatte con partita doppia, nonostante il metodo risalga al 1494 e che a descriverlo per bene fu un frate italiano (leggetevi la pagina su Wikipedia). Io voglio sapere alla fine del mese quanto ho incassato e quanto ho speso, cosicché potrò raggruppare le spese e vedere cosa posso ridurre.

Per gli ingressi non serve molto, posso inserirli a mano, in genere è il solo stipendio, per le uscite, vorrei avere un meccanismo di supporto, che potrebbe essere:

  1. Raccolgo le immagini degli scontrini fiscali usando lo smartphone
  2. Faccio arrivare le immagini sul mio PC
  3. Carico le nuove immagini in una applicazione
  4. Salvo l’immagine nel database della applicazione, con data e descrizione della transazione
  5. Registro il movimento e se serve, lo scompongo in più movimenti con diverse categorie.
  6. Classifico la spesa in una categoria e sottocategoria predefinite

Serve un nome

Perché il progetto funzioni, devo avere voglia di alzarmi la mattina e usare la mia applicazione. Quindi anche il nome deve essere interessante! Che ne dite di SMQB? Ovvero Spendi Meno Quanto Basta.

Raccolta degli scontrini

Sarebbe bellissimo fare una app che sullo smartphone mi permette di fare delle foto, mettere dei commenti, salvarle nel cloud e poi accedere al cloud con il mio programma, eccetera eccetera. Ma vorrebbe dire iniziare nel 2030! Perchè non vedere se posso riutilizzare il lavoro di qualcun altro? E mentre ero in attesa dal barbiere (altra spesa che forse a tendere potrei comprimere!), ho avuto una illuminazione!

Posso usare l’app Google Drive, che permette di scattare una foto e salvarla in una cartella in rete. Se la cartella è tra i preferiti, selezionarla è velocissimo. Poi imposto la sincronizzazione della cartella, o di tutto il contenuto di Google Drive, sul mio pc, in modo che ogni volta che scatto una foto, la foto finisce nel mio computer.

Dopo aver creato la cartella: Scontrini sul mio Google Drive, la parte di raccolta delle immagini è risolta.

Ho scelto Google Drive perchè ho visto che è disponibile per macOS, per Windows e con applicazioni di terze parti anche per Linux, e poi perchè è la prima app con cui sono riuscito a fare delle foto senza riempire iCloud di immagini non correlate con i miei ricordi.

Non escludo che anche altre app possano fare lo stesso. Per favore aggiungete queste informazioni nei commenti.

Sprint 01: Creare l’applicazione

Ora prendiamo Qt ed iniziamo ad impostare la nostra applicazione. Si parte creando una Qt Widget Application che chiameremo SpendiMenoQuantoBasta. Poi nella mainwindows andiamo a mettere un tabWidget con 5 tab che chiameremo:

  • tabSetup (ovvero Impostazioni)
  • tabIncome (ovvero Entrate)
  • tabExpense (ovvero Uscite)
  • tabReport (ovvero Report)
  • tabAbout (ovvero Info)

Prima di compilare, impostiamo il parametro windowTitle della finestra principale come: “Spendi Meno Quanto Basta”.

Adattiamo il tabWidget alla finestra di dialogo con un layout verticale e compilando dovreste vedere:

Salvare le impostazioni

Gestiamo subito il salvataggio delle impostazioni della form principale creando 3 metodi protetti in mainwindow.h:

protected:    
    QString iniFilePath(); 
    void loadSettings();
    void saveSettigs();

Il metodo iniFilePath() è semplicissimo, e serve per calcolare il percorso in cui salvare le impostazioni. Io preferisco metterle in un file .ini a fianco dell’eseguibile (o del file .app nel caso macOS). Ecco il codice

 QString MainWindow::iniFilePath()
 {
     QFileInfo FI(qApp->applicationFilePath());
 #if defined Q_OS_MAC
     return FI.absolutePath() + "../../../../" + FI.baseName()
            + ".ini";
 #elif defined Q_OS_WIN
     return FI.absolutePath() + "/" + FI.baseName() + ".ini";
 #elif defined Q_OS_LINUX
     return FI.absolutePath() + "/" + FI.baseName() + ".ini";
 #endif
 }

Non dimenticate di aggiungere #include <QFileInfo> alla lista delle inclusioni. Basta selezionare QFileInfo e premere ALT+INVIO per avere l’opzione come suggerimento del tool di refactoring.

Provate a farlo, è fantastico!

Anche i metodi loadSettings() e saveSettings() si scrivono in poche righe. Per il momento salviamo la geometria della finestra di dialogo e l’indice corrente del controllo con i tab, poi li estenderemo anche alle altre impostazioni.

 void MainWindow::loadSettings()
 {
     QSettings settings(iniFilePath(), QSettings::IniFormat);
     restoreGeometry(settings.value("Geometry", saveGeometry())
                         .toByteArray());
     ui->tabWidget->setCurrentIndex(settings
                         .value("SelectedTab", 0).toInt());
 }
 
 void MainWindow::saveSettigs()
 {
     QSettings settings(iniFilePath(), QSettings::IniFormat);
     settings.setValue("Geometry", saveGeometry());
     settings.setValue("SelectedTab", 
                    ui->tabWidget->currentIndex());
 }

Anche in questo caso, non dimenticate di aggiungere #include <QSettings>, sempre usando ALT+INVIO per velocizzare l’operazione e non perdere il focus.

Ora invochiamo i metodi loadSettings() e saveSettings(), dopo aver costruito la user interface:

MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::MainWindow)
 {
     ui->setupUi(this);
     loadSettings();
 }

E prima di distruggere il tutto e chiudere il programma

MainWindow::~MainWindow()
 {
     saveSettigs();
     delete ui;
 }

Nella prossima puntata

Per questa puntata è tutto. Abbiamo solo scalfito la superficie, me ne rendo conto, ma abbiamo messo delle basi solide per fare la nostra applicazione Spendi Meno Quanto Basta. Seguitemi e ci divertiremo.

Attendo con ansia i vostri commenti e i vostri suggerimenti, per ora divertitevi a controllare che effettivamente le impostazioni vengano salvate e ripristinate quanto rilanciate il programma.

Nella prossima puntata vedremo come creare la form con le impostazioni.

Il primo database

Che lo crediate o no, i database so qui per restare

Mentre preparavo la presentazione del QtDay 2019, stavo anche leggendo il libro 21 Lezioni per il XXI secolo di Yuval Noah Harari, che è sempre una fortissima fonte di ispirazione.

E pensavo, ma davvero, nel 2019, un talk sui database? Sono cose vecchie, me ne occupavo nel 1990, al tempo si parlava di Modello Entità Relazione e di Tuple, ora sono argomenti vecchi!

Vecchi, ma quanto vecchi?

E qui mi è venuto in mente un tema che avevo trovato in uno dei libri di Yuval Noah Harari, ovvero che l’invenzione della scrittura serviva essenzialmente per registrare il pagamento di tributi e imposte.

La storia in realtà è più complessa, e non credo ci sia stato un giorno in cui la scrittura è stata inventata, ma credo piuttosto ad un processo per fasi, partendo dalle prime incisioni rupestri fino ad arrivare alle tavolette di argilla. Se siete interessati, al solito Wikipedia offre molti spunti: https://it.wikipedia.org/wiki/Storia_della_scrittura. E l’applicazione della scrittura è andata ben oltre la registrazione di entrate e uscite, arrivando a rendere immortali alcune opere dell’ingegno umano.

Ma l’idea che molti dei testi risalenti ai Sumeri, fossero in realtà delle registrazioni di transazioni, mi fece venire in mente questa slide per il QtDay, dove ho rappresentato una tavoletta di pietra risalente al 2500 A.C.

Durante il talk non ho avuto modo di approfondire l’argomento, ma vale la pena di entrare nel dettaglio.

La tavoletta appartiene alla collezione Schoyen, https://www.schoyencollection.com/23-religions/extinct-religions/23-1-sumerian/gift-adab-priestess-ms-3029 e rappresenta un elenco di donazioni fatte al potente dio Adab, in occasione della nomina della sacerdotessa suprema.

Questa immagine mi ha colpito perchè se guardiamo la tavoletta con le righe in verticale, fa venire in mente una tabella, un Excel diremmo oggi.

Se invece la giriamo e mettiamo le righe in orizzontale, come si vede in Wikipedia, mi ricorda gli esempi di database che si facevano con i primi computer, in cui il database aveva dei record a lunghezza fissa e veniva scritto in modo sequenziale su nastro magnetico.

Quindi se i database esistevano già nel 2500 a.C., vecchi o non vecchi, sono destinati a restare.

I database oggi

Se ci pensate oggi tutto funziona con un database, tutti i siti internet hanno un database, tutte le applicazioni hanno un database, anche per allenare l’intelligenza artificiale si usano database. Di fatto il testo che sto scrivendo viene salvato in un database, le banche non sono altro che enormi database.

Anzi si continua a ripetere che i dati saranno il petrolio dei prossimi anni, e chi potrà accedere ai dati potrà fare cose incredibili.

E dove li metti i dati? Non sulle tavolette di pietra, ma nei database.

Per oggi è tutto, vi aspetto la prossima settimana.

Un archivio di immagini

Nel 1998, per un amico archeologo ho creato un archivio di immagini, a supporto della sua attività. Essendo passati ormai più di 20 anni, mi ero completamente dimenticato del lavoro fatto.

Un giorno andai a trovarlo e con estrema sorpresa, notai che stava usando un database per gestire le immagini. Quando gli chiesi che applicativo fosse, mi disse: “Ma come, non ti ricordi? Me lo hai fatto tu!”

Ebbene sì era il mio vecchio database di immagini, che era passato indenne da Windows 3.11 a Windows 10, e da Access 2 a Access “non lo so a che versione siamo adesso…”

E nel tempo la base di immagini era cresciuta fino a gestire qualcosa vicino alle 100.000 immagini!

Indicizzare i percorsi

Non ci crederete, ma ho iniziato a fare reverse engineering sul mio lavoro. L’idea base era quella di mettere le immagini in cartelle e di salvare nel database solo il percorso dell’immagine, non tutta l’immagine.

Questo ha permesso di passare da fotocamere da 2 MPixel a fotocamere da 20 MPixel senza fare esplodere il database.

Tenete conto che Access memorizza il database in un file solo, pertanto, non sarebbe pensabile un database con 100.000 immagini. Se considerate 10MB a foto, fanno 1TB di file.

Per identificare le foto ho usato semplicemente un contatore, e nuovamente, dato che il filesystem di Windows non gradisce più di 3-5000 file nella stessa cartella, avevo creato un albero facendo cartelle da 1000 foto. Pertanto anche 100.000 foto alla fine si riducono ad una cartella con 100 sottocartelle.

Pre-calcolare le anteprime

Avevo fatto alcuni esperimenti, e avevo notato come fosse insopportabile aspettare che il controllo Immagine di Access ci mettesse dei secondi per visualizzare le immagini di anteprima. Allora pensai di pre-calcolarle, ovvero di creare un albero con tutte le immagini di anteprima già riscalate a 1024×768. Non contento di questo, mi spinsi oltre, pre-calcolando anche dei thumbnail a non ricordo quanto, ma circa 200×150 pixels. In questo modo era possibile incorporare il thumbnail nella finestra di dialogo, e poi con un click vedere l’anteprima a tutto schermo, che al tempo voleva dire 1024×768.

Quindi con 3 alberi indipendenti, uno per in thumbnail, uno per le anteprime, uno per le immagini originali, mi ero assicurato la scalabilità del sistema nel tempo.

L’idea mi era venuta leggendo un articolo sulle olimpiadi di Nagano, del 1998, in cui si spiegava come IBM fosse riuscita a garantire un elevatissimo numero di accessi al sito internet dell’organizzazione, pre-calcolando le pagine HTML al posto di fare una query su database per ogni accesso.

Visto gli strumenti e le conoscenze di cui disponevo al tempo, la procedura di archiviazione di ogni singola immagine era estremamente manuale, ma funziona bene da 20 anni, pertanto, perchè cambiarla?

Se lo rifacessi con Qt?

Per lavoro mi occupo di elaborazione di immagini, pertanto il tema di gestire grandi quantità di immagini mi è rimasto.

Per esigenze di lavoro mi sono trovato a creare un archivio di immagini, dimensionato per gestire 1 Milione di immagini.

Memore dell’esperienza di 20 anni fa, ho deciso di precalcolare le anteprime. Certo adesso le dimensioni sono diverse.

La risoluzione di riferimento di uno schermo è passata da 1024×768 a 1920×1080, quindi è intervenuto quasi un fattore 4, e quanto alla dimensione dei dischi, si è passati da 500 MB a 500 GB, almeno, questa è la dimensione del disco SSD del mio portatile.

Inoltre la velocità di lettura è passata da 5/10MB/s a 500MB/s, ma l’idea delle anteprime precalcolate è ancora valida, perché permette di sfogliare le immagini alla massima velocità possibile.

Il database? SQLite

Ora non uso più Access, ma SQLite, che come Access salva il database in un solo file, e come nel caso di Access è un database: “in proccess” ovvero vive all’interno della mia applicazione, non è un processo esterno. Questo rende la comunicazione estremamente veloce e la latenza bassa.

Se siete curiosi, guardate la mia presentazione al Qt Day 2019:

Archiviare le anteprime nel database

Ecco questo aspetto invece l’ho cambiato. Ora le anteprime le salvo sul database, perchè in questo modo riesco a visualizzarle molto più velocemente, e perché la dimensione del file del database non è più un problema. Anche se ho 1.000.000 di immagini, e per ogni immagine alloco 100kB, si tratta di un file da 100GB, impensabile 20 anni fa quando i dischi erano da 500 MB, accettabile oggi in un NAS da 15 TB (150 volte più grande)

Arrivano i NAS

Ecco, appunto, il problema è il NAS. Mentre 20 anni fa i NAS praticamente non esistevano (a livello personale), oggi un archivio di immagini per forza di cose deve stare su un NAS. Questo permette di avere anche 15 TB di spazio di archiviazione, a prezzi economici, condiviso tra più utenti.

Ma il NAS è collegato alla rete che per quanto sia veloce, introduce una latenza fastidiosa. Questa latenza si applica per ogni volta che accedo al filesystem, pertanto se ogni volta che voglio vedere una immagine, per quanto piccola devo aprire 4 o 5 cartelle, capite bene che il problema non sono i 10kB del thumbnail o i 90kB dell’anteprima, ma sono le 4 o 5 cartelle.

Stiamo parlando di 50/100 ms, che si notano in termini di velocità, e di reattività del sistema.

E se ci mettessimo la VPN? Anche in questo caso la situazione è la stessa, solo che le latenze sono maggiori.

Se invece l’immagine è nel database, il problema non esiste, dato che il file del database è già aperto, da qualche parte c’è una copia in cache, il calcolo della posizione della mia immagine è semplicemente un off-set nel file, la lettura viaggia alla velocità massima permessa dalla mia connessione.

Se rifacessi il lavoro oggi, come lo farei?

L’architettura con le anteprime precalcolate resta molto attuale, ma metterei le anteprime direttamente nel database.

E con Qt renderei automatica la creazione delle anteprime e tutto il processo di archiviazione.

Per non parlare dei dati EXIF e della possibilità di ricostruire la posizione geografica della foto.

Credo che sarebbe divertente farlo… Magari lo propongo al mio amico, che dite?

D’altronde Qt è il futuro!

Qt è il futuro

Eccoci qua, finalmente ho creato un sito dedicato a Qt 5 Quanto Basta.

Giusto per fare un poco di marketing, vi ricordo che il mio libro (Qt 5 Quanto Basta) è disponibile sia in formato cartaceo che in formato kindle su Amazon.it e su moltissimi altri siti e librerie.

Dopo la prima introduzione doverosa, vorrei iniziare questa avventura con un messaggio chiaro:

Io studio Qt perchè sono convinto che sia il futuro!

Ma cos’è Qt?

Qt è un framework per lo sviluppo di applicazioni… Un fra… che?

Facciamola semplice! Qt è un pacchetto formato da una libreria software che si chiama Qt appunto, e un applicativo che si chiama Qt Creator con il quale posso fare delle applicazioni.

Perchè è diverso da Visual Studio

Perchè con Visual Studio posso creare solo applicazioni per il sistema operativo Windows, mentre con Qt posso creare applicazioni per:

  • Windows
  • Linux
  • macOS
  • Dispositivi mobili iOS
  • Dispositivi Android
  • Dispositivi Embedded quali pannelli operatore, cruscotti di automobili.

E da Java?

Anche Java è pensato per funzionare su diverse piattaforme, usando un approccio diverso. Con Qt compilo per ogni piattaforma e quindi ho un comportamento identico alle altre applicazioni e prestazioni ottimizzate. Con Java, compilo un meta-linguaggio che poi viene interpretato da una macchina virtuale, e con svariate ottimizzazioni che nel tempo sono state implementate raggiunge prestazioni ragguardevoli, ma tendenzialmente usando molta più memoria e molta più CPU, e lasciando spesso l’impressione di non essere una applicazione nativa.

Si sì, ma non lo usa nessuno…

Appunto, questo è il motivo! È così potente che lo useranno tutti, e noi saremo i primi!

Questo era vero nel 2012, quando ho iniziato. Ormai è molto usato. Ad esempio quasi tutti i nuovi cruscotti sono fatti in Qt, a partire da quello di Tesla. O per esempio tutte le auto tedesche usano Qt.

Molti progetti open source usano Qt, come per esempio Video Lan, OBS, GNU Octave, KDE. Valutate voi stessi…

Ci sono anche software commerciali che usano Qt, come per esempio Autodesk Maya

E ci sono sistemi embedded! Un caso esemplare era Tom Tom, ma ormai credo di essere tra i pochi a sapere cosa è. Il decoder di Sky usa Qt.

Quali sono i vantaggi?

Il primo è che per impararlo non devo fare grossi investimenti, se non il tempo necessario a studiarlo. Infatti è disponibile una versione open source che è perfetta per imparare. Certo da qualche anno anche Visual Studio è disponibile come Community Edition, ma non è sempre stato così, e non è detto che lo sarà al prossimo cambio di amministratore delegato.

Il secondo, è che se sviluppo un progetto oggi, posso star sicuro che qualsiasi piattaforma la gente userà tra 10 anni (o anche 20), Qt potrà essere compilato per quella piattaforma, sia essa derivata da Linux, Apple, Microsoft o Android. Conoscete altre piattaforme? Bene state certi che quelli di Qt ci stanno già lavorando.

Concludendo

Fatevi un giro su www.qt.io per farvi una idea di che cosa sia Qt, scaricate il l’anteprima del mio libro da Amazon ed approfittate della calura per chiudervi in casa, condizionatore acceso, birra e… Qt.

Alla prossima settimana!