UserList - lato C++
Implementare il codice C++ di supporto alla gestione di una userList dinamica è un obiettivo complesso.
Quanto segue è riferito al codice, non ancora raffinato, collocato nel branch dinamicUserList e, in particolare, nei file AutoCompletion.cpp, | AutoCompletion.cpp e Main.qml.
Quest'ultimo, in particolare, è ad un punto di sviluppo del tutto primordiale, utile solamente a verificare la funzionalità dell'algoritmo lato C++.
Il primo aspetto da sottolineare è la necessità di mettere in interazione due strutture di dati indipendenti.
La grafica delle userList, infatti, è gestita, in Qt, da un vettore lineare chiamato QList. Ciascun elemento della QList è un puntatore a una classe USER, che contiene le informazioni essenziali proprie dell'utente (username, realname, uid, gid e via dicendo), corrispondente a un parsing del comando getpwent.
La ricerca per il completamento, invece, si sviluppa intorno ad un albero trie, essenziale per la gestione dell'algoritmo.
Gli elementi di un trie sono foglie, contenenti una lettera, due puntatori e un marcatore per la gestione delle ricerche in profondità (dfs).
typedef struct letter { char character; int mark { 0 }; letter* right { NULL }; letter* down { NULL }; } letter;
Per gestire gli effetti grafici, dopo ogni ricerca condotta lungo l'albero trie, è necessario individuare la classe USER corrispondente all'utente corrente. Procedere linearmente significherebbe vanificare del tutto (!!!) il vantaggio di avere usato il trie.
Cosa possiamo fare?
Forse, una buona soluzione può essere quella di rendere disponibile, alla fine di ogni ricerca lungo il trie, un campo contenente il puntatore alla classe USER corrispondente. Tecnicamente, questo si realizza modificando la foglia nel modo seguente:
typedef struct letter { char character; int mark { 0 }; letter* right { NULL }; letter* down { NULL }; UserPtr user { nullptr }; } letter;
Osserviamo ora come avviene l'inizializzazione della base, nella versione attuale del metodo initAutoCompletion:
- richiesta di un puntatore getpwent per definire l'utente corrente;
- chiamata del metodo addStringToTrie per inserire lo username del nuovo utente nell'albero dati;
- inserimento di tutte le lettere dello username corrente, fino a quella finale, tramite il metodo addLetterToTrie;
- costruzione, per il solo carattere di fine parola, di un elemento della classe USER, e trascrizione del puntatore nel campo user della foglia attuale;
- ripetizione del ciclo fino al termine degli utenti;
- ...
e la QList???
Abbiamo creato gli oggetti USER, ma non abbiamo costruito ancora la QList, necessaria per le chiamate QML.
- ...
- eseguiamo una 'dfs completa del trie;
- a fine lettura di ogni singolo username, preleviamo il campo user e incrementiamo la QList;
!!!
Il gioco è fatto. All'inserimento di ogni nuovo carattere, la QList viene svuotata e riempita nuovamente con gli esiti di una nuova nuova dfs, che in questo caso restituirà un sottoinsieme dei valori precedenti.
... dinamicamente.